Vertex Shader
This sample uses a custom vertex shader to quickly adjust the positions and normals of many vertices in a plane to achieve a ripple effect without iterating through the vertices in javascript.
uniform mat4 world; uniform mat4 worldViewProjection; uniform mat4 worldInverseTranspose; uniform float clock; uniform float y00; uniform float y10; uniform float y01; uniform float y11; // Input parameters for the vertex shader. attribute vec4 position; attribute vec3 normal; attribute vec4 color; attribute vec2 texCoord0; // Input parameters for the pixel shader (also the output parameters for the // vertex shader.) varying vec3 v_objectPosition; varying float water; varying float terrain; varying vec3 terrainNormal; varying vec3 waterNormal; float myfunction (float y0,float y1,float x) { float dy = y1 - y0 ; float d = y0 ; float a = -2.0*dy; float b = 3.0 * dy ; return d+(x*x*(b+a*x)); } float dmyfunction (float y0,float y1,float x) { float dy = y1 - y0 ; float d = y0 ; float a = -2.0*dy; float b = 3.0 * dy ; return x*(b*2.0+a*3.0*x); } float wave(vec2 v) { float tmp = clock; float z1 = myfunction (y00,y01,v.x); float z2 = myfunction (y10,y11,v.x); return myfunction(z1,z2,v.y); } vec3 dwave(vec2 v) { float z1 = myfunction (y00,y01,v.x); float z2 = myfunction (y10,y11,v.x); vec3 n = normalize(vec3(mix(dmyfunction (y00,y01,v.x),dmyfunction (y10,y11,v.x),v.y),1.0,dmyfunction (z1,z2,v.y))); return n; } float wave2(vec2 v) { float z=.0075*sin(31.0*(-v.x)-5.0*clock)+.01*sin(17.00*((v.x+v.y*.4736957))+7.0*clock)+.0025*sin(11.0*((v.y+v.x*.3574598))+3.0*clock)+.005*sin(13.0*((v.y*.4-v.x*.6))+5.0*clock); return z; } /** * vertexShaderFunction - The vertex shader perturbs the vertices of the plane * to achieve the ripples. Then it applies the worldViewProjection matrix. * * @param input.position Position vector of vertex in object coordinates. * @param input.normal Normal of vertex in object coordinates. * @param input.color Color of vertex. */ void main() { vec4 p = vec4(position.x,0,position.z,1); float h = 1.0/256.0; terrain = wave(texCoord0); vec3 n = dwave(texCoord0); p.xz = position.xz; p.y = terrain; water = wave2(p.xz); if (p.y
0.0) { /* vec2 t = vec2(atan(terrainNormal.x,terrainNormal.z)/3.141592654,terrain*4.0); */ vec2 t = p.xz*4.0; c = mix(c,texture2D(cliffSampler,t),a); bump = mix(bump,texture2D(cliffBump,t),a); } if (water>terrain) { n =normalize(waterNormal); c = mix(c,texture2D(waterSampler,p.zx), clamp((water-terrain)*20.0,.0,1.0)); bump = texture2D(waterBump,p.zx); } float bumpAngle1 = bump.r - .5 ; float bumpAngle2 = bump.g - .5 ; mat3 rot1 = mat3(cos(bumpAngle1),sin(bumpAngle1),0, -sin(bumpAngle1),cos(bumpAngle1),0, 0,0,1); mat3 rot2 = mat3(cos(bumpAngle2),0,sin(bumpAngle2), 0,1,0, -sin(bumpAngle2),0,cos(bumpAngle2)); n = rot2 * rot1 * n ; vec3 l = normalize(lightWorldPos); // Unit-length vector toward light. //vec3 noise = vec3(fract(19999.0*p.x*p.y)-.5,fract(19999.0*p.x*p.z)-.5,fract(19999.0*p.z*p.y)-.5); //vec3 n = normalize(v_normal+noise); // Unit-length normal vector. vec3 v = normalize(cameraWorldPos - p); // Unit-length vector toward camera. vec3 r = normalize(-reflect(v, n)); // Reflection of v across n. float ldotr = dot(r, l); float shininess =20.0; if (p.y>.025) { if (p.y>.35) shininess = 20.0-clamp((.4-p.y)*20.0,.0,1.0)*15.0; else shininess = 5.0 ; } float specular = pow(clamp(ldotr, 0.0, 1.0),shininess) ; float prof = clamp((gl_FragCoord.z/gl_FragCoord.w)/4.0,.0,1.0); vec4 fog = vec4(0,.5,1,1); // Fixed color to be a blue-green; could use v_color instead below. gl_FragColor = mix(c *(.5+.5*clamp(dot(n, l),0.0,1.0)) + specular,fog,prof); } // #o3d MatrixLoadOrder RowMajor