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

注:文章译自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

时间: 2024-10-13 10:07:15

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

【Git入门之十二】DIY Git

[Git入门之十二]DIY Git - JackyStudio - 博客频道 - CSDN.NET Git的配置是很有学问的,如果弄懂它,将对你帮助很大. 1.用户配置 这是全局的. ? [cpp]?view plaincopy ? #设置用户名?? $Snbsp;git?config?--global?user.name?"Jacky"?? ?? #设置邮箱?? $Snbsp;[email protected]?? ? 2.设置默认编辑器 在需要输入文本信息时调用,比如之前的reba

Swift入门(十二)——利用Extension添加逆序输出字符串方法

Swift好像没有自带逆序输出字符串的方法,于是决定通过拓展(Extension)给String类添加一个逆序输出字符串的reverse方法. 首先新建一个Swift文件,命名规则不太清楚,于是暂且模仿OC叫做String+Operation吧,然后实现我们需要拓展的方法.下面先贴上代码,然后解释一下这段代码. //String+Operation.swifft import Foundation //逆序输出swift中的字符串 extension String{ func Reverse()

UWP入门(十二)--数据绑定用法

原文:UWP入门(十二)--数据绑定用法 主要几个元素: Template DataTemplate ItemSource 数据绑定是一个数据提取的方法,能使数据和UI上的控件紧密相连,下面的Demo是这样的: 有许多书的集合,书 类中有图片.标题.作者和ID,把它成现在GridView 控件上,每次点击GridView 的时候动态显示书本信息 github 代码 效果图: 原理图: 1. Template 为GridView 创建一个Template,决定每个独立的图书对象如何呈现在屏幕上 <

Project Server 2013新手入门 (十二)特定工作组

很多时候我们需要那种分层次的组织结构来个部门分配任务,然后部门领导再给员工分配任务,这里就用到了了一个功能特定工作组.而创建一个全新的工作组的话,就要用到查阅表格. 1.新建查阅表格 1)在PWA中,选择"服务器设置",在"企业数据"下,选择"企业自定义域和查阅表格". 2)在"企业自定义域和查阅表格"页面,选择"自定义域的查阅表格"(如果企业自定义域比较多可能得向下翻阅滚动条才能找到) 3)在出现的页面中

我的编程之路(二十) 新的环境、新的开始

被其他项目组借用了三个星期,这周终于要给自己的项目组干活了,之前就听同事说过省厅,这次终于要去了,有点激动哈: 1.挤公交 星期二跟着同事一起去省厅,那个公交呀,真是挤呀,以前还庆幸自己上班不用挤公交呢,唉~~~看来这一个多月都要重复着早上7点20起床,7点50挤半个多小时公交的生活了~~~ 2.同事 还记得刚来公司的时候,强哥就跟我说,zqq(一个女生)就做的很好,对自己要求很高,一直在省厅那边,上次我们项目组聚会,第一次见到本人,也见到不少其他同事,那次还自己把自己灌醉了,幸亏宝强哥把我送了

(转)Inno Setup入门(十二)——Pascal脚本(1)

本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17250917 事件函数(1) Inno Setup支持以下函数和过程. function InitializeSetup(): Boolean; 该函数在安装程序初始化时调用,返回False 将中断安装,True则继续安装,测试代码如下: function InitializeSetup(): Boolean; begin Result := MsgBox('安装程

(转)Inno Setup入门(二十二)——Inno Setup类参考(8)

本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17268473 列表框 列表框(ListBox)是Windows应用程序中重要的输入手段,其中包括多个选项用户可以从其中选择一个或者多个,程序根据用户的选择做出相应的处理,列表框在外观上和存储框类似,但是行为却有很大的不同,列表框中项一般是预先给定的,而存储框则可以让用户进行输入,并且列表框中的项被选择之后也会触发事件.Pascal脚本中列表框的类由TlistBox实

Python3快速入门(十二)——NumPy

Python3快速入门(十二)--NumPy 一.NumPy简介 1.NumPy简介 NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,同时对数组运算提供了大量的数学函数库.Numpy 是一个运行速度非常快的数学库,内部解除了CPython的GIL(全局解释器锁),运行效率极好,主要用于数组计算,是大量机器学习框架的基础库,NumPy主要包括如下:(1)强大的N维数组对象 ndarray(2)广播功能函数(3)整合 C/C++/

【管理心得之二十二】小人物 仰视 大授权

场景再现====================Boss:小王,来我办公室一下.小王: 嗯Boss:近期总公司有会,需要到外地出差几日.我不在的这段期间里,公司大小事务你帮忙处理一下.          如果有什么难决定的事,第一时间电话.邮件联系我商定即可.小王:  明白.放心吧领导,绝不会让你失望的Boss:嗯,那就好,没事了. {小王走出办公室} 心中暗喜,"难道这就是传说中的授权,Boss不在的时候,我岂不是最高权力的行使者." ==================== 从场景