[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);
向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);
// 获取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入门]二,开始WebGL之前,先了解一下canvas
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指 ...
- opencv函数findcontours_OpenCV系列之轮廓入门 | 二十一
目标 了解轮廓是什么. 学习查找轮廓,绘制轮廓等. 你将看到以下功能:cv.findContours(),cv.drawContours() 什么是轮廓? 轮廓可以简单地解释为连接具有相同颜色或强度的 ...
- [WebGL入门]二十六,纹理绘图
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指 ...
- WebGL入门(二十)-三维视图通过透视投影矩阵创建远小近大的两排三角形
通过透视投影矩阵创建远小近大的两排三角形 1.demo效果 2.相关知识点 2.1 透视投影 2.2 Matrix4.setPerspective()函数 3. demo代码 1.demo效果 如上, ...
- OpenCV系列之轮廓入门 | 二十一
目标 了解轮廓是什么. 学习查找轮廓,绘制轮廓等. 你将看到以下功能:cv.findContours(),cv.drawContours() 什么是轮廓? 轮廓可以简单地解释为连接具有相同颜色或强度的 ...
- [WebGL入门]二十八,纹理参数
注:文章译自http://wgld.org/,原作者杉本雅広(doxas) 本次demo的效果 lufy:先啰嗦几句,真是好几年没写博客了,以后的工作要重新接触HTML5开发了,虽然没有以前那样强烈的 ...
- [WebGL入门]二十,绘制立体模型(圆环体)
注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指 ...
- CarSim仿真快速入门(二十一)-CarSim: 车轮箭头动画和其他指示动画
CarSim2022中的动画是:车轮箭头和其他指标界面用于定义一组轮胎力或其他感兴趣的变量的视觉动画指标,这些指标在仿真车辆的每个车轮.轮胎或车轴上重复出现. 所有VehicleSim(VS)产品都包 ...
- conan入门(二):conan 服务配置-密码管理及策略
conan 服务配置 密码管理及策略配置 第一次以管理员身份(admin)使用默认密码(password)WEB登录入JFrog Artifactory后台时,系统就提示要求我修改密码,因为现有密码太 ...
- conan入门(二十):封装只包含头文件(header_only)的库示例
conan: 封装只包含头文件(header_only)的库示例 有的C/C++项目只包含头文件,不需要编译,对于这种情况如何封装为Conan的包呢? Conan官方文档 <Package sc ...
最新文章
- vscode前端开发中的快捷键说明
- 程序员常用的六大技术博客类
- MySQL5.7 : 对隐式锁转换的优化
- 转载: Vim 练级攻略
- 织梦cms技巧:织梦登录后台显示空白页的解决办法
- CF809C Find a car
- 远程图片保存到服务器 php,保存远程图片到本地服务器几种方法[php,asp]网
- vim的一些基本应用
- jQuery的datatable的destroy属性,和$(#test).dataTable().fnDestroy();区别,两者的区别
- [第一章]一、面向对象思想的发展
- transformer模型_【预训练模型】万字长文梳理NLP预训练模型!从transformer到albert...
- WAP PUSH解析(2)——WSP以及WBXML编码
- 美国邮编大全及邮政编码规范
- java应用程序由若干个_Java应用程序由若干个类所构成,这些类可以在一个源文件中,也可以分布在若干个源文件中。...
- Android破解九宫格密码
- html5 图片羽化,课题:html5图像羽化(不规则区域羽化,feather,html5羽化)
- VC中常见的108个问题
- 什么是TCP粘包?为什么UDP没有粘包?
- 使用ftp服务上传文件时553报错的解决(绝对有用)
- 基于遗传算法的电动汽车有序充放电优化问题