注:文章译自http://wgld.org/,原作者杉本雅広(doxas)。文章中假设有我的额外说明。我会加上[lufy:],另外,鄙人webgl研究还不够深入。一些专业词语。假设翻译有误。欢迎大家指正。

本次的demo的执行结果

各种各样的光照

上次,以及上上次,介绍了通过顶点着色器来实现光照效果。

最開始介绍了从平行光源发出的光。上次介绍了平行光源的缺点。以及相应这个缺点的方法,就是环境光源。
这次是光照处理的第三篇。进一步介绍反射光照。
反射光和它的名字一样,就是模拟光的反射。通过反射光。能够让3D场景更加的真实。

详细点儿说,反射光能够让模型呈现出光泽。就像金属那样,有光滑质感的表面。所以反射光的作用是很大的。

顺便说一下。specular直接翻译的话。是镜面反射,就是像镜子那样反射的意思。

反射光的概念

从平行光源发出的扩散光的光照,通过光的方向(光向量)和面的方向(面法线向量),来计算这个面的扩散程度,从而实现光照。

光照最强的地方就是模型的颜色,反之,没有被光照到的地方。就会变成暗色。

可是,像金属那样的质感,就是光泽的表现。仅仅用扩散光就不够了。

为什么呢。光照最强的部分,也仅仅只是是显示了模型的原来的颜色,要想表现出光泽。则须要表现一下高亮这种强光效果。

改动顶点着色器,仅仅通过扩散光尽管也能够实现高亮效果,可是大部分场合都会感觉不自然。这是由于扩散光是不会考虑视线的。扩散光,仅仅是考虑光的方向和面的方向。而反射光。则会考虑观看模型的视线和光的方向,表现出的高亮部分会很的自然。

表示视线的向量和表示光的向量,再加上面法线向量,能够算出反射光的强度。想一下的话,就是从光源发出的光。撞到模型上发生反射,反射的光的方向假设正好和视线一致的话,这就是最强光了。例如以下图所看到的:

像这样模拟反射光。就不得不进行高负荷的计算。

这里,有一个手法,能够用比較简单的处理来得到类似的结果,就是通过光向量和视线向量的中间向量来求反射光的类似效果。

使用中间向量得到的反射光的近似处理。首先求出光向量和视线向量的中间向量,然后求中间向量和面法线向量的内积,从而决定反射光的强度。

和面法线向量的内积在之前也做过了吧。

在平行光源的计算的时候,就计算了光向量和面法线向量的内积。

和这个处理流程是一样的,这次求一下中间向量和面法线向量的内积。

这样。就能够简单的模拟反射光的效果了。

顶点着色器的改动

这次和上次一样。全都在顶点着色器中进行计算,将终于计算的颜色情报传给片段着色器。
>顶点着色器的代码
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);
}
这次没有添加attribute变量。而是添加了表示视线向量的uniform变量eyeDirection,视线向量并非每一个顶点情报都不同,全部的顶点都是一致的处理,所以使用了uniform修饰符。
和平行光源发出的扩散光原理一样。使用模型坐标变换矩阵的逆矩阵来对视线向量进行变换,变换之后的视线向量和光向量的中间向量保存到halfLE中。然后和面法线向量求内积,进行光反射计算。
这里新出现了一个内置函数,就是给变量specular赋值的时候的时候使用的函数pow,这个函数是用来求幂的,比方2的平方,2的三次方等计算。
由于反射光是为了体现强光照耀,依据内积得到的结果进行求幂运算,然后限制结果范围。由内积得到的结果用clamp函数将范围限制在0.0 ~ 1.0。求幂之后,小的数。会变的越来越小,而最强光的状态就是1,不管求多少次幂,也依旧是1。

反射光依据求幂运算,让弱光的效果更弱。而强光的效果则不变。

这样。就更能体现强光的反射效果。另外,减少求幂的次数,则会将该部分的亮点覆盖的范围会变大,要实现局部闪烁等效果的时候。适当的对求幂的次数进行控制就能实现了。

反射光的强度系数的使用和环境光的原理同样。所以颜色部分也使用加法运算。终于的颜色计算公式例如以下。
颜色=顶点颜色 * 扩散光 + 反射光 + 环境光
注意仅仅有顶点颜色和扩散光的计算是乘法。

改动javascript代码

接着改动基本的代码部分。
顶点着色器做了几个比較复杂的改动,可是改动并不算多。主要是利用uniform变量来传入视线向量的处理。
>取得uniformLocation的处理
// 将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');
取得正确的uniformLocation之后,再定义视线向量并传给着色器。基本上。把在生成视图坐标变换矩阵的时候所指定的镜头的坐标,当作视线向量就能够了。(镜头的注视点是原点)
>视线向量的定义和写入
// 视图×投影坐标变换矩阵
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);
视线向量在着色器中是有三个元素的vec3,所以用uniform3fv函数传给着色器。这次的demo和光向量是一样的,所以视线向量也在持续循环的时候处理。

总结

好了。反射光相关的知识已经基本理解了吧。
与眼下为止所涉及到的算法相比,今天的算法也不算难,就是。计算从光源发出的光向量和视线向量之间的半向量,然后与面法线向量求内积,所以相对的负荷也不大。可是,这仅仅是在一定程度上模拟了反射光的效果,并非很严格的反射光的计算。
从渲染的结果来看,圆环体已经变的很美丽了,实际的效果,请參考文章最后给出的链接。
下一回,介绍一下高氏着色和补色着色。
用扩散光。环境光以及反射光渲染的demo

转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

[WebGL入门]二十三,反射光的光照效果的更多相关文章

  1. [WebGL入门]二十四,补色着色

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...

  2. [WebGL入门]二十五,点光源的光照

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明.我会加上[lufy:].另外,鄙人webgl研究还不够深入,一些专业词语.假设翻译有误,欢迎大家指 ...

  3. [WebGL入门]二十一,从平行光源发出的光

    注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明.我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语.假设翻译有误,欢迎大家指 ...

  4. [WebGL入门]二,開始WebGL之前,先了解一下canvas

    年2月)HTML5依旧处于草案阶段. HTML5支持网页端的多媒体功能和画布功能,追加了非常多全新的更合理的Tag标签.各个浏览器也都在逐渐的完好这些新的特性. Canvas对象表示一个 HTML画布 ...

  5. WebGL入门教程(二)-webgl绘制三角形

    前面已经介绍过了webgl,WebGL入门教程(一)-初识webgl(http://www.cnblogs.com/bsman/p/6128447.html),也知道了如何绘制一个点,接下来就用web ...

  6. WPF入门教程系列二十三——DataGrid示例(三)

    DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...

  7. Bootstrap入门(二十三)JS插件1:模态框

    Bootstrap入门(二十三)JS插件1:模态框 1.静态实例 2.动态实例 3.模态框的尺寸和效果 4.包含表单的模态框 模态框经过了优化,更加灵活,以弹出对话框的形式出现,具有最小和最实用的功能 ...

  8. WebGL入门教程(五)-webgl纹理

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 WebGL入门教程(四)-webgl颜色 这里就需要用到 ...

  9. WebGL入门教程(四)-webgl颜色

    前面文章: WebGL入门教程(一)-初识webgl WebGL入门教程(二)-webgl绘制三角形 WebGL入门教程(三)-webgl动画 颜色效果图: 操作步骤: 1.创建HTML5 canva ...

随机推荐

  1. 解决eclipse用maven install打包报错问题:-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.

    1.添加M2_HOME的环境变量 2.Preference->Java->Installed JREs->Edit 选择一个jdk, 添加  -Dmaven.multiModuleP ...

  2. phpstorm如何在同一个文件夹打开多个目录

    phpstorm默认一个窗口只显示一个项目,如果新建一个项目,他会给你个选项卡,问你是在新窗口打开新项目还是在本窗口打开. 能不能在一个窗口打开多个项目呢?就像sublime text那样,其实是可以 ...

  3. wordpress 你所不知道的固定链接设置方法,设置适合自己的个性固定链接,适合SEO

    %year% 年份,四位数字,例如2004年  %monthnum% 一年的月份,例如05  %day% 一个月的日子,例如28  %hour% 一天中的小时,例如15  %minute% 小时,例如 ...

  4. [Windows Server 2008] 安装PHP+MySQL方法

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:PHP+MyS ...

  5. 史上巨坑: vim的"set foldmethod=syntax"设置竟然是导致ctrl+p(ctrl+n)补全在文件稍大时光标位于中间位置补全效率变慢的元凶!

    最近我的vim又让我闹心了. 问题出现在supertab的补全速度上, 有时候按下tab键半天才弹出补全列表, 即便是弹出了列表在列表上下移动也变得的相当缓慢, 这让我的很是蛋疼. 在完全无法接受这个 ...

  6. (转) Hibernate框架基础——操纵持久化对象的方法(Session中)

    http://blog.csdn.net/yerenyuan_pku/article/details/52761021 上一篇文章中我们学习了Hibernate中java对象的状态以及对象的状态之间如 ...

  7. CentOS 7 不能连接网路的解决方法

    ---恢复内容开始--- 刚安装的CentOS7 是不能连接网络的,更不能使用yum 进行应用的安装 (1)通过ip addr或者是 ifconfig获取需要编辑的文件名 (2)vi /etc/sys ...

  8. PAT_A1003#Emergency

    Source: PAT A1003 Emergency (25 分) Description: As an emergency rescue team leader of a city, you ar ...

  9. Nginx +tomcat 实现负载均衡集群

    一.       工具   nginx-1.8.0 apache-tomcat-6.0.33 二.    目标   实现高性能负载均衡的Tomcat集群: 三.    步骤   1.首先下载Nginx ...

  10. [Luogu] P3907 圈的异或

    题目描述 给出无向图G,边 (Ai,Bi)的权是Ci,判断下列性质是否成立: 对于任意圈C,其边权的异或和是0 输入输出格式 输入格式: 第1 行,1 个整数T,表示数据的组数. 每组数据第1 行,2 ...