Shader
varying : vs 的输出, fs 的输入(在光栅化时进行了图元内线性插值)。在 vs,fs 中的声明必须一致。
uniform :应用程序通过通过OpenGL ES 2.0 API 传送给 shader 的只读变量 ;uniform 在 programobject 中是共享的,即一个 programobject 只有一组 uniforms 。如果 uniform 同时在 vs 和 fs 中声明,必须具有相同的类型,并且在这两个 shader 中该 uniform 的值是一样的。在 link 时, linker 会为 program 中的每个 activeuniform 分配一个 uniformlocation 。应用程序使用这个 uniformlocation 作为标识来载入 uniform 的值。
attribute :只在vs中使用,用于指定per-vertex的输入。通常保存位置,法线,纹理坐标,颜色等数据。
WebGL渲染流程
JavaScript定义顶点/颜色等值→绑定到uniform和attribute变量上→提交到vertexShader中→顶点Shader进行差值处理→得到Varying变量→提交到fragmentShader中→最后进行片元处理。
灯光渲染:
疑问1:
shader-vs中
float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);
疑问2:
setMatrixUniforms()中
var normalMatrix = mat3.create();
mat4.toInverseMat3(mvMatrix, normalMatrix);
mat3.transpose(normalMatrix);
gl.uniformMatrix3fv(shaderProgram.nMatrixUniform, false, normalMatrix);
第13章 片元级光照与多program对象:
其中片元级光照的实现,是要对法线进行处理,如果法线和光线平行,那应该是最亮的,如果夹角越大,光线会越暗。
在左边的图中,B点将会相当明亮,因为B点的光线几乎是平行于法线的;而A点则会稍微暗一些,因为光线的入射角更大一些。在A点和B点之间的点,将会有一个从明到暗的渐变。这个效果看起来非常好。
右图中的那样。A点和C点都会比较暗,因为光线的入射角更大。假设我们仍然使用逐顶点光照,那么B点的明亮程度应该是A点和C点的平均值,所以B点也同样会比较暗。但是,这很明显是错误的!在B点,光线几乎是平行于法线的,所以它应该是其中最明亮的一个点。所以在计算顶点之间的片元光照时,我们必须逐个片元、逐个片元的单独进行计算。
函数回顾:
提交 uniform
a)
gl.uniform1i(shaderProgram.useLightingUniform, lighting);
b)
gl.uniform3f( shaderProgram.ambientColorUniform, parseFloat(document.getElementById("ambientR").value), parseFloat(document.getElementById("ambientG").value), parseFloat(document.getElementById("ambientB").value) );
c)
gl.uniform3fv(shaderProgram.lightingDirectionUniform, adjustedLD);
d)
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
f)
gl.uniformMatrix3fv(shaderProgram.nMatrixUniform, false, normalMatrix);
处理纹理
gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, crateTexture); gl.uniform1i(shaderProgram.samplerUniform, 0);
处理Buffer
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer); gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
索引绑定
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,cubeVertexIndexBuffer); gl.drawElements(gl.TRIANGLES,cubeVertexIndexBuffer.numItems,gl.UNSIGNED_SHORT,0);
美轮美奂的高光效果