Некоторые приемы полигональной графики

advertisement
Некоторые приемы полигональной графики
Все,что делает GPU - это вывод полигонов
Наша задача - свести основные эффекты к работе с гранями
При этом часто нужно производить специальную настройку
граней
Переложим на GPU
Некоторые приемы полигональной графики billboards
Billboard - это грань,
всегда параллельная
плоскости экран
up
view
P
right
Любая ее точка
задается уравнением
P’ = P + s * right + t * up
Пример использования billboard-ов - системы
частиц
Некоторые приемы полигональной графики
billboards
В лоб Р - положение частицы
right, up - ориентация камеры
glBegin
glTexCoord2f
glVertex3fv
glTexCoord2f
glVertex3fv
glTexCoord2f
glVertex3fv
glTexCoord2f
glVertex3fv
glEnd
( GL_QUADS);
( 0, 0 );
( p );
( 0, 1 );
( p + right);
( 1, 1 );
( p + up + right );
( 1, 0 );
( p + up );
();
P+up
tex=(0,1)
P
tex=(0,0)
P+up+right,
tex=(1,1)
P+right
tex=(1,0)
Некоторые приемы полигональной графики
billboards
--:
• Вся работа целиком на CPU
• Постоянный большой объем передаваемых GPU
данных
• Во многих случаях даже для анимации законы
крайне просты (т.е. могут быть легко переложены на
GPU)
Некоторые приемы полигональной графики
billboards через GPU
Передаваемые данные (вершинные):
(p, (0,0)),
(p, (0,1)),
(p, (1,1)),
(p, (1,0))
Вершинный шейдер:
Передаваемые данные (глобальные):
camera.up,
out.tex
= in.tex;
camera.right,
out.color = in.color;
time,
out.pos
= mul ( mvp,
in.pos +
in.tex.tex.x * right +
in.tex.y * up );
Некоторые приемы полигональной графики
billboards через GPU
Пример:
- разлет частиц под действием силы тяжести
Решение:
- всю анимацию можно переложить на GPU
- тогда данные в вершинах вообще не изменяются
- данные в вершинах поместим в VBO
- единственный передаваемый на каждом кадре параметр это время
Некоторые приемы полигональной графики
billboards через GPU
Вершинный шейдер:
float t
= mod ( time, 4.0 );
float alpha = 1 - 0.25 * t;
float3 pos
= in.pos +
in.tex.tex.x * right +
in.tex.y * up;
out.tex
= in.tex;
out.color
= in.color;
out.color.a = alpha;
out.pos
= mul ( mvp, pos + 0.5 * t *
float3 ( 0, 0, -1.0 );
Некоторые приемы полигональной графики
billboards через GPU
?:
!:
Что делать когда время жизни частицы выйдет
• Переиспользуем ее.
• Чтобы все частицы не переиспользовались в одно и
тоже время, добавим к частице фазу - сдвиг по времени
• Заодно можем добавить начальную скорость частицы
• Поместим все это в tex1 (vel.x, vel.y, vel.z, phase)
Некоторые приемы полигональной графики
billboards через GPU
float3
float
float
float
float3
vel
phase
t
alpha
pos
out.tex
out.color
out.color.a
out.pos
=
=
=
=
=
in.tex1.xyz;
in.tex1.w;
mod ( time + phase, 4.0 );
1 - 0.25 * t;
in.pos + in.tex.tex.x * right + in.tex.y * up;
=
=
=
=
in.tex;
in.color;
alpha;
mul ( mvp, pos + t * vel+
0.5 * t * float3 ( 0, 0, -1.0 );
Некоторые приемы полигональной графики
billboards через GPU
++:
• Вся анимация полностью на GPU
• Минимум передаваемых данных
Еще пример:
Огонь как система частиц полностью на GPU
Некоторые приемы полигональной графики
огонь как система частиц на GPU
Fire Particle:
• положение
• температура
• цвет (зависит от температуры)
• скорость
vel = in.vel + t * acc;
temp = in.temp - t * kt;
pos = in.pos + in.vel * t +
0.5 * t * t * acc;
const float4 c1 = float4 ( );
const float4 c2 = float4 ( );
const float4 c3 = float4 ( );
if ( temp < temp1 )
color = lerp ( c1, c2, temp / temp1 );
else
color = lerp ( c2, c3, (temp - temp1)/(temp2 - temp1);
Некоторые приемы полигональной графики рендеринг травы
L
Выводить отдельно каждую травинку потребует
слишком больших затрат.
А анимация :((((
J
А зачем выводит по одной травинке - будем
выводить сразу по много
Некоторые приемы полигональной графики рендеринг травы
Будем использовать billboard-ы:
Распределим на ландшафте ряд точек, с
каждой точкой свяжем свой billboard
++:
• Полностью статическая
геометрия (т.е. не надо
заново передавать)
• Легкость создания
• Требуется не так много
полигонов
Некоторые приемы полигональной графики рендеринг травы
Некоторые приемы полигональной графики рендеринг травы
Переложим на GPU и анимацию травы
Для этого достаточно смещать верхние две
вершины (где tex.y > 0.5) как функцию от
точки Р и времени t.
if ( in.tex.y > 0.5 )
{
float angle1 = c0 * time + c1 * in.pos.x + c2 * in.pos.z;
float angle2 = c3 * time + c4 * in.pos.y + c5 * in.pos.z;
out.pos += 0.05*float4 ( sin ( angle1 ), cos ( angle2 ), 0, 0 );
}
Некоторые приемы полигональной графики рендеринг травы
L
Трава получается слишком одинаково выглядящей
J
Давайте вместо billboard-ов будем использовать
набор граней заранее заданной ориентации
(анимируя верхние вершины)
Некоторые приемы полигональной графики рендеринг травы
Некоторые приемы полигональной графики «толстые линии»
В ряде случаев возникает
необходимость не в частицахточках, а в вытянутых линиях.
Это могут быть следы от быстро
летящий частиц, лучи света и т.п
Некоторые приемы полигональной графики «толстые линии»
Основные положения:
• рисуем как четырехугольники (GL_QUADS)
• задаем две точки А и В (координаты второй точки можно
передать через текстурные координаты
• Необходимо отрезок АВ, получающийся при
проектировании исходных точек на экран сделать толще и
длиннее
Вершинные данные:
(pt, otherPt, tex0)
(A,B,(0,0))
(B,A,(0,1))
(B,A,(1,1))
(A,B,(1,0))
Некоторые приемы полигональной графики «толстые линии»
(A,B,(0,0))
(B,A,(0,1))
(A,B,(1,0))
thickness
(B,A,(1,1))
Некоторые приемы полигональной графики «толстые линии»
float4 start = mul ( mvp, in.pos );
float4 end
= mul ( mvp,in.tex1 );
float2 start2d
float2 end2d
float2 dir2d
// current point
// other point
// map to screen
= start.xy / start.w;
= end.xy
/ end.w;
= normalize ( end2d - start2d );
if ( in.tex0.y > 0.5 )
thickness = -thickness;
// определить направление шага
// вбок
if ( in.tex0.x > 0.5 )
dir2d = -dir2d;
// определить направление вперед
// направление вбок
float2 side2d
= float2 ( dir2d.y, dir2d.x );
out.pos = in.pos + thickness * side2d;
out.tex = in.tex0;
Некоторые приемы полигональной графики «толстые линии»
L
J
Если проекции А и В почти совпадают, то вместо
толстой линии получаем, тонкий отрезок
Тогда будет сдвигать точку не только вбок на
величину thickness, но и вперед/назад на величину
offset
(A,B,(0,0))
(A,B,(1,0))
offset
(B,A,(0,1))
(B,A,(1,1))
Некоторые приемы полигональной графики рендеринг в текстуру
Некоторые приемы полигональной графики рендеринг в текстуру
Традиционный подход - отразить камеру относительно зеркала
camera
camera'
Некоторые приемы полигональной графики рендеринг в текстуру
L
Однако, если у нас поверхность с рябью, то такой
подход непосредственно не приемлем
J
Попробуем при помощи отраженной камеры
построить отраженное изображение сцены в
текстуру, а потом исказим ее при наложении
Для рендеринга в текстуру (render-to-texture, RTT)
можно использовать FBO или р-буфер.
Некоторые приемы полигональной графики рендеринг в текстуру
camera'
Текстура с отраженной сценой
Некоторые приемы полигональной графики рендеринг в текстуру
L
Полученная таким образом текстура уже содержит в
себе изображение с примененным перспективным
преобразованием, поэтому ее нельзя накладывать на
поверхность зеркала обычным образом - тогда она
еще раз подвергнется перспективному
преобразованию
Некоторые приемы полигональной графики рендеринг в текстуру
J
Поместим в положении камеры проектор,
проектирующий полученную картинку на сцену
camera
Некоторые приемы полигональной графики рендеринг в текстуру
J
Для моделирования проектора возьмем в качестве
матрицы преобразования текстурных координат
(GL_TEXTURE) произведение модельной и
проектирующей матриц, использованных при
построении отражения (они переведут исходные
координаты вершин в [-1,1]*[-1,1]. А затем
переведем в [0,1]*[0,1] посредством переноса и
масштабирования.
Некоторые приемы полигональной графики рендеринг в текстуру
glMatrixMode
( GL_TEXTURE );
glPushMatrix
();
glLoadIdentity ();
glTranslatef ( 0.5, 0.5, 0 );
glScalef
( 0.5, 0.5, 1 );
glMultMatrixf ( proj );
glMultMatrixf ( mv
);
Если при использовании такой
матрицы в качестве текстурных
координат вершины задать
трехмерный вектор ее
пространственных координат, то
получающиеся текстурные
координаты будут
соответствовать той точке
текстуры, которая является
проекцией данной вершины при
отражении.
Некоторые приемы полигональной графики рендеринг в текстуру
Если при помощи
шумовой функции
слегка искажать
текстурные координаты
для каждого фрагмента,
то мы получим вполне
правдоподобно
выглядящую рябь.
float4 main ( FragmentData IN,
uniform float time,
uniform float4x4 texMatrix,
uniform sampler3D noiseMap,
uniform sampler2D reflectionMap ) : COLOR
{
float3 ncoord
= float3 ( IN.p.x, IN.p.y + time,
IN.p.z ) * 1.1;
float3 noise
= tex3D ( noiseMap, ncoord ).rgb;
float4 tex
= mul
( texMatrix, IN.p ) +
float4 ( noise * 0.05, 0.0 );
float3 reflColor = tex2Dproj ( reflectionMap,
tex.xyw ).xyz * 0.8;
return float4 ( reflColor, 1.0 );
}
Некоторые приемы полигональной графики рендеринг в текстуру
Дополнительные возможности - можно в специальной
текстуре занести глубину воды в точке.
Тогда значение глубины, равное нулю, означает отсутствие
воды (и отражения).
Остальные значения используются для управления величиной
искажений - чем больше глубина, тем больше искажение и
характерный размер искажений (т.е. значение глубины
изменяет не только добавляемое к текстурным координатам
искажение, но и масштабирует текстурные координаты,
используемые для обращения к шумовой функции.
Некоторые приемы полигональной графики рендеринг в текстуру
Download