[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 属性来完 ...
随机推荐
- postgresql遇到的性能问题
问题SQL scwksmlcls.wk_cls_c , scwklrgcls.wk_lrg_cls_nm , scwkmdlcls.wk_mdl_cls_nm , scwksmlcls.wk_sml_ ...
- MS-DOS Batch Script Template
@echo off @setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION @rem Name: @rem Purpose: @rem @rem Autho ...
- The Runtime Interaction Model for Views-UI布局事件处理流程
The Runtime Interaction Model for Views Any time a user interacts with your user interface, or any t ...
- time模块,补上之前拉下的作业。
time,时间模块比较重要,但不难学,主要是要学会转换时间格式.计算机的时间都是时间戳.人是看不懂的.写出时间转换的固定格式语句.import time # 首先就是引入时间模块. time.ti ...
- JavaScript--小白入门篇2
一.布尔值和关系运算符.逻辑运算符 1.1 布尔值 我们上篇文章说了,学习了两种变量的类型数值型.字符串型. 实际上,还有很多变量的类型.我们今天再学习一种,叫做“布尔类型”. 数值型里面的值 ...
- UVA - 808 Bee Breeding (建立坐标系&找规律)
题目: 输入两个格子的编号a和b(a,b≤10000),求最短距离.例如,19和30的距离为5(一条最短路是19-7-6-5-15-30). 思路: 如图建立坐标系,然后看两个点的向量如果位于二四象限 ...
- docker插件
import docker c = docker.Client(base_url='unix://var/run/docker.sock',version='1.15',timeout=10) pri ...
- * average vector from multiple files--Matlab
n=359;a=[];b=[];c=[];% for loopfor i=1:n filename=sprintf('output_%d.dat',i); fileinfo = imp ...
- 洛谷 1328 生活大爆炸版石头剪刀布(NOIp2014提高组)
[题解] 简单粗暴的模拟题. #include<cstdio> #include<algorithm> #include<cstring> #define LL l ...
- [bzoj1878][SDOI2009][HH的项链] (莫队算法)
Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变 ...