[WebGL入门]二十二,从环境光源发出的光

翻译 2014年09月06日 00:52:18

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



本次的demo的运行结果

平行光源的弱点

上次挑战了一下从平行光源发出的光。平行光源的光的方向是固定的。而且,为了模拟这些,需要用到模型变换矩阵的逆矩阵,以及需要向模型数据中加入法线情报等等。
平行光源的计算负担比较小,在一定程度上模拟了光照效果,在3D模拟世界中经常被用到。但是,平行光源也有弱点,阴面的部分,就是没有被光照到的部分是无法完美的模拟。
比如上次的demo中的定点着色器,仔细观察的话,获取光向量和法线的内积的部分,实际上是取巧的。

>上次的demo中的一部分代码

float diffuse  = clamp(dot(normal, invLight), 0.1, 1.0);
这里使用了GLSL的内置函数clamp,这个函数是将参数的数值限制到指定的范围之内,上面的代码,结果会限制在0.1 ~ 1.0之间。

但是,获取光向量和法线的内积,根据使用场合的不同,可能会出现负数,而使用了clamp函数,即使有负数,也会被指定的最小值0.1代替,假设把clamp的范围设置为0.0 ~ 1.0之间会是什么效果呢,试着运行一下的话,出现下图效果。


这样,完全没有和光发生碰撞的地方会变成完全的黑色。这样会导致无法分清楚模型的轮廓,这就是平行光源的缺点。

就像上次的demo那样,将光照系数的范围设定的大一些,在一定程度上可以解决上述问题。但是使用环境光源的话,可以彻底解决这个问题。


什么是环境光源

环境光是模拟现实世界中的自然光的漫反射。现实世界中,从太阳或是照明器械等发射出的光,遇到物体或者大气中的灰尘等遮挡而发生反射,将世界照亮。比如说,在一个漆黑的屋子里面,只需要一个灯泡,背对着灯泡的话,就会看到自己的影子映射到床或者墙壁上,而自己的身体虽然没有直接被光照到,但是也应该能看得见吧。

由于墙壁和屋顶,以及床和大气中的灰尘等对灯泡发出的光的反射,即使是没有直接被光照到的部分也会受到光的影响。这样,呈现光的漫反射的就是环境光源了。

环境光源用于照亮三维空间中的所有部分。就是说,不是根据顶点的不同处理attribute变量,而是向着色器中传递uniform变量。进一步说,环境光最终影响的是在context中输出的颜色,处理包含四个元素的颜色情报。

>定义环境光的例子

var ambientColor = [0.1,0.1,0.1,1.0];

使用环境光源的时候,需要注意颜色的亮度。环境光照的是全部,比如上面的代码中指定的0.1,如果全都换成1.0的话,模型就会变成全白了。和平行光源不一样,所以要注意。

环境光的颜色,最好是限制在0.2左右以下,这次的demo使用的是0.1。


顶点着色器和javascript的修改

接着,看一下各个代码部分的修改。先从顶点着色器开始看。

>顶点着色器代码

attribute vec3 position;
attribute vec3 normal;
attribute vec4 color;
uniform   mat4 mvpMatrix;
uniform   mat4 invMatrix;
uniform   vec3 lightDirection;
uniform   vec4 ambientColor;
varying   vec4 vColor;

void main(void){
    vec3  invLight = normalize(invMatrix * vec4(lightDirection, 0.0)).xyz;
    float diffuse  = clamp(dot(normal, invLight), 0.0, 1.0);
    vColor         = color * vec4(vec3(diffuse), 1.0) + ambientColor;
    gl_Position    = mvpMatrix * vec4(position, 1.0);
}

上次追加了一个uniform变量,就是vec4型的变量ambientColor。环境光是在平行光源等一连串的计算结束之后,最后输出颜色的阶段开始添加的。

这里,如果不使用加法而使用乘法的话,整个画面都会变暗,所以要特别注意。

接下来,修改主程序。

说起来,只是把环境光作为参数传给顶点着色器,追加的东西还是挺少的。

首先在程序中定义环境光的参数。

>增加环境光参数

var ambientColor = [0.1,0.1,0.1,1.0];

接着,为了正确的传给顶点着色器,追加获取着色器的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, 'ambientColor');

接着,作为uniform变量在持续循环的时候传给着色器就行了。

>向着色器中传送环境光的参数

gl.uniformMatrix4fv(uniLocation[0], false, mvpMatrix);
gl.uniformMatrix4fv(uniLocation[1], false, invMatrix);
gl.uniform3fv(uniLocation[2], lightDirection);
gl.uniform4fv(uniLocation[3], ambientColor);

这样,就完成了顶点着色器和javascript程序的修改了。

其实,因为这次引入了环境光源,所以平行光源部分的光照系数设定成了0.0 ~ 1.0,没有被平行光源照到的部分,就会使用纯粹的环境光来照射。


总结

环境光,模拟了自然界的光的漫反射,弥补了平行光源的缺点。一般,这两种光会同时使用。只使用环境光的话,无法表现出模型的凹凸,只使用平行光源的话,阴影过于严重无法分清模型的轮廓。

3D模拟中的扩散光的代表就是环境光和平行光。这次的demo也实现到了这一步。下次会介绍一下反射光。


点击下面的连接,可以确认一下今天的内容。

同时使用平行光源和环境光源照射的圆环体

http://wgld.org/s/sample_010/


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

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

写的太长了,果然,就算是简单点说,关于光的处理也需要很长的描述。 重点是,3D渲染中没有办法完全模拟现实中的光,只是大致是那么回事而已。 完全模拟自然界的物理学的话,计算量是非常大的,所以代替这些的就...
  • lufy_Legend
  • lufy_Legend
  • 2014-08-28 23:40:53
  • 7993

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

用点光源的光照,概念基本上和平行光源一样。根据获取光向量和顶点的法线及视点向量的内积来添加阴影。和平行光源的不同之处,简单的说就是光向量是否是一个固定值。点光源使用的是模型坐标变换后的顶点的位置和光源...
  • lufy_Legend
  • lufy_Legend
  • 2014-10-13 00:22:09
  • 6426

30 WebGL光照的概念

光照原理: 现实世界中的物体呗光纤照射时,会反射一部分光。只有当反射光纤进入你的眼睛时,你才能够看到物体并辨认出它的颜色。比如,白色的盒子会反射白光,当白光进入你的眼睛时,你才能看到盒子是白色的。 在...
  • qq_30100043
  • qq_30100043
  • 2017-06-05 10:42:44
  • 610

<Three.js>(第一节)环境搭建

Three.js顾名思义3D的js库。是运行在浏览器的基于webgl的3D引擎。该引擎是github上的一个开源项目,下载地址:https://github.com/mrdoob/three.js/1...
  • chenxiqilin
  • chenxiqilin
  • 2016-07-14 17:21:58
  • 3705

54 WebGL实现阴影效果

案例查看地址:点击这里实现阴影的基本思想是:太阳看不见阴影。如果在光源处放置以为观察者,其视线方向与光线一致,那么观察者也看不到阴影。他看到的每一处都在光的照射下,而那些背后的,他没有看到的物体则处在...
  • qq_30100043
  • qq_30100043
  • 2017-06-27 13:54:33
  • 1020

webgl--平面阴影效果

在特定的3D场景中,阴影效果有时还是显得十分重要的,在一般的3D引擎当中设置阴影可以直接通过对物体设置属性来实现,十分的方便,这里我们就用webgl来实现一下平面效果。         平面阴影是通过...
  • srk19960903
  • srk19960903
  • 2017-07-04 10:45:21
  • 370

33 WebGL运动中的物体的光照效果(逆转置矩阵)

案例查看地址:点击这里很多场景中,物体有可能会动,观察者的视角也很有可能会改变,我们必须考虑这种情况。首先,我们先看一下物体变动时,法向量的情况:~平移变换不会改变法向量,因为平移不会改变物体的方向。...
  • qq_30100043
  • qq_30100043
  • 2017-06-08 11:42:10
  • 471

OpenGL ES之glUniform函数

函数名: glUniform 功能: 为当前程序对象指定Uniform变量的值。(译者注:注意,由于OpenGL ES由C语言编写,但是C语言不支持函数的重载,所以会有很多名字相同后...
  • wangyuchun_799
  • wangyuchun_799
  • 2012-07-13 09:38:11
  • 36929

Three.JS 添加灯光、材质和阴影(第一个例子)

three.js中都多种灯光和材质,这里只是添加了一种灯光,聚光灯spotLight。首先构建一个spotLight对象:var spotLight = new THREE.SpotLight(0x...
  • bullzerone
  • bullzerone
  • 2017-07-16 13:38:26
  • 1012

03.ThreeJs开发指南-第三章-光源

第三章环境光:AmbientLight 点光源:PointLight 聚光灯:SpotLight 方向光:DirectionalLight:无限光,例如太阳光,平行光 半球光:Hemisphe...
  • birdflyto206
  • birdflyto206
  • 2016-09-02 15:16:59
  • 1927
收藏助手
不良信息举报
您举报文章:[WebGL入门]二十二,从环境光源发出的光
举报原因:
原因补充:

(最多只允许输入30个字)