Некоторые приемы полигональной графики Все,что делает 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 ); } Некоторые приемы полигональной графики рендеринг в текстуру Дополнительные возможности - можно в специальной текстуре занести глубину воды в точке. Тогда значение глубины, равное нулю, означает отсутствие воды (и отражения). Остальные значения используются для управления величиной искажений - чем больше глубина, тем больше искажение и характерный размер искажений (т.е. значение глубины изменяет не только добавляемое к текстурным координатам искажение, но и масштабирует текстурные координаты, используемые для обращения к шумовой функции. Некоторые приемы полигональной графики рендеринг в текстуру