[WebGL入门]二十三,反射光的光照效果
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正。
各种各样的光照
反射光的概念
从平行光源发出的扩散光的光照,通过光的方向(光向量)和面的方向(面法线向量),来计算这个面的扩散程度,从而实现光照。光照最强的地方就是模型的颜色,反之,没有被光照到的地方,就会变成暗色。
但是,像金属那样的质感,就是光泽的表现,只用扩散光就不够了。为什么呢,光照最强的部分,也只不过是显示了模型的原来的颜色,要想表现出光泽,则需要表现一下高亮这样的强光效果。
修改顶点着色器,只通过扩散光虽然也可以实现高亮效果,但是大部分场合都会感觉不自然。这是因为扩散光是不会考虑视线的。扩散光,只是考虑光的方向和面的方向。而反射光,则会考虑观看模型的视线和光的方向,表现出的高亮部分会非常的自然。
表示视线的向量和表示光的向量,再加上面法线向量,可以算出反射光的强度。想一下的话,就是从光源发出的光,撞到模型上发生反射,反射的光的方向如果正好和视线一致的话,这就是最强光了。如下图所示:
像这样模拟反射光,就不得不进行高负荷的计算。这里,有一个手法,可以用比较简单的处理来得到相似的结果,就是通过光向量和视线向量的中间向量来求反射光的类似效果。
使用中间向量得到的反射光的近似处理,首先求出光向量和视线向量的中间向量,然后求中间向量和面法线向量的内积,从而决定反射光的强度。
和面法线向量的内积在之前也做过了吧。在平行光源的计算的时候,就计算了光向量和面法线向量的内积。和这个处理流程是一样的,这次求一下中间向量和面法线向量的内积。这样,就可以简单的模拟反射光的效果了。
顶点着色器的修改
attribute vec3 position; attribute vec3 normal; attribute vec4 color; uniform mat4 mvpMatrix; uniform mat4 invMatrix; uniform vec3 lightDirection; uniform vec3 eyeDirection; uniform vec4 ambientColor; varying vec4 vColor; void main(void){ vec3 invLight = normalize(invMatrix * vec4(lightDirection, 0.0)).xyz; vec3 invEye = normalize(invMatrix * vec4(eyeDirection, 0.0)).xyz; vec3 halfLE = normalize(invLight + invEye); float diffuse = clamp(dot(normal, invLight), 0.0, 1.0); float specular = pow(clamp(dot(normal, halfLE), 0.0, 1.0), 50.0); vec4 light = color * vec4(vec3(diffuse), 1.0) + vec4(vec3(specular), 1.0); vColor = light + ambientColor; gl_Position = mvpMatrix * vec4(position, 1.0); }
修改javascript代码
// 将uniformLocation存入数组 var uniLocation = new Array(); uniLocation[0] = gl.getUniformLocation(prg, ‘mvpMatrix‘); uniLocation[1] = gl.getUniformLocation(prg, ‘invMatrix‘); uniLocation[2] = gl.getUniformLocation(prg, ‘lightDirection‘); uniLocation[3] = gl.getUniformLocation(prg, ‘eyeDirection‘); uniLocation[4] = gl.getUniformLocation(prg, ‘ambientColor‘);
// 视图×投影坐标变换矩阵 m.lookAt([0.0, 0.0, 20.0], [0, 0, 0], [0, 1, 0], vMatrix); m.perspective(45, c.width / c.height, 0.1, 100, pMatrix); m.multiply(pMatrix, vMatrix, tmpMatrix); // 平行光源的方向 var lightDirection = [-0.5, 0.5, 0.5]; // 视点向量 var eyeDirection = [0.0, 0.0, 20.0]; // 环境光的颜色 var ambientColor = [0.1, 0.1, 0.1, 1.0]; // (中间部分代码略) // uniform变量的写入 gl.uniformMatrix4fv(uniLocation[0], false, mvpMatrix); gl.uniformMatrix4fv(uniLocation[1], false, invMatrix); gl.uniform3fv(uniLocation[2], lightDirection); gl.uniform3fv(uniLocation[3], eyeDirection); gl.uniform4fv(uniLocation[4], ambientColor);
总结
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。