var pixels = [], tSize = 64; for(var i = 0; i < tSize; i++){ var s = .2*Math.sin(2*i*Math.PI/tSize), no = Math.sqrt(1 + s*s); pixels.push( 0, s/no, 1/no ); }and store them in a float texture
var texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, tSize, 0, gl.RGB, gl.FLOAT, new Float32Array(pixels)); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.uniform1i(gl.getUniformLocation(prog, "uTexSamp"), 0);It is well known that spline patches have natural tangent directions ∂S(u,v)/∂u and ∂S(u,v)/∂v. They are not orthogonal therefore you can use any one of them and make third vector by cross product (it is ambiguously). These two non orthogonal tangents aBinorm1 and aBinorm2 are used in this script.
Now in the vertex shader we move (rotate and translate) our model
<script id="shader-vs" type="x-shader/x-vertex"> attribute vec3 aPos; attribute vec3 aNorm; attribute vec3 aBinorm1; attribute vec3 aBinorm2; attribute vec2 aTexCoord; uniform mat4 mvMatrix; uniform mat4 prMatrix; varying vec3 rotDif; varying vec3 rotHalf; varying vec2 vTexCoord; const vec3 dirDif = vec3(0., 0., 1.); const vec3 dirHalf = vec3(-.4034, .259, .8776); void main(void) { vTexCoord = aTexCoord; gl_Position = prMatrix * mvMatrix * vec4(aPos, 1.);rotate x, y, z (aBinorm1, aBinorm2, aNorm) vectors
vec3 rotNorm = (mvMatrix * vec4(aNorm, .0)).xyz; vec3 rotBinorm1 = (mvMatrix * vec4(aBinorm1, .0)).xyz; vec3 rotBinorm2 = (mvMatrix * vec4(aBinorm2, .0)).xyz;and project light directions (dirDif, dirHalf) into the rotated local coordinate system
rotDif = vec3(dot(dirDif,rotBinorm1), dot(dirDif,rotBinorm2), dot(dirDif,rotNorm)); rotHalf = vec3(dot(dirHalf,rotBinorm1), dot(dirHalf,rotBinorm2), dot(dirHalf,rotNorm)); } </script>to calculate colors in the fragment shader we use dot products of the "local" light directions and normals saved in texture.
<script id="shader-fs" type="x-shader/x-fragment"> precision mediump float; uniform sampler2D uTexSamp; varying vec3 rotDif; varying vec3 rotHalf; varying vec2 vTexCoord; void main(void) { vec3 Norm = texture2D(uTexSamp, vTexCoord).xyz; float i = max( 0., abs(dot(Norm, rotDif)) ); vec4 color = vec4(i, .5*i, 0., 1.); i = 2.*pow( max( 0., abs(dot(Norm, rotHalf)) ), 120.); color += vec4(i, i, i, 0.); gl_FragColor = color; } </script>