Добрый день!
Подскажите пожалуйста есть ли у кого шейдер для создания водяной поверхности?
У меня 2D игра (стратегия), вид сверху под 45 градусов (изометрия почти). Тайлы квадратные.
Там где у меня вода(озеро) я планирую накладывать по альфе определенную текстуру и к ней нужен эффект воды.
Может у кого уже есть готовый такой эффект? Или кто-то может сделать или подсказать как сделать?
У меня временно так:
Вершинный шейдер
#version 120 attribute vec4 Position; uniform vec3 LightPos; uniform vec3 EyePos; uniform mat4 mCamera; varying vec3 toeye; varying vec3 wp; void main() { vec3 offs = floor(EyePos + vec3(6.0, -6.0, -6.0)); offs.y = 0; vec3 pos = Position.xyz + offs; toeye = EyePos - pos; wp = pos; gl_Position = gl_ProjectionMatrix * mCamera * gl_ModelViewMatrix * vec4(pos,1); }
Фрагментный шейдер:
#version 120 uniform samplerCube samplercube; uniform sampler3D sampler3d; uniform float time; varying vec3 toeye; varying vec3 wp; vec3 turbulence( const in vec3 p) { float sum = 0.0; vec3 t = vec3 ( 0.0 ); float f = 1.0; for ( int i = 0; i <= 3; i++ ) { t += (2.0 * texture3D ( sampler3d, f * p ).rgb - vec3(1.0)); sum += 1.0; f *= 0.47693; } return t / sum; } void main() { vec3 e = normalize(toeye); vec3 n = turbulence(wp + vec3( 0.245843, 1.0, 0.12581 ) * time); n.y = (n.y + 1) * 10.0; n = normalize(n); vec3 p = abs(-toeye); float mh = max(p.x, p.z); float ml = sqrt(mh*mh + p.y*p.y); float L = ml*(1000-mh)/mh; vec3 r = normalize(-toeye + normalize(reflect(-toeye,n)) * L); float fresnel = max ( dot ( e, n ) , 0.0 ); vec3 env = (1-fresnel) * textureCube(samplercube, r).xyz; vec3 color = fresnel * vec3(0.0, 0.2, 0.1); float alpha = 0.7 + (1-fresnel)*0.3; gl_FragColor = vec4(color+env, alpha); }
Может не самое лучшее, что есть. Переделаешь как надо.
Как выглядит:
Привет.
Спасибо за шейдеры, но я так понимаю это для 3D, а у меня 2D.
А какая разница, натянуть текстуру с водой на 3D полигон, либо на тайл в 2D? Оставить шумовую 3d-текстуру, остальное выкинуть
#version 120 attribute vec4 Position; varying vec3 wp; void main() { wp = Position.xyz; // передадим позицию во фрагментный шейдер, для расчёта цвета в зависимости от позиции gl_Position = Position; // позиция в экранных координатах (x,y,z -1..+1) }
#version 120 uniform sampler3D sampler3d; // шумовая 3d текстура uniform float time; varying vec3 wp; vec3 turbulence(const in vec3 p) { ... любая функция турбулентности, использующая sampler3d } void main( ) { vec3 dp = vec3( ??,??,??); // направление сдвига по 3d текстуре в зависимости от времени (чем больше значение, тем быстрее будет "булькать" вода) // получим нормаль(можно воспринимать не как нормаль) из 3d шумовой текстуры по координатам фрагмента тайла на экране vec3 n = turbulence( wp*?? + dp * time); // ?? - будет регулировать масштаб наложенной текстурки // небольшие преобразования нормали(чтоб Y не была отрицательной) n.y = n.y + 1.0; n = normalize( n); /* //можно применить расчёт любой модели освещения vec3 light = vec3(0.0, -1.0, 0.0); //представим, что свет светит на поверхность воды вертикально в низ vec3 toeye = -light; //представим, что глаз находится там же где и свет // нормаль есть, свет есть, уже можно что-то рисовать */ // либо просто менять альфу по функции турбулентности vec4 color = цвет воды color.a = n.y; // меняем альфу gl_FragColor = color; }
http://cgm.computergraphics.ru/issues/issue17/waterrendering#chapter2
http://steps3d.narod.ru/tutorials/water-tutorial.html
У меня 2D игра (стратегия)
Делай 3Д игру !
UVW
Огромное спасибо за статьи и код, думаю это то из чего я смогу сделать то что мне нужно!
ronniko >> Делай 3Д игру !
Вам тоже отдельное спасибо за Ваш "бесценный совет". Обязательно в следующих версиях своей игры я им воспользуюсь.
Тема в архиве.