1.基本概念:

着色:根据光照条件,重建“物体表面明暗不一效果”的过程

光源类型:

(1)平行光:没有衰减的平行的光线,类似于太阳光。用一个方向和一个颜色定义。

(2)点光源:理想化为质点点光源,类似于人造灯泡,有光线衰减。用光源位置和颜色定义。

(3)环境光:用于模拟真实世界中的非直射光(由光源发出经过墙壁或其他物体反射的光)。只需要指定颜色。

反射光取决于以下两个因素:

(1)入射光(入射光的方向和颜色)

(2)物体表面类型(物体表面的固有颜色(基底色),和反射特性)

物体表面反射光线的方式有两种:

(1)漫反射:针对平行光和点光源而言,漫反射的反射光在各个方向上是均匀的,反射强度受入射角影响。

我们将入射光线与表面法线形成的夹角为入射角,用B表示,那么

<漫反射光颜色>=<入射光颜色>x<表面基底色>x cosB,乘法操作在矢量上逐分量进行

(2)环境反射:针对环境光而言,反射光的方向就是入射光的反方向,所以反射光是各向均匀的。

<环境反射光颜色>=<入射光颜色>x<表面基底色>

综上:<表面的反射光颜色>=<漫反射光颜色>+<环境反射光颜色>

2.平行光漫反射的计算:

平行光:平行光下物体每个面上光线的入射角是相同的,所以只要确定cosB的值再利用公式计算即可。

根据向量之间的点乘,a.b = |a|x|b|xcosB,如果a,b向量的模都是1,那么cosB = a.b,那么我们应该首先将a,b向量进行归一化

(1)归一化:将矢量的长度调整为1,同时保持方向不变

GLSL ES提供了归一化函数,其原理是,将矢量的各个分量处以矢量的模,即n( nx/|n| , ny/|n| , nz/|n| )。

(2)确定法向量方向:

法向量表示的是方向,平行平面的法向量相同;每个平面有两个方向相反的法向量,在三维图形学中,法向量方向和顶点的绘制顺序有关,法向量指向顶点绘制顺序逆时针的一方

cosB = <光线方向>.<法线方向>,其中光线方向是入射光线的反方向(因为该方向与法线夹角才是入射角)。

<漫反射光颜色>=<入射光颜色>x<表面基底色>x(<光线方向>x<法线方向>)

3.程序实现:

(1)法向量和光线方向向量归一化:

由于物体表面的法向量和顶点有关,法向量的归一化放在顶点着色器中进行

'attribute vec4 a_Normal;\n' +

'vec3 normal = normalize(vec3(a_Normal));\n' +

在GLSL ES中,normalize()方法将矢量进行归一化,由于a_Normal声明为vec4类型,法向量由前三个分量x y z 定义,所以先使用vec3()构造器取出前三个分量

光线方向矢量归一化:

光线方向和物体本身无关,所以放在js代码中进行归一化,放在顶点着色器中会执行n遍,浪费计算机资源

//设置光线方向

var lightDirection = new Vector3([0.5,3.0,4.0]);

//入射光线归一化

lightDirection.normalize();

gl.uniform3fv(u_LightDirection,lightDirection.elements);

cuon-matrix.js中为Vector3类型提供了normalize()函数,调用后归一化后的分量值存入对象本身。

(2)漫反射光颜色计算

' float nDotL = max(dot(u_LightDirection,normal),0.0);\n' +

'vec3 diffuse = u_LightColor * vec3(a_Color) * nDotL;\n'+

法向量和光线方向向量的点乘运算:dot(n,l ),GLSL  ES内置dot方法计算矢量的点乘,入参为两个矢量,返回点积(标量)

当点积结果小于0时,说明入射光线方向与法线夹角大于90度,光线照在平面的背面,所以颜色值为0,max(a,b)将a,b中较大的值赋给变量

(3)环境光的计算

'uniform vec3 u_AmbientLight;\n' +

'vec3 ambient = u_AmbientLight * a_Color.rgb;\n'+

a_Color是一个vec4类型变量,前三个分量代表rgb值,只取其前三个分量进行计算

(4)反射光颜色 = 漫反射光颜色+环境反射光颜色

'v_Color = vec4(diffuse + ambient,a_Color.a);\n' +

最后计算的反射光有三个分量,v_Color有四个分量,将a_Color的a分量值写入

(5)顶点法向量的写入

顶点的法向量依赖于顶点组成的平面(TRIANGLE),由多个TRIANGLE共用的顶点在绘制每个TRIANGLE时拥有不同法向量(由顶点绘制顺序决定),例如正六面体中每个顶点被三面共用,那么需要的法向量就有64个

4.绘制光照立方体

var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'attribute vec4 a_Color;\n' +
'attribute vec4 a_Normal;\n' +
'uniform mat4 u_MvpMatrix;\n' +
'uniform vec3 u_LightColor;\n' +
'uniform vec3 u_LightDirection;\n' +
'varying vec4 v_Color;\n' +
'void main(){\n' +
'gl_Position = u_MvpMatrix * a_Position;\n' +
//对法向量进行归一化
'vec3 normal = normalize(vec3(a_Normal));\n' +
//计算光线方向和法向量乘积,已经完成归一化,u_LightDirection在js代码中已经完成归一化
'float nDotL = max(dot(u_LightDirection,normal),0.0);\n' +
//计算漫反射光的颜色
'vec3 diffuse = u_LightColor * vec3(a_Color) * nDotL;\n'+
//a_Color.a是GLSL ES中对矢量的访问符,r,g,b,a
'v_Color = vec4(diffuse,a_Color.a);\n' +
'}\n';var FSHADER_SOURCE =
'precision mediump float;\n'+
'varying vec4 v_Color;\n' +
'void main(){\n' +
'gl_FragColor = v_Color;\n' +
'}\n';function main(){
var canvas =document.getElementById('webgl');
var gl = canvas.getContext('webgl');
initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE);
var n = initVertexBuffers(gl);
//开启深度检测
gl.enable(gl.DEPTH_TEST);
gl.clearColor(1.0,0.0,0.0,1.0);
var u_LightColor = gl.getUniformLocation(gl.program,'u_LightColor');
var u_LightDirection = gl.getUniformLocation(gl.program,'u_LightDirection');
var u_MvpMatrix = gl.getUniformLocation(gl.program,'u_MvpMatrix');
//设置光线颜色
gl.uniform3f(u_LightColor,1.0,1.0,1.0);
//设置光线方向
var lightDirection = new Vector3([0.5,3.0,4.0]);
//入射光线归一化
lightDirection.normalize();
gl.uniform3fv(u_LightDirection,lightDirection.elements);
//计算模型视图投影矩阵
var mvpMatrix = new Matrix4();
mvpMatrix.setPerspective(30,canvas.width/canvas.height,1,100);
mvpMatrix.lookAt(3,3,7,0,0,0,0,1,0);
//mvpMatrix.rotate(180,0,1,0);
gl.uniformMatrix4fv(u_MvpMatrix,false,mvpMatrix.elements);
gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES,n,gl.UNSIGNED_BYTE,0);
}function initVertexBuffers(gl){
var verteices = 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 normals = 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,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,//顶面顶点法向量
0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0, 0.0,-1.0,0.0//底面顶点法向量
]);
var colors = new Float32Array([
0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, //前面的顶点颜色
0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, //右面顶点颜色
0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, //后面顶点颜色
0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, //左面顶点颜色
0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, //顶面顶点颜色
0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, 0.4,1.0,0.4, //底面顶点颜色
]);
var indices = 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 //底面顶点索引
]);
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);initArrayBuffer(gl,verteices,3,gl.FLOAT,'a_Position');
initArrayBuffer(gl,colors,3,gl.FLOAT,'a_Color');
initArrayBuffer(gl,normals,3,gl.FLOAT,'a_Normal');
return indices.length;
}
function initArrayBuffer(gl,data,num,type,attribute){
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);
var a_attribute = gl.getAttribLocation(gl.program,attribute);
gl.vertexAttribPointer(a_attribute,num,type,false,0,0);
gl.enableVertexAttribArray(a_attribute);
return true;
}

5.运动物体的光照效果:

当物体发生平移、旋缩放等变换时,顶点的法向量可能会发生改变,根据模型矩阵计算变换后的法向量的方法是:

用模型矩阵的逆转置矩阵乘以原法向量,就可以得到变换后的法向量。

Matrix4提供了计算逆转置矩阵的方法:

(1)求原矩阵的逆矩阵:

Matrix4 . setInverseOf(m):将m矩阵的逆矩阵赋值给自身

(2)对逆矩阵进行转置:

Matrix4 . transpose():对自身进行操作,将自身设置为转置后的结果。

16.光照(平行光)相关推荐

  1. 【three.js:语法】光源使用详解2-3(聚光灯 SpotLight、平行光 DirectionLight 、环境光 HemisphereLight、镜头光晕 LensFlare)

    注意点:SpotLight.target 的使用. 1.SpotLight.target= object 或者是 THREE.Object3D()才行.不能只是一个position. 2.target ...

  2. Three.js - 光源使用详解2(聚光灯 SpotLight、平行光 DirectionLight)

    三.THREE.SpotLight(聚光灯光源) 1,基本介绍 THREE.SpotLight 是一种具有锥形效果的光源,该光源拥有产生光的方向和角度.我们可以将其与手电筒或者灯笼产生的光进行对比. ...

  3. 人脸识别 光照预处理

    转载:http://shijuanfeng.blogbus.com/logs/204416961.html ---------------------------------------------- ...

  4. Oasis Engine 3d全景展示demo

    Oasis Engine 是一套 Web 为先,移动优先的互动引擎,使用 Typescript 编写.核心功能由 oasis-engine 提供,非核心和偏业务逻辑定制的高级功能由 oasis-eng ...

  5. 简单的builltin下的PBRshader手撸练习——UnityShader学习笔记

    文章目录 自言自语 一.截图效果 二.shader 总结 自言自语 又是很久没有写笔记了.因为一直在啃PBR.总算在昨晚算是啃通了一遍.不过这只是个简单的builltin下的相对简单的PBR框架的sh ...

  6. 实现手机来电铃声,通知铃声、警告铃声等音频定制化功能(三,多媒体扫描结果定制处理)

    本篇博文主要是对MediaScanner中endFile方法的处理流程上的重构,以实现需求中的资源区域化定制.处理思路为首先扫描定制分区中的资源,在扫描系统分区下默认资源时判断定制分区西下是否已经存在 ...

  7. sqlserver错误码

    错误 6,000 到 6,999 错误 严重性 是否记录事件 说明 6001 10 否 SHUTDOWN 正在等待 %d 个进程完成. 6004 10 否 用户没有执行此操作的权限. 6005 10 ...

  8. CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果...

    CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...

  9. GAMES101课程学习笔记—Lec 14(2)~16:Ray Tracing(2) BRDF、渲染方程、全局光照、路径追踪

    GAMES101课程学习笔记-Lec 14(2)~16:Ray Tracing(2) BRDF.渲染方程.全局光照.路径追踪 0 引入--辐射度量学概述 1 相关概念 1.1 Radiant Ener ...

最新文章

  1. GDCM:gdcm::TagToType的测试程序
  2. SQLCLR系列文章
  3. nginx搭建基于http协议的视频点播服务器
  4. 彻底理解python递归_Python开发之-Python递归图示理解
  5. 英伟达3080Ti、3070Ti来了!
  6. 花式上分算法大赛,速看鹅厂六强团队解题思路集锦【附PPT下载】
  7. 《假设的世界-一切不能想当然》笔记
  8. 知识回顾之一:WEB编程语言发展回顾...
  9. 计算机考试系统客户端怎么用不了,[说明]计算机基础测评系统考试客户端操作步骤.doc...
  10. 如何在html中插入带圈数字,Excel2013中带圈数字怎么输入
  11. Android studio app登录界面设计
  12. 良田高拍仪集成WEB说明
  13. 【嵌入式--伺服电机】电磁理论的基础概念
  14. 湘潭大学2022软件工程程序设计实践平时练习二C/C++
  15. container 和initContainers使用
  16. 飞塔防火墙密码恢复。
  17. Windows和Ubuntu系统文件无法粘贴问题
  18. 一次线上事故,我顿悟了异步的精髓
  19. 如何正确选择电磁流量计
  20. 读《The C Programming Language》

热门文章

  1. PowerCHM-强大的CHM工具
  2. 华硕笔记本刷BIOS
  3. FPGA基础资源之IOB的应用
  4. 数据分析2021年最实用工具排名前6位出炉
  5. 你会的还只有初级工程师的技术吗?灵魂拷问
  6. eclipse鼠标变成十字架
  7. 哪款游戏蓝牙耳机好用?好用的游戏蓝牙耳机推荐
  8. 家用投影仪不会选?记住这几个方面,帮你选到适合你的投影仪
  9. 电机控制Clarke(α/β)等幅值变换推导
  10. 详细图解3阶段事务提交及单点故障和网络脑裂问题