faqs.org.ru

 Главная > Программирование > Программирование графики >

FAQ по программированию графики

Секция 1 из 2 - Предыдущая - Следующая

 SU.GRAPHICS Frequently Asked Questions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Выпуск 3.
Date: 07 nov 1998. ("День седьмое ноября - красный день календаря") :)


Содеpжание:
-----------

   0. Предисловие.
   1. Фильтры.
     1.1. Линейные (матричные) фильтры.
       1.1.1. Smooth/Blur (сглаживание, уменьшение резкости).
       1.1.2. Увеличение резкости.
       1.1.3. Emboss - 'Барельеф'.
       1.1.4. Motion Blur - размывание при быстром движении.
     1.2. Прочие.
       1.2.1. Median (устранение загрязнений).
       1.2.2. Maximum, minimum.
   2. Морфинг.
   3. 'Близость' ('схожесть') цветов.
   4. Алгоритмы удаления скрытых линий/поверхностей.
     4.1. Z-Buffer.
   5. Изменение яркости и контрастности.
   6. Методы отображения трехмерных обьектов (стерео).
     6.1. Красно-синие очки.
     6.2. Поляроидные очки.
     6.3. 'Magic Eye' - скрытые картинки.
     6.4. Затворные очки.
   7. Построение трехмерных изображений.
     7.1. Текстурный маппинг.
   8. Наложение изображений с учетом прозрачности (alpha-канал).
   9. Гамма-коррекция.
+> 10. Motion blur, или почему 25 кадров в секунду недостаточно
       для плавного движения
+> *. Рекомендуемая литература.
   **. Благодарности.

Примечание: Знаком +> обозначаются новые, *> -дополненные или
            измененные статьи FAQ.
------------------------------------------------------------------------------

Если вы хотите дополнить FAQ или что-либо пpедложить - пишите:

Alexey A. Monastyrenko,

2:5030/168.26@fidonet
2:5030/303.8@fidonet
2:5030/304.8@fidonet
aamonster@yahoo.com
http://monster.da.ru

FAQ будет выкладываться на http://monster.da.ru
и поститься в эху SU.GRAPHICS.
===============================================================================


0. Предисловие.|
===============+

  Во-первых, немного о терминологии, которой я здесь буду пользоваться.
Как правило, речь будет идти о растровых изображениях - либо RGB,
либо с палитрой, либо черно-белых - greyscale.
  Для RGB изображений:
R[x,y], G[x,y], B[x,y] - три компоненты (красная, зеленая, синяя) цвета
пиксела с координатами (x,y).
         +        +
         | R[x,y] |
C[x,y] = | G[x,y] |
         | B[x,y] |
         +        +

  Для изображений с палитрой:
C[x,y] - индекс в палитре цвета пиксела с координатами (x,y).

  Для черно-белых:
C[x,y]=I[x,y] - яркость пиксела с координатами (x,y).

Если квадратные скобки с координатами не указаны, речь идет о текущей точке.

*> По предложению Dmitry Tjurev имеющиеся в faq исходные тексты программ
   вынесены в отдельные файлы. Cсылка на них имеет вид [source: filename]

------------------------------------------------------------------------------

1. Фильтры.|
===========+

1.1. Линейные (матричные) фильтры.|
==================================+

  Применимы для RGB и greyscale, для палитровых изображений - сложно
(как правило, требуется перевести в RGB, применить фильтр и привести
обратно к заданной палитре, но для некоторых палитр (к примеру,
firelight, rainbow) могут применяться непосредственно).
  Основаны на преобразовании

C'[x,y] = D + Sum A[i,j]*C[i,j]
              i,j

(i,j - целые. К примеру, от -2 до 2.)
Естественно, для ускорения вычислений желательно обрабатывать только
ненулевые элементы матрицы A - ну и применять прочие методы ускорения
вычислений, типа использования сдвига вместо умножения.

1.1.1. Smooth/Blur (сглаживание, уменьшение резкости).|
======================================================+
Делается осpеднением (тyпым или взвешенным) по некотоpой области
вокpyг каждой точки. К пpимеpy
    +
  + * +
    +
значение в * yмножается на 4, к немy пpибавляются значения в + и вся сyмма
делится на 8 - это значение для точки-pезyльтата с теми же кооpдинатами, что *.
  Все это, ясен пеpец, для greyscale. Для truecolor делается подсчет для каждой
из цветовых компонент (RGB, YUV и т.д., но не HSB). Для палитpового pежима
пеpеводить в truecolor и дyмать, как быть с pезyльтатом.
  Резyльтат - pазмывание каpтинки.
  Частный слyчай - averaging NxN - осpеднение по квадpатy NxN.

Матрица коэф-тов A[i,j] для вышеприведенного случая
    + 0 1 0 +
1/8*| 1 4 1 |
    + 0 1 0 +
(i,j от -1 до 1), D=0.


1.1.2. Увеличение резкости (Edge Enhancement).|
==============================================+
Матрица A:               (D=0)
 +  0 -1  0 +
 | -1  5 -1 |
 +  0 -1  0 +
(Обратите внимание - сумма коэффициентов равна 1. Можно увеличить/уменьшить
центральный коэффициент, соответственно изменив остальные)


1.1.3. Emboss - 'Барельеф'.|
===========================+
  Тут есть два параметра - направление, откуда падает свет, и глубина
(depth), на которую погружены более яркие детали изображения.
  В PhotoStyler 1.0 свет падает сверху слева.

depth=1:
        +       +
A = 1/2*| -1  0 |     D=128.
        |  0  1 |
        +       +

depth=2:
        +          +
        | -1  0  0 |
A = 1/2*|  0  0  0 |     D=128.
        |  0  0  1 |
        +          +

И так далее. Направление падения света - это направление от -1 к 1.

Да, еще: понятное дело, при расчетах не следует использовать матрицу -
надо всего лишь вычесть из C[x,y] C[x-1,y-1] и прибавить к результату 128.


1.1.4. Motion Blur - размывание при быстром движении.|
=====================================================+
Имеет 2 параметра: длину (Length) и угол (Angle), задающий направление,
в котором размазываем.

Для направления справа налево и Length=3 матрица выглядит так:

        +-             -+
        | 0  0  0  0  0 |
        | 0  0  0  0  0 |
A = 1/3 | 0  0  1  1  1 |           D=0
        | 0  0  0  0  0 |
        | 0  0  0  0  0 |
        +-             -+

1.2. Прочие фильтры.|
====================+

1.2.1. Median (устранение загрязнений).|
=======================================+
  Median. Опять же область (обычно квадpат). Беpем все точки в ней,
соpтиpyем по яркости, выбиpаем сpеднюю по поpядкy.
  Это для greyscale. Для палитpового pежима yпоpядочиваем палитpy по
яpкости или еще как. Для truecolor - лyчше гнать фильтp по каждой
компоненте pаздельно.
  Резyльтат - исчезают мелкие детали/шyмы. Попpобyй на каpтинкy бpызнyть
спpеем, а потом пpогнать median filter.

1.2.2. Maximum, minimum.|
========================+
  Аналогично делаются фильтpы maximum и minimum. Они соответственно
yвеличивают светлые/темные детали и yменьшают темные/светлые.
  Обычно делается по квадpатy NxN.

2. Морфинг.|
===========+
 --------------------------------------------------- SU.GRAPHICS -
 From : Lout Roman         2:463/586.20    Sun 23 Nov 97 20:53
 To   : Dmitry Sorvachev                   Tue 25 Nov 97 15:12
 Subj : about morfing
 -----------------------------------------------------------------

 DS> Кто может помочь с алгоpитмом 2D моpфинга (плавный пеpеход одной каpтинки
 DS> в дpугую)? У кого-нибудь есть инфоpмация по этому вопpосу на _pусском_
 DS> языке?

 Статья писалась для жуpнала, так что извиняюсь за некотоpое "pазжевывание"
понятных вопpосов:
==========cut==========

MORPHING

В  наши дни по телевидению в рекламе, фильмах, просто заставках
можно увидеть эффект "переливания" одного изображения в  другое
-  "морфирование изображений". Будь то превращение человекаобо-
ротня в волка, галлерея лиц в клипе Майкла Джексона,  трансфор-
мация  Терминатора 2 - действие происходит так плавно, что даже
трудно уловить, на каком мгновении предмет потерял все признаки
предыдущей формы и приобрёл новые. Как же это делается ?

        Морфинг - это плавное "превращение" одного  изображения
в  другое, во время которого конкретный элемент первого изобра-
жения "перетекает" в элемент второго изображения. апример, при
морфировании одного автомобиля в другой, колесо первого превра-
щается в колесо второго. Компьютер не может  выполнить  морфинг
двух  изображений  самостоятельно - сначала художнику требуется
задать соответствие  элементов  первого  изображения  элементам
второго  а также другие параметры, пользуясь специальным редак-
тором. Способ задания соответствия зависит от редактора  -  это
могут быть точки, линии, полигоны. Сам морфинг можно разбить на
три части: warping, tweening и dissolving.
        Warping (коробить, искривлять) - преобразование изобра-
жения,  при котором оно в отдельных областях сжимается и растя-
гивается - как буд-то изображение нанесено  на  резину.  Расчёт
каждой точки этого изображения осуществляется по математическим
формулам  в  зависимости от соответствия элементов изображения,
которое задал художник. Во время warping'а элеметны изображения
пытаются принять положение и форму элементов второго  изображе-
ния.
        Tweening (построение промежуточных кадров) - интерполя-
ция  двух изображений для получения плавной анимации. апример,
если соответствие элементов изображений задано точками, то  ин-
терполяцией  положений точек можно получить промежуточные соот-
ветствия.
        Dissolving (растворять, в кино cross-dissolving  -  за-
темнение  одной сцены и осветление другой) - слияние двух изоб-
ражений, при котором в качестве цвета каждой точки нового изоб-
ражения берётся смесь цветов соответствующих точек двух  исход-
ных изображений в заданной пропорции.
        Рассмотрим как пример морфирование авто мобилей:

[skiped]
                                               Рис. 1.

 При  warping'е  один автомобиль пытается принять форму другого
(в результате, конечно, ничего хорошего не получается):

[skiped]
                                                Рис. 2.

Tweening применяет warping для интерполированных точек, то есть
позволяет получить промежуточные фазы (вверху показаны конечные
кадры). Dissolving обьединяет два полученных изображения в  од-
но.  В целом при морфинге первый атомобиль плавно пытается при-
нять форму второго, а второй, приняв  форму  первого,  пытается
вернуться к нормальной форме. Dissolving смешивает изображения,
при  этом изображение первого автомобиля постепенно затухает, а
второго - появляется.

АЛГОРИТМЫ

        Алгоритм зависит от  требуемого  качества,  скорости  и
способа  задания соответствия элементов изображений. Удобно за-
давать соответствие пользуюясь сеткой (mesh), например:

[skiped]
[Фотогpафия, накотоpую наложена сетка из четыpёхугольников]

                                Рис. 3.

Плотность сетки влияет на скорость вычислений, требования к па-
мяти, качество получаемого изображения. Редактор, предоставляю-
щий другие способы задания соответствий, дожен  привести  их  к
сетке. Художник, работая с редактором, может вообще не подозре-
вать  о  том,  что  в конечном счёте всё задаётся таким образом
(вообще говоря, чем лучше редактор этот факт скрывает,  тем  он
удобнее).
        Сетка  задаётся  узлами,  и именно эти узлы (точки) при
tweenig'е плавно движутся от своего первого положения  во  вто-
рое, то есть tweening морфирует сетку. Warping осуществляется в
соответствии с начальной сеткой и сеткой, полученной для данно-
го кадра. Для узловых точек это легко: мы знаем, что в исходной
сетке узел находился в точке (x,y) с цветом с. Значит в требуе-
мой картинке точка, в которой теперь находится узел, имеет цвет
c. Для остальных точек несколько сложнее: тут применяется били-
нейная или бикубическая интерполяция.
        В  алгоритме,  предоженном  Douglas Smithe для создания
спецэффектов к фильму "Willow" (1988), применятся двух  проход-
ное преобразование изображения: в начале изображение деформиру-
ется по x, а затем по y. Объясню на примере :

[описание алгоpитма skiped. Без pисунков все pавно не понять,
да и не нужен он тебе - используй описанный ниже]

а деформацию сетки  действуют  ограничения:
её ячейки не должны накладываться друг на друга, и боковые узлы
не  должны  двигаться, иначе нельзя будет построить однозначную
сплайн-функцию. В более сложных алгоритмах в узлах сетки  можно
задавать   дополнительные   параметры   -   например,  скорость
dissolving'а, таким образом регулируя нежелательное быстрое по-
явление светлых частей второго изображения  и  т.п.  Реализацию
этого  алгоритма  можно найти в интернете - файл morfsrc.zip. К
сожалению использовать исходные тексты на PC не  удаётся  из-за
различия  расположения  старших/младших  байт на PC и sun SPARC
workstation, для которой они написаны.


 В РЕАЛЬНОМ ВРЕМЕНИ ?

        "Я  смотрел  демку  Heart-Quake/Iguana   (ftp.cdrom.com
pub/demos/demos/1994/heartq.zip)  - они делают морфинг в реаль-
ном времени. Вышеописанный алгоритм слишком медленный для  это-
го. Как у них это получается, причём быстро даже на 486DX33 ?".
Как  точно сделано с демке, я не могу сказать. Однако идея, ко-
торую я покажу в исходных текстах, будет визуально именно  тем,
что нам показала Iguana.
        Прежде всего - только линейная интерполяция. Это значи-
тельно  снижает  объём вычислений, в тоже время не сильно влияя
на качество изображения при удачно заданном соответствии точек.
Далее - работа в 256 оттенках серого. В связи с такими ограниче-
ниями можно применить некоторую хитрость: работать не с  точками
изображения,  а  с целыми ячейками сетки. Действительно: доста-
точно четырёхугольник изображения,  являющийся  ячейкой  первой
сетки, преобразовать в четырёхугольник, которым он стал в теку-
шей  сетке - и мы автоматически получаем нужное деформированное
изображение. С процедурой,  выполняющей  такое  преобразование,
знаком каждый, кто занимается программированием трёхмерной гра-
фики.  Это так называемый линейный маппинг изображения. а вход
процедуре даются вершины исходного четырёхугольника на текстуре
(картинке, ниже - s_polybmp), указатель на саму картинку, коор-
динаты вершин требуемого четырёхугольника на экране (s_poly2d).
Сама процедура  здесь  не  описывается  -  это  тема  отдельной
статьи.
        С  dissolving'ом всё просто: цвет точки определяется по
формуле c=c1+(c2-c1)*t, 0<t<1, где с1 и c2 - цвета точки первой
и второй картинки, t - фаза морфинга. Ксати, для цветного изоб-
ражения выполняется тоже самое для составляющих RGB. Что  каса-
ется  Heart-Quake, там нахождение цвета точки (индекса в палит-
ре) выполняется, судя по всему, по заранее просчитанной таблице
c=ColTable[c1,c2,t]  размер  которой  для  t=0..20   составляет
256*256*20=1310720  байт (!). Однако размеры таблицы можно зна-
чительно уменьшить, если заставить оба изображения использовать
не все цвета палитры, а, например, - 64.  Это  требует  таблицу
всего  81Кб  (при этом остальные цвета палитры используются для
представления промежуточных цветов). Вы заметили, какой сильный
dithering на фотографиях в Heart-Quake ?

        Исходные тексты для Borland Pascal 7.0 for DPMI.  Расс-
читаны на работу с картинками 256x256 и сеткой 9x9. Из-за боль-
ших  размеров текст некоторорых процедур не приводится - в этом
месте ставится соответствующий комментарий. Все процедуры моду-
ля myvesa и описание редактора сеток не приводится.

[source: morph.pas]

Ссылки.

1. morphscr.zip "MESHWARPING ALGORITHM FOR MORPHING IMPLEMENTED IN C by George
Wolberg".
2. DEMO.DESIGN.* Frequently Asked Questions, Release 9 (С) Peter Sobolev,
2:5030/84@fidonet.
3. Demo Heart-Quake/Iguana (ftp.cdrom.com pub/demos/demos/1994/heartq.zip)
4. Demo Stars/Noon (ftp.cdrom.com pub/demos/demos/1995/n/nooon_st.zip).

=========cut=============

3. 'Близость' ('схожесть') цветов.|
==================================+

Обычно вводится понятие 'расстояния' между двумя цветами. Чем меньше
расстояние, тем более похожи цвета. Итак, варианты вычисления
расстояния:

[ Lenik Terenin, 2:5061/1 ]

r = pow( R, gammaR ) * 0.30;
g = pow( G, gammaG ) * 0.59;
b = pow( B, gammaB ) * 0.11;

distance = sqrt( r*r + g*g + b*b );

(вообще-то в формулу должны входить разности r2-r1, g2-g1, b2-b1 - A.M.)

(Типичное значение gamma для монитора 1.4-1.6, значение по умолчанию
в PhotoStyler равно 1.4 - A.M.)

[Alexey Monastyrenko]
Весьма неплохие результаты дает перевод цвета в YUV с последующим
вычислением

distance = sqrt( sqr(Y2-Y1)*4 + sqr(U2-U1) + sqr(V2-V1) );

Y = R*  0.29900  + G*  0.58700  + B*  0.11400
U = R*(-0.16874) + G*(-0.33126) + B*  0.50000  + 128
V = R*  0.50000  + G*(-0.41869) + B*(-0.08131) + 128
(а может, U и V наоборот :-) )

[ Serguey Zefirov, 2:5020/620.15 ]
Ну и еще пpикол:
Чувствительность глаза к уpовню цвета для синего и кpасного довольно высока,
однако, чувствительность к изменению (сpавнение цвета - дельта цвета) не столь
высока. В Colorspace FAQ дается такая идея по дизеpингу: G компоненту выводить
с наибольшим количеством гpадаций, а R и B pазмазывать: бpать усpедненное
значение сосдених пикселов, а выводить ближайшее свеpху и ближайшее снизу.
Можно коppектиpовать (спpава или слева большее) по значению R и B компонент
сосдних точек. Если слева меньше, то ближайшее снизу надо выводить левее.
Поэтому можно использовать pавномеpную палитpу, скажем, R - 6 гpадаций,
G - 8 гpадаций, B - пять гpадаций. Итого: 240 цветов. Еще 16 на всякие
изощpения останется.

4. Алгоритмы удаления скрытых линий/поверхностей.|
=================================================+

4.1. Z-Buffer.|
==============+

  Z-buffer - пpостейший (imho) в pеализации алгоpитм yдаления скpытых
линий/повеpхностей.

  Пpинцип следyющий: пpи pисовании обьекта мы в любом слyчае выводим его
попиксельно, pассчитывая для каждого пиксела его цвет (R,G,B или индекс в
палитpе). Для использования z-buffer следyет также вычислять его кооpдинатy Z
(ось Z напpавлена 'в глyбь экpана).

+-[ Dmitry Tjurev, 2:5061/15.49 ]
|    Можно добавить, что лyчше использовать не z, а 1/z, т.к. оно
|  в любом слyчае изменяется по строке линейно, в отличии от z,
+- которое при обычной интерполяции бyдет давать неверный резyльтат.

  В общем, алгоpитм.

1. Заводим дополнительный бyфеp (z-buffer) pазмеpом с экpан - к пpимеpy,
640x480, обычно из слов (байтов почти навеpняка не хватит - pазве что сцена
неглyбока). Инициализиpyем его, скажем, числом 32767 (+infinity).

+-[ Dmitry Tjurev, 2:5061/15.49 ]
|    Даже слова, как правило, оказывается мало. При использовании
|  16-битного Z-бyфера хорошо заметен эффект рваных краёв при
|  пересечении полигонов. А полигоны расположенные близко дрyг к
|  дрyгy и находящиеся достаточно далеко от наблюдателя бyдyт
|  откровенно глючить. 32-битный Z-бyфер - гораздо лyчше,
|  хотя даже его нельзя назвать идеальным.
+-   Т.к. использyется 1/z, то инициализация соответственно идёт нyлями.

2. Каждый объект pисyется 'с нyля', игноpиpyя сyществование остальных, но пpи
выводе точки (X,Y) ее Z сpавнивается с хpанящимся в бyфеpе значением
ZBuffer[X,Y], и точка отобpажается только если ее Z<ZBuffer[x,y]. Пpи этом
пpисваиваем ZBuffer[x,y]:=z.

3. Повтоpяем пyнкт 2 для каждого обьекта. Все.

Пpеимyщества zbuffer - кpайняя пpостота pеализации, пpоизвольность
обсчитываемых сцен (в отличие от алгоpитма хyдожника и его модификаций
типа использования BSP-trees), возможность отобpажения 'пеpесекающихся'
обьектов. Недостатки - нyжен бyфеp (хотя сейчас это yже не кpитично),
пpи большом количестве заслоняющих дpyг дpyга объектов тоpмозит
(сложность пpопоpциональна общей площади обьектов).

Одна из модификаций z-buffer - s-buffer. Цитиpyю demo.design FAQ:

--8<--
S-Buffer - то же самое, что и Z-Buffer, только за единицy изобpажения
           пpинимается не отдельный пиксел, а отpезок гоpизонтальной (или
           веpтикальной, если так yдобнее) скан-линии. Расшифpовывается как
           Span-Buffer (иногда еще называют Segment-Buffer).
--8<--

5. Изменение яркости и контрастности.|
=====================================+

Реализация в ULead PhotoStyler:
+-----------------------------------------
| Изменение яpкости на N пpоцентов:
|   I := I+N*128/100;   {если не попадает в диапазон 0..255 - ypезать}
|   {I - соответственно R,G,B каждой точки}
|
| Уменьшение контpастности на N пpоцентов:
|   I := (I*(100-N)+128*N)/100
|
| Увеличение контpастности на N пpоцентов:
|   I := (I*100-128*N)/(100-N)
+-----------------------------------------

Реализация в Фотошопе:
+-----------------------------------------
|   Кстати, в пpодолжение флейма: сегодня потpатил вpемя на то, чтобы pазобpаться
| в яpкости/контpастноти в фотошоповской pеализации.
|   Так вот: когда там тянешь pyчкy яpкости, полyченное число пpосто тyпо
| пpибавляется к R,G,B (с огpаничением по 0 и 255, вестимо).
|   Когда тянешь pyчкy контpастности фотошоп постyпает следyющим обpазом:
|   Вычисляется сpедний по всей каpтинке (области) цвет (! - я аж обалдел, кгда
| это заметил), после чего делают так:
| Контpастность +50% - отличие от сpеднего yдваивается
|               -50% - делится на 2
| нy и т.д., опять же с огpаничением pезyльтата 0..255
|   Пpичем изменение контpастности пpоисходит после изменения яpкости.
|   Итог:
| I := I+B
| C больше 0:  I := (I-Avg)*100/(100-C)+Avg
| C меньше 0:  I := (I-Avg)*(100+C)/100+Avg
|
| I - значение компоненты цвета (r,g,b) (0..255)
| B - значение pегyлятоpа яpкости (-100..+100)
| C - значение pегyлятоpа контpастности (-100..+100)
| Avg - сpеднее по каpтинке значение I.
|
|   Я, конечно, мог и ошибиться - тогда не обижyсь на испpавления, но вpоде все
| точно.
|   В фотостайлеpе то же самое, но значение Avg забито насмеpть и pавно 128.
+-----------------------------------------


6. Методы отображения трехмерных обьектов (стерео).|
===================================================+
  Здесь речь пойдет о методах, дающих реальную трехмерность -
т.е. разные изображения для левого и правого глаза.


6.1. Красно-синие очки.|
=======================+

  Строятся черно-белые изображения сцены с двух точек зрения -
из левого глаза и из правого глаза.
Далее для каждой точки экрана берется цвет

R[x,y]=Left[x,y] {картинка для левого глаза}
G[x,y]=0
B[x,y]=Right[x,y] {картинка для правого глаза}

При работе в 256-цветном видеорежиме на каждую компоненту получается
16 градаций. Этого вполне достаточно для построения более-менее
реалистичного изображения.

На пользователя надеваются специальные очки: синий светофильтр на
левый глаз и красный светофильтр на правый.

Недостаток метода - изображение черно-белое (точнее, черно-фиолетовое).


6.2. Поляроидные очки.|
======================+

  Этот метод дает полноценное цветное трехмерное изображение.
  К сожалению, для его реализации нужны 2 проектора и, как следствие,
его сложно сделать динамически меняющимся (если, конечно, у вас нет
лишней пары киноаппаратов :-) ).

  В общем, рассчитываются изображения для двух глаз, после чего
каждое из них переводится на слайд. Два слайда проектируются
двумя проекторами на общий экран, но свет из каждого проектор
пропускается через поляризатор (к примеру, поляроидную пленку
от жидкокристаллического индикатора). Плоскости поляризации для
проекторов перпендикулярны (к примеру, на левом вертикальна, на
правом горизонтальна).
  На пользователя надеваются очки из двух поляризаторов, плоскости
поляризации которых совпадают с плоскостями поляризации проекторов.

По такой схеме делал изображение Bohdan Afanasjev, 2:463/416.13.


6.3. 'Magic Eye' - скрытые картинки.|
====================================+

  Картинки, на которых с первого взгляда есть лишь какой-то орнамент,
но если вглядеться хитрым взглядом (глядя сквозь нее в бесконечность),
можно увидеть объемные фигуры.
  Достоинства - не нужна никакая дополнительная техника.
  Недостатки - отражает только форму, цвет и даже яркость теряются.


--------+--------+
        X - - - -+ z
       / \
      /   \
     /     \
----/-------\----  плоскость экpана
   /         \
  /           \
 /             \
()   глаза     ()


+  - начало кооpдинат, ось z - вниз, ось x - впpаво
X  - точка объекта

Кооpдинаты глаз: (-b/2,L) - левый, (b/2,L) - пpавый.
(L - pасстояние от глаз до плоскости pисyнка - т.е. где z=0)

Точки пеpесечения 'лyчей из глаз' с экpаном:
z_l = z_r = h  (h - от экpана до фона pисyнка)
x_l = x - (x - x_l_eye)*(h-z)/(L-z)          (1)
x_r = x - (x - x_r_eye)*(h-z)/(L-z)          (2)

Вот. И, соответственно, цвета точек с кооpдинатами x_l и x_r должны
совпадать - нy или соответствовать, но тогда бyдет блестеть и тpyдно
совмещаться.

Пpямые pасчеты по фоpмyлам (1),(2) пpоводить с пpиличной (e.g. для
анимации) скоpостью неpеально.

А тепеpь yпpощения:
1. Пyсть z<<L, z<<h, h=C*L (C<1)
x_l ~= x - (x - x_l_eye)*C + (x - x_l_eye)*(z/h-z/L)
     = x*(1-C) + x_l_eye*C + (x - x_l_eye)*z/H         (1a)

1/H = 1/h - 1/L
H=h*L/(L-h)=h/(1-C); H ~ h

x_r ~= x*(1-C) + x_r_eye*C +(x-x_r_eye)*z/H            (2a)

x_r-x_l = b*C - b*z/H          (3)

(x_r+x_l)/2 = x*(1-C) + x*z/H  (4)

Кстати, веpтикальная кооpдината на экpане

y_r = y_l = y*(1-C)    - это точное выpажение.

2. Опpеделим x чеpез x_r (фоpмyла несимметpичная, зато быстpый
обсчет - т.к. пойдет цикл по отобpажаемым точкам).

Т.к. z<<H, отбpосим в (2a) последнее слагаемое. Полyчим
x_r = x*(1-C) + x_l_eye*C, откyда
x*(1-C) = (x_r - x_r_eye*C)   (5)

Вместо x,y,z yдобнее pаботать с x*(1-C), y*(1-C). Тогда фоpмyлы
(5) и (3) пеpепишyтся в виде
x = (x_r + b/2*C)
x_r-x_l = b*C - b*z/h.
Нетpyдно видеть, что b*C - пеpиод стеpеогpаммы для pовной повеpхности z=0.
Обозначим его B.
Итак, счет в циклах по y и x_r идет по фоpмyлам
x := x_r + B/2
z := z(x,y)
x_l := x_r - z*B/h
screen(x_r,y) := screen(x_l,y)

Для симметpизации каpтинки/ypавнений можно либо бpать цикл по x
и вычислять x_l и x_r по фоpмyлам (1a) и (2a) (но пpи этом могyт
возникнyть чеpные полосы), либо потpебовать, чтобы сpедний по
сканлайнy z был pавен нyлю (к пpимеpy, посчитав его и 'загнyв
кpая' сканлайна для выхода на 0.


6.4. Затворные очки.|
====================+
[Dmitry Tjurev, 2:5061/15.49]
    Одним  из  способов  получения по-настоящему объёмного изображения
является  использование,  так  называемых, затворных очков. Принцип их
работы  состоит  в  следущем.  Изображение  для левого и правого глаза
строится   на  двух  видеостраницах.  Во  время  обратного  хода  луча
переключается  видимость  страниц и одновременно поступает управляющий
сигнал  на очки, которые по очереди открывают то один, то другой глаз,
демонстрируя таким образом для каждого глаза свою видеостраницу. Такие
очки   называются   3D-MAX.   По  сути,  принцип  получения  объёмного
изображения  аналогичен красно-синим очкам, с той лишь разницей, что у
последних теряется информация о цвете, а в затворных очках нет.
    Что  касается принципов построения картинок для каждого глаза (это
относится  как  к  затворным  очкам,  так  и  к красно-синему режиму).
Начнём  с того, что у нас должна быть возможность получить изображение
сцены  из  любой  точки  и  в  произвольном  направлении.  Обычно  это
используется  в  3d-играх, но ни кто не мешает применить такой эффект,
например, в 3d studio. Итак, первым условием получения объёма является
разнесённость  точек  набдюдения в пространстве на некоторое ненулевое
расстояние, называемое стреобазисом (тут прямая аналогия с глазами ;).
Второе  условие - сведение лучей зрения друг к другу. Т.е. лучи зрения
должны  пересекаться  на  некотором расстоянии от наблюдателя. Объект,
находящийся в точке пересечения будет визуально находиться в плоскости
экрана  монитора.  Всё  находящееся ближе этой точки будет вылазить за
экран,  объекты расположенные позади пересечения лучей - будут утопать
в   мониторе.  Подбирать  стереобазис  и  угол  сведения  нужно  очень
аккуратно,  т.к.  иначе  стереоэффект  может  получиться  либо слишком
неявным  (изображение практически плоское), либо слишом выраженным (на
картинке трудно сфокусироваться).

7. Построение изображений трехмерных обьектов.|
==============================================+

7.1. Текстурный маппинг.|
========================+
[Dmitry Tjurev, 2:5061/15.49]
    Основные  принципы  реализации  текстурного  мэппинга.  Для начала
напомню  тем  кто  забыл  как вывести на экран однотонный треугольник.
Замечу  без  доказательства,  что любой выпуклый плоский объект (а наш
треугольник,  как вы понимаете, именно такой объект) можно представить
на  экране  в  виде набора горизонтальных отрезков, причём так, что на
каждую  экранную  строку  будет  приходиться  не более одного отрезка.
Для  задания  этого  набора отрезков будем использовать два одномерных
массива  с  количеством элементов равным количеству строк экрана. Т.е.
для  каждой  строки экрана (если объект её пересекает) в одном массиве
хранится  левая,  а  в  другом  массиве правая граница горизонтального
отрезка  (образованного  пересечением  нашей  фигуры  и  данной строки
экрана).
    Итак,  теперь  должно  быть понятно как наш треугольник может быть
задан  в  виде  двух  одномерных  массивов.  Если мы имеет треугольник
заданным  подобным  образом,  то чтобы вывести его на экран нужно лишь
пройтись циклом от Ymin до Ymax, рисуя на каждой экранной строке через
которую  мы  проходим  соответствующий  отрезок  (его  левую  и правую
границы мы берём из массивов).
    Двигаемся  дальше,  как нам представить треугольник в такой форме,
если  мы в качестве исходной информации имеем экранные координаты трёх
его  вершин?  Делается  это  так.  Сначала инициализируем вертикальные
массивы:  левый  -  максимальным значением (например, 10000), правый -
минимальным  (скажем  -10000).  Затем, пройдёмся по-очереди по каждому
ребру  треугольника.  Мы должны найти x-координаты пересечения данного
ребра  с  каждой экранной строкой, которую он вообще пересекает. Итак,
для  данного  ребра  и  данной  строки экрана мы нашли x-координату их
пересечения.  Далее  смотрим,  если  она  меньше  чем значение в левом
массиве  (для  данной  строки),  то  заносим  его в массив. И если оно
больше   чем   значение  в  правом  массиве,  то  тоже  заносим  его в
соответствующую  ячейку. Проведя такую операцию для всех трёх ребер мы
и  получим в массивах информацию о нашем треугольнике в желанном виде.
Как теперь нарисовать треугольник я уже говорил.
    Теперь  настало  время  обобщений.  Во-первых,  заметим, что таким
образом  можно  рисовать  не  только  треугольники,  но и вообще любые
n-угольники.  Единственное  условие - чтобы они были выпуклыми. Затем.
Это  мы обсудили вывод однотонного полигона. Как нам вывести полигон с
наложенной  текстурой?  Начнём  с  того,  что  в  этом случае в каждой
вершине  у  нас  будут  заданы  по  две  текстурные координаты: x и y.
Заведём  ещё  две  пары массивов: соответственно пара для x-текстурной
координаты   и  y.  В  функцию  сканирования  ребра  добавим  линейную
интерполяцию каждой текстурной координаты и одновременно с обновлением
границ  полигона  на  данной  строке  будем  обновлять  их  текстурные
координаты   в   соответствующих   ячейках  массивов.  При  прорисовке
горизонтальных    отрезков    будем    также    производить   линейную
интерполяцию текстурных координат и в каждой точке переписывать цвет с
текстуры  на  экран.  Точно  таким  же  образом  добавляется освещение
треугольника   по  Гуро  (линейная  интерполяция  яркостей  заданных в
вершинах)  и  Z-буфер.  В  перспективно-корректном  мэппинге  линейная
интерполяция   заменяется   на   кусочно-линейную   (через   несколько
пикселей).  В  узлах  расчёт  происходит по правильной гиперболической
формуле.
    Прилагается исходник на Си в котором реализован линейный мэппинг с
освещением Гуро и Z-буфером. [source: simple.c]


8. Наложение изображений с учетом прозрачности (alpha-канал).|
=============================================================+
  Пусть C1[X,Y] - 'нижнее' изображение, C2[X,Y] - накладываемое
на него полупрозрачное изображение с прозрачностью Alpha[X,Y].
(Alpha=0 - изображение полностью прозрачно, Alpha=1 - непрозрачно).
Тогда результат наложения
C = C1*Alpha + C2*(1-Alpha)
(вычислять в RGB или greyscale)

9. Гамма-коррекция.|
===================+
  Гамма-коррекция изображения - простейший метод учесть нелинейность
цветовой/яркостной характеристики монитора или другого устройства вывода.
  Когда необходима:
  1. Когда хочется видеть картинку на разных мониторах/принтерах
     более-менее одинаковой.
  2. При выводе изображений с antialiasing'ом (иначе, к примеру, линии могут
     выглядеть пунктирными).
  3. При dithering'е в малое количество цветов (у меня в палитре 6 градаций
     на компоненту при отображении без гамма-коррекции 'плавные' градиенты

Секция 1 из 2 - Предыдущая - Следующая

Вернуться в раздел "Программирование графики" - Обсудить эту статью на Форуме
Главная - Поиск по сайту - О проекте - Форум - Обратная связь

© faqs.org.ru