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

照亮世界
光的模拟

处理光的时候,在原来的RGBA的值上乘与对应的系数。这个系数的范围也是0 ~ 1 之间,有光的一面,显示为原色相近的状态。而背光的一面则使用较暗的颜色。
什么是平行光源

法线向量和光向量


仅仅要准备好正确的数据。剩下的计算交给WebGL即可了。
定向灯的着色器
attribute vec3 position;
attribute vec3 normal;
attribute vec4 color;
uniform mat4 mvpMatrix;
uniform mat4 invMatrix;
uniform vec3 lightDirection;
varying vec4 vColor; void main(void){
vec3 invLight = normalize(invMatrix * vec4(lightDirection, 0.0)).xyz;
float diffuse = clamp(dot(normal, invLight), 0.1, 1.0);
vColor = color * vec4(vec3(diffuse), 1.0);
gl_Position = mvpMatrix * vec4(position, 1.0);
}
什么是逆矩阵呢?
这次在顶点着色器中加入的invMatrix是用来保存模型坐标变换矩阵的逆矩阵的变量,预计大多数人都不知道什么叫做逆矩阵吧。
平行光源发出的光(定向灯发出的光)通常须要光向量,三维空间中的全部的模型都被同一方向的光照耀。可是,试想一下。通过模型坐标变换。能够对模型的放大缩小,旋转。移动。假设仅仅通过法线和光向量进行计算的话,会受到光的方向。位置,模型的方向,位置等的影响。
本来正确的光的位置和方向。由于受到模型坐标变换的影响,就得不到正确的结果了。因此,通过对模型的坐标变换进行全然的逆变换,来抵消模型坐标变换的影响。
模型沿着x轴旋转45度的话,就向反方向旋转45度,这样就抵消了旋转。模型即使发生了旋转,光源位置和光的方向也能够固定。相同,对模型进行缩放的话,是矩阵相乘运算,能够通过和逆矩阵相乘来抵消。
这样,就须要为光准备一个模型坐标变换矩阵的逆矩阵,在minMatrix.js中提供了生成逆矩阵的函数,本站点使用它来进行光的计算。
|
vec3 invLight = normalize(invMatrix * vec4(lightDirection, 0.0)).xyz;
float diffuse = clamp(dot(normal, invLight), 0.1, 1.0);
vColor = color * vec4(vec3(diffuse), 1.0);
使用这个函数,将模型坐标变换的逆矩阵和光向量相乘的结果进行标准化。模型进行了旋转等坐标变换的话,也能够通过逆变换来抵消。这个计算的后面还有个.xyz,这个是为了把变换结果作为正确的三维向量来代入。
事实上这里是求法线和光向量的内积。这里出现的clamp和dot都是GLSL的内置函数,clamp是将值限制在一定的范围内,第二个參数是最小值,第三个參数是最大值。
之所以要限制范围。是由于向量的内积可能出现负数值。为了防止这样的情况而进行的处理。
向VBO中追加法线信息
// 生成圆环体的函数
function torus(row, column, irad, orad){
var pos = new Array(), nor = new Array(),
col = new Array(), idx = new Array();
for(var i = 0; i <= row; i++){
var r = Math.PI * 2 / row * i;
var rr = Math.cos(r);
var ry = Math.sin(r);
for(var ii = 0; ii <= column; ii++){
var tr = Math.PI * 2 / column * ii;
var tx = (rr * irad + orad) * Math.cos(tr);
var ty = ry * irad;
var tz = (rr * irad + orad) * Math.sin(tr);
var rx = rr * Math.cos(tr);
var rz = rr * Math.sin(tr);
pos.push(tx, ty, tz);
nor.push(rx, ry, rz);
var tc = hsva(360 / column * ii, 1, 1, 1);
col.push(tc[0], tc[1], tc[2], tc[3]);
}
}
for(i = 0; i < row; i++){
for(ii = 0; ii < column; ii++){
r = (column + 1) * i + ii;
idx.push(r, r + column + 1, r + 1);
idx.push(r + column + 1, r + column + 2, r + 1);
}
}
return [pos, nor, col, idx];
}
// 获取attributeLocation并放入数组
var attLocation = new Array();
attLocation[0] = gl.getAttribLocation(prg, 'position');
attLocation[1] = gl.getAttribLocation(prg, 'normal');
attLocation[2] = gl.getAttribLocation(prg, 'color'); // 将attribute的元素个数保存到数组中
var attStride = new Array();
attStride[0] = 3;
attStride[1] = 3;
attStride[2] = 4; // 生成圆环体的顶点数据
var torusData = torus(32, 32, 1.0, 2.0);
var position = torusData[0];
var normal = torusData[1];
var color = torusData[2];
var index = torusData[3]; // 生成VBO
var pos_vbo = create_vbo(position);
var nor_vbo = create_vbo(normal);
var col_vbo = create_vbo(color);
而为了在顶点着色器中接收法线信息。声明了一个attribute类型的变量。所以不要忘了获取attributeLocation。
// 获取uniformLocation并保存到数组中
var uniLocation = new Array();
uniLocation[0] = gl.getUniformLocation(prg, 'mvpMatrix');
uniLocation[1] = gl.getUniformLocation(prg, 'invMatrix');
uniLocation[2] = gl.getUniformLocation(prg, 'lightDirection');
加入关于光的处理
// 各矩阵的生成和初始化
var mMatrix = m.identity(m.create());
var vMatrix = m.identity(m.create());
var pMatrix = m.identity(m.create());
var tmpMatrix = m.identity(m.create());
var mvpMatrix = m.identity(m.create());
var invMatrix = m.identity(m.create()); // 视图x投影坐标变换矩阵
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];
// 计数器自增
count++; // 用计数器计算角度
var rad = (count % 360) * Math.PI / 180; // 模型坐标变换矩阵的生成
m.identity(mMatrix);
m.rotate(mMatrix, rad, [0, 1, 1], mMatrix);
m.multiply(tmpMatrix, mMatrix, mvpMatrix); // 依据模型坐标变换矩阵生成逆矩阵
m.inverse(mMatrix, invMatrix); // uniform变量
gl.uniformMatrix4fv(uniLocation[0], false, mvpMatrix);
gl.uniformMatrix4fv(uniLocation[1], false, invMatrix);
gl.uniform3fv(uniLocation[2], lightDirection);
总结
[WebGL入门]二十一,从平行光源发出的光的更多相关文章
- [WebGL入门]二十三,反射光的光照效果
注:文章译自http://wgld.org/,原作者杉本雅広(doxas).文章中假设有我的额外说明.我会加上[lufy:],另外,鄙人webgl研究还不够深入.一些专业词语.假设翻译有误.欢迎大家指 ...
- [WebGL入门]二十五,点光源的光照
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明.我会加上[lufy:].另外,鄙人webgl研究还不够深入,一些专业词语.假设翻译有误,欢迎大家指 ...
- [WebGL入门]二,開始WebGL之前,先了解一下canvas
年2月)HTML5依旧处于草案阶段. HTML5支持网页端的多媒体功能和画布功能,追加了非常多全新的更合理的Tag标签.各个浏览器也都在逐渐的完好这些新的特性. Canvas对象表示一个 HTML画布 ...
- Android入门(二十一)解析XML
原文链接:http://www.orlion.ga/685/ 解析XML常用的方式有两种,一种是PULL解析一种是SAX解析. 假设解析数据为: <apps> <app> ...
- [WebGL入门]二十四,补色着色
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,假设翻译有误,欢迎大家指 ...
- OpenCV-Python 轮廓:入门 | 二十一
目标 了解轮廓是什么. 学习查找轮廓,绘制轮廓等. 你将看到以下功能:cv.findContours(),cv.drawContours() 什么是轮廓? 轮廓可以简单地解释为连接具有相同颜色或强度的 ...
- WebGL入门教程(二)-webgl绘制三角形
前面已经介绍过了webgl,WebGL入门教程(一)-初识webgl(http://www.cnblogs.com/bsman/p/6128447.html),也知道了如何绘制一个点,接下来就用web ...
- 无废话ExtJs 入门教程二十一[继承:Extend]
无废话ExtJs 入门教程二十一[继承:Extend] extjs技术交流,欢迎加群(201926085) 在开发中,我们在使用视图组件时,经常要设置宽度,高度,标题等属性.而这些属性可以通过“继承” ...
- Bootstrap入门(二十一)组件15:警告框
Bootstrap入门(二十一)组件15:警告框 通过这些简单.灵活的进度条,为当前工作流程或动作提供实时反馈. 进度条组件使用了 CSS3 的 transition 和 animation 属性来完 ...
随机推荐
- git 删除分支如何恢复
强制删除了一个分支而后又想重新使用这个分支,该怎么找回该分支上的代码呢? 一:问题描述: 今天师父说上线几个功能,让我把开发的分支推送到远程.当打开git就傻眼了,之前开发好的分支被我删除了,就连推送 ...
- LR接口测试---Java Vuser之增删改查
import lrapi.lr; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Prepared ...
- Wrapping calls to the Rational Functional Tester API——调用Rational Functional Tester封装的API
转自:http://www.ibm.com/developerworks/lotus/library/rft-api/index.html The Rational GUI automation to ...
- dbcp数据源配置
<bean id="dbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource" de ...
- 梦想CAD控件事件COM接口知识点
一.鼠标事件 _DMxDrawXEvents::MouseEvent 控件中的鼠标事件. 参数 说明 LONG lType 事件类型,1鼠标移动,2是鼠标左键按下,3是鼠标右键按下,4是鼠标左键双击 ...
- java基础学习之垃圾回收机制
回收过程: 1.发现无用的对象 2.回收无用对象占用的内存的空间. 垃圾回收相关算法: 1.引用计数法 堆中每个对象都有一个引用计数.被引用一次,计数加一.被引用变量值变为null,则计数减一. 到计 ...
- Openstack manila的一些命令
(本文是测试环境进行的操作:) 1.查看一些信息: [root@openstackcontroller ~]# manila type-list [root@openstackcontroller ~ ...
- Linux:DNS主、从、缓存服务器配置、DNS同步加密TSIG配置、DNS分离解析配置
DNS主服务器配置(正向解析.反向解析) 正向解析:根据主机名查找对应的IP地址.当用户访问一个域名时(不考虑hosts文件等因素),正常情况会向指定的DNS主机发送递归查询请求反向解析:根据IP地址 ...
- Linux学习笔记(二) 文件管理
了解 Linux 系统基本的文件管理命令可以帮助我们更好的使用 Linux 系统,以下介绍几个常用的文件管理命令 1.pwd pwd 是 Print Working Directory 的简写,用于显 ...
- 基于 Ubuntu 搭建 FTP 文件服务
搭建 FTP 文件服务 安装并启动 FTP 服务 任务时间:5min ~ 10min 安装 VSFTPD 使用 apt-get 安装 vsftpd: sudo apt-get install vsft ...