1.demo效果


此效果是上一章绘制的立方体基础上,向Y轴方向平移一个单位,然后绕Z轴旋转30度。

如上图,归纳一下物体坐标变换法向量变化的规律如下

  • 平移变换, 法向量不会改变
  • 旋转变换, 大多数情况下法向量会变 ,如果绕某个轴旋转360度,又回到原点,法向量自然不变
  • 缩放变换, 法向量可能会变 ,如果物体在X轴、Y轴、Z轴上的缩放比例不一致,会导致物体形状的改变,自然也会改变法向量,如果在所有轴上的缩放比例一样,那法向量也不会变

2.矩阵逆转置

上面我们学习了物体变幻时法向量如何变化,那变化后的法向量如何计算呢?有强大的矩阵运算助力,实现变成一件很简单的事,只需要用原法向量乘以变换模型矩阵的逆转只矩阵即可,用公式表示如下。
<变换后的法向量> = <原法向量> x <模型矩阵的逆转置矩阵>

Matrix4对象为我们提供了获取模型矩阵的逆转置矩阵的方法,相关方法如下

方法/属性名称 描述
Matrix4.setInverseOf(m) 使自身称为矩阵m的逆矩阵
Matrix4.transpose() 对自身进行转置操作,并将自身设置为转置后的结果

3.demo代码

//Chapter 08
//temp 03//绘制一个立方体
// => 运动中的光照效果
// 加上逆转置变化法向量var VSHADER_SOURCE = `attribute vec4 a_Position;attribute vec4 a_Color;uniform mat4 u_VpMatrix; //view and range matuniform mat4 u_ModelMatrix; //model matuniform mat4 u_ReverseModelMat; //模型矩阵的逆转置attribute vec4 a_Normal; //法向量uniform vec3 u_LightColor; //平行光uniform vec3 u_LightDirection; //光照方向 //=归一化后的世界坐标uniform vec3 u_AmbientLight; // 环境光varying vec4 v_Color;void main() {gl_Position = u_VpMatrix * u_ModelMatrix * a_Position;//漫反射光颜色//法向量进行归一化vec3 normal = normalize(vec3(u_ReverseModelMat * a_Normal));//计算cos入射角 当角度大于90 说明光照在背面 赋值为0float nDotLight = max(dot(u_LightDirection, normal), 0.0);//计算反射光颜色vec3 diffuse = u_LightColor * vec3(a_Color) * nDotLight;// 环境反射光颜色vec3 ambient = u_AmbientLight * a_Color.rgb;v_Color = vec4(diffuse + ambient, a_Color.a);}
`;var FSHADER_SOURCE = `precision mediump float;varying vec4 v_Color;void main() {gl_FragColor = v_Color;// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}
`;ready(loadWEBGL);function loadWEBGL() {var canvas = document.getElementById('webgl');var webgl = canvas.getContext('webgl');if ( !initShaders(webgl, VSHADER_SOURCE, FSHADER_SOURCE) ) {console.log(new Error('failed to init shaders!'));return ;}var viewMat = new Matrix4().setLookAt(7, 2.5, 6, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);// var modelMat = new Matrix4().setIdentity();var modelMat = new Matrix4().setTranslate(0, 1, 0).rotate(30, 0, 0, 1);var projMat = new Matrix4();projMat.setPerspective(30, canvas.width/canvas.height, 1.0, 100);var vpMat = new Matrix4().setIdentity().multiply(projMat).multiply(viewMat);var u_VpMatrix = webgl.getUniformLocation(webgl.program, 'u_VpMatrix');webgl.uniformMatrix4fv(u_VpMatrix, false, vpMat.elements);var u_ModelMatrix = webgl.getUniformLocation(webgl.program, 'u_ModelMatrix');webgl.uniformMatrix4fv(u_ModelMatrix, false, modelMat.elements);//************* *///model逆转置var reverseModelMat = new Matrix4().setInverseOf(modelMat); //求逆reverseModelMat.transpose(); //转置var u_ReverseModelMat = webgl.getUniformLocation(webgl.program, 'u_ReverseModelMat');webgl.uniformMatrix4fv(u_ReverseModelMat, false, reverseModelMat.elements);//************* */// datavar vertexData = new Float32Array([1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, //front面 v0-41.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, //right v03451.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, //up v0561-1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, //left -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, //down1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0 //back]);var colorData = new Float32Array([0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, //front0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, //right1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, 1.0, 0.4, 0.4, //up1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, //left1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, //btm0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0, 0.4, 1.0, 1.0 //back]);var colorData_ALLWHITE = new Float32Array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, ]);var indicesData = new Uint8Array([0, 1, 2, 0, 2, 3,4, 5, 6, 4, 6, 7,8, 9, 10, 8, 10, 11,12, 13, 14, 12, 14, 15,16, 17, 18, 16, 18, 19,20, 21, 22, 20, 22, 23]);initArrayBuffer(webgl, vertexData, 'a_Position', 3, webgl.FLOAT);initArrayBuffer(webgl, colorData_ALLWHITE, 'a_Color', 3, webgl.FLOAT);initIndexBuffer(webgl, indicesData);var n = indicesData.length;//设置光照颜色var u_LightColor = webgl.getUniformLocation(webgl.program, 'u_LightColor');webgl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);//设置光照方向var u_LightDirection = webgl.getUniformLocation(webgl.program,'u_LightDirection');var lightDirection = new Vector3([0.5, 3.0, 4.0]);lightDirection.normalize();webgl.uniform3fv(u_LightDirection, lightDirection.elements);//通过设置顶点的法向量 确定面的法向量var normalData = new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0]);initArrayBuffer(webgl, normalData, 'a_Normal', 3, webgl.FLOAT);//设置环境光var u_AmbientLight = webgl.getUniformLocation(webgl.program, 'u_AmbientLight');webgl.uniform3f(u_AmbientLight, 0.2, 0.2, 0.2);webgl.enable(webgl.DEPTH_TEST);webgl.clearColor(0.0, 0.0, 0.0, 1.0);webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);// webgl.drawArrays(webgl.TRIANGLES, 0, n);webgl.drawElements(webgl.TRIANGLES, n, webgl.UNSIGNED_BYTE, 0);var tempRMatrix = new Matrix4().setInverseOf(modelMat);var tick = () => {var modelMat = animateRotate(webgl, 30);//model逆转置tempRMatrix.setInverseOf(modelMat); //求逆tempRMatrix.transpose(); //转置webgl.uniformMatrix4fv(u_ReverseModelMat, false, tempRMatrix.elements);//mvp矩阵webgl.uniformMatrix4fv(u_ModelMatrix, false, modelMat.elements);//************* */webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT);webgl.drawElements(webgl.TRIANGLES, n, webgl.UNSIGNED_BYTE, 0);        requestAnimationFrame(tick);};// requestAnimationFrame(tick);
}// 初始化顶点缓冲区
// 坐标值 或者 颜色值
function initArrayBuffer (webgl, data, name, num, type) {var vertexBuffer = webgl.createBuffer();webgl.bindBuffer(webgl.ARRAY_BUFFER, vertexBuffer);webgl.bufferData(webgl.ARRAY_BUFFER, data, webgl.STATIC_DRAW);var vertexLoction = webgl.getAttribLocation(webgl.program, name);webgl.vertexAttribPointer(vertexLoction, num, type, false, 0, 0);webgl.enableVertexAttribArray(vertexLoction);return true;
}//=> 使用索引
function initIndexBuffer (webgl, indexData) {var indicesBuffer = webgl.createBuffer();webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, indicesBuffer);webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, indexData, webgl.STATIC_DRAW);return true;
}//=> 添加一个动画
// return rotate 矩阵
var CURRENT_ANGLE = 0;
var CURRENT_MODEL_MATRIX = new Matrix4();
var CURRENT_TIMESTAMP = Date.now();
function animateRotate (webgl, speed) {var now = Date.now();var interval = Date.now() - CURRENT_TIMESTAMP;CURRENT_TIMESTAMP = now;CURRENT_ANGLE += (interval * speed /  1000);//累加CURRENT_MODEL_MATRIX.setRotate(CURRENT_ANGLE, 0, 0, 1);return CURRENT_MODEL_MATRIX;
}

WebGL编程指南-24 同时使用漫反射光和环境反射光、立方体平移旋转缩放变换时漫反射光和环境反射光处理相关推荐

  1. 【WebGL编程指南】GLSL ES语法基础

    [WebGL之巅]20-GLSL ES着色器语言语法详解 查看原文:[WebGL之巅]20-GLSL ES着色器语言语法详解 对应<WebGL编程指南>第六章 GLSL ES 总览 本章知 ...

  2. 【《WebGL编程指南》读书笔记-WebGL入门】

    <WebGL编程指南>读书笔记 目录链接:https://blog.csdn.net/floating_heart/article/details/124001572 第二章 WebGL入 ...

  3. 【WebGL】《WebGL编程指南》读书笔记——第5章

    一.前言        终于到了第五章了,貌似开始越来越复杂了. 二.正文         Example1:使用一个缓冲区去赋值多个顶点数据(包含坐标及点大小) function initVerte ...

  4. 【WebGL】《WebGL编程指南》读书笔记——第2章

    一.前言 最近看了<WebGL编程指南>这本书,发现还是很有意思的,故每章阅读后做个笔记. 二.正文 Example1:在canvas中绘制2D矩形 <!DOCTYPE html&g ...

  5. 【《WebGL编程指南》读书笔记——着色器和程序对象的准备】

    本文为<WebGL编程指南>第九章下半部分读书笔记 总目录链接:https://blog.csdn.net/floating_heart/article/details/124001572 ...

  6. WebGL编程指南-23 光照原理、漫反射光计算、漫反射光照射下的立方体

    1.demo效果 如上,添加了漫反射光照射效果的立方体,最前面的面亮一些,顶上和右侧的面暗一些 2.光照原理 现实中,物体被光线照射,会有一部分光在物体表面反射,当反射光线进入你的眼睛时,你就看到了物 ...

  7. webGL编程指南实战教程

    学习路线: 如果你是在校大学生,有足够的时间去学习:前端>数学(几何+线性代数)>图形学>webgl>shader >threejs>three.js源码 如果你是 ...

  8. WebGL编程指南-27 逐片元处理点光源光照效果

    1.demo效果 如上图,图二为逐片元处理点光源的效果,与之前的demo效果相比,物体表面的光照效果更佳柔和.细腻. 2.实现要点 在上一章中实现方式是逐顶点的方式,实现点光源在照射到立方体呈现出的效 ...

  9. webgl编程指南源码_ThreeJS 源码剖析之 Renderer(一)

    引子? 最近,忽然想起曾在 WebGL 基础系列 文章中立下 flag:"后续还打算出 <ThreeJS 源码剖析> 系列"(特意翻出原话?),项目忙了一阵后,便决定开 ...

最新文章

  1. 终极方案!解决正确设置LaunchImage后仍然不显示的问题
  2. Linux环境下oracle client安装和配置
  3. ntko office在线编辑控件问题记录
  4. 在linux中安装rpm包
  5. J2EE总结--浅识JNDI
  6. ImageMagick 打水印支持透明度设置
  7. 电压源和电流的关联参考方向_数控电压、电流源1.3
  8. 新法规将处罚垃圾邮件制造者
  9. [转]跨域资源共享 CORS 详解
  10. SDLC - 螺旋模型
  11. 关于Linux内核学习
  12. cisco 路由器时区设置
  13. NIOS_Altera EPCS下载 注意事项20210815
  14. i3 10105F参数配置 i3 10105F怎么样
  15. win8 安装双系统 ubuntu 过程
  16. Java题-古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少?
  17. C#实现图书管理系统(课程设计)——第五步、查询界面及操作
  18. 给你的网页加个二次元老婆吧
  19. 2022爱分析・智慧园区厂商全景报告 | 爱分析报告
  20. accumulate 的用法

热门文章

  1. 单片机助手,STM32、杰发科技、定时器计算工具助手,CAN比特率计算助手
  2. UG\NX二次开发 判断面的凹凸、圆柱还是孔、外R角还是内R角。三种方案
  3. 粒子系统(二):绘制精美几何图案
  4. Website Watchman for Mac(mac网站内容监控工具)
  5. chatbot 资料汇总
  6. 什么是硬件集成开发?硬件集成开发的核心有哪些?
  7. 我终于把C++多文件编程理解透彻了
  8. 交流电计算方法c语言,正弦交流电的计算公式
  9. 机器人校本课感想(一)
  10. windows 20008DHCP中继