[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 属性来完 ...
随机推荐
- Android 仿微信调用第三方应用导航(百度,高德、腾讯)
实现目标 先来一张微信功能截图看看要做什么 其实就是有一个目的地,点击目的地的时候弹出可选择的应用进行导航. 大脑动一下,要实现这个功能应该大体分成两步: 底部弹出可选的地图菜单进行展示 点击具体菜 ...
- 解决安装androidstudio无法查看源代码的问题
如果androidstudio的sdk是自己导入的,则可能会有查看不了源代码的原因.原因是默认目录中没有这个api的源代码. 1.先在C:\Users\xxx\.AndroidStudio2.3\co ...
- dubbo之服务容器
服务容器是一个standalone的启动程序,因为后台服务不需要Tomcat或JBoss等Web容器的功能,如果硬要用Web容器去加载服务提供方,增加复杂性,也浪费资源. 服务容器只是一个简单的Mai ...
- HDU_2476_String painter_(区间dp)
String painter Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- Android(java)学习笔记204:JNI之native方法头文件的生成
1. JDK1.6 ,进入到工程的bin目录下classes目录下: 使用命令: javah packageName.ClassName 会在当前目录下生成头文件,从头文件找到jni协议方法 下面举 ...
- java_IO_1
public class DirStudy { public static void main(String[] args) { File file = new File("F:/Eclip ...
- input password密码验证跳转页面
代码如下: 查询密码 <input type="password" id="pwd" /> 页面如下: 密码校验成功后跳转页面: window.lo ...
- (转)vim编辑器操作命令大全-绝对全
周六了,熟悉熟悉vim 命令 学习链接: vim命令大全 http://blog.csdn.net/scaleqiao/article/details/45153379 vim命令小技巧 http:/ ...
- springAOP源码解析-190313
Spring相关笔记 SpringAOP讲解 子路老师讲解 spring与aspectj的区别答:它们的区别是 spring是动态加载 aspectj是静态加载,再编译过程就已经实现切面,此时会往代码 ...
- css--小白入门篇2
一.css基础选择器 html负责结构,css负责样式,js负责行为. css写在head标签里面,容器style标签. 先写选择器,然后写大括号,大括号里面是样式. 1 <style type ...