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; // Input parameters for the vertex shader. attribute vec4 position; attribute vec3 normal; attribute vec4 color; // Input parameters for the pixel shader (also the output parameters for the // vertex shader.) varying vec3 v_objectPosition; varying vec3 v_normal; varying vec4 v_color; /** * A function defining the shape of the wave. Takes a single vec2 as an * argument the entries of which are the x and z components of a point in the * plane. Returns the height of that point. * * @param {vec2} v The x and z components of the point in a single vec2. */ float wave(vec2 v) { float d = length(v); return 0.15 * sin(15.0 * d - 5.0 * clock) / (1.0 + d * d); } /** * 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 = position; // The height of the point p is adjusted according to the wave function. p.y = wave(p.xz); // Step size used to approximate the partial derivatives of the wave function. float h = 0.001; // We take the derivative numerically so that the wave function can be // modified and the normal will still be correct. vec3 n = normalize(vec3( wave(vec2(p.x - h, p.z)) - wave(vec2(p.x + h, p.z)), 2.0 * h, wave(vec2(p.x, p.z - h)) - wave(vec2(p.x, p.z + h)))); gl_Position = worldViewProjection * p; v_objectPosition = (world * p).xyz; v_normal = (worldInverseTranspose * vec4(n, 1.0)).xyz; v_color = color; } // #o3d SplitMarker uniform float clock; uniform vec3 lightWorldPos; uniform vec3 cameraWorldPos; varying vec3 v_objectPosition; varying vec3 v_normal; varying vec4 v_color; /** * This pixel shader is meant to be minimal since the vertex shader is * the focus of the sample. */ void main() { vec3 p = v_objectPosition; // The point in question. vec3 l = normalize(lightWorldPos - p); // Unit-length vector toward light. vec3 n = normalize(v_normal); // 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. vec3 q = (lightWorldPos - p); float ldotr = dot(r, l); float specular = clamp(ldotr, 0.0, 1.0) / (1.0 + length(q - length(q) * ldotr * r)); // Fixed color to be a blue-green; could use v_color instead below. gl_FragColor = vec4(0, 0.6, 0.7, 1) * dot(n, l) + specular; } // #o3d MatrixLoadOrder RowMajor