打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
WebGL 第七课 中文翻译

第7课:光线

平行光:directional lights

环境光:ambient lights

webGL没有内建的对光的支持,不像OpenGL,能够帮助你处理至少8种光源。不过OpenGL只能处理简单的光照现象。甚至连不平坦的物体表面都处理不了,也不能处理阴影。

目标是在场景内虚拟出光源。首先我们需要能够设定一系列的光源,然后确定这些光源对指定对象的影响。这节课里面,我们需要写处理光的顶点渲染器。对于每个顶点,要计算出光对他的影响,并据此来改变他 的颜色。先处理一个光源的情况,多光源只需将效果叠加就可以了。

per-vertex lighting:处理平坦的表面,若处理复杂的表面可使用perfrgment lighting 技术,将会在之后讲到。现在先看看一个光源对顶点颜色的影响。冯氏明暗处理模型。

现实世界中只有一种光,而对于图像来说,假设有两种光会有用的多。

1来自特定方向的光,只影响对象的某一面,称作平行光

2来自所有方向的光。称作环境光(现实世界中被空气离散的光)

光的反射:Diffusely 漫反射

specularly:镜面反射

冯氏模型假设每种光都有两个属性漫反射的RGB值,镜面反射的RGB值;并且每种材料都有四种属性:环境光RGB值,漫反射RGB值,镜面反射RGB值,材料的反光度shininess

对于点光源,我们需要计算出每个点上的光线的方向,而对于平行光光源,只需计算光源的一个数据值就行。因此这节课只讲平行光源。

1由于平行光的数据不会在不同顶点间改变,因此可以将这些数据放在统一变量中,以便渲染器能够得到它。

2对于3D对象来说,每个顶点都需要一个法向量以表示它相对于光的方向。

3算出每个顶点反射的光(根据光与法向量平面的角度计算)这些角度符合余弦(0~90)

可以看出在将光的方向向量传递给渲染器之前使用vec3模型来封装光的方向,就像用mat4来封装模型视图矩阵和投影矩阵一样,他们都是glMatrix的一部分。

1vec3.normalize是矩阵行数相等

2改变方向

3使用gl.uniform3fv来把三元数组float32array z传递给统一变量。

接下来的代码比较简单,它只是把平行光的颜色部分复制到渲染器的合适的属性中:

gl.uniform3f(

shaderProgram.directionalColorUniform,

parseFloat(document.getElementById(“directional”).value),

parseFloat(document.getElementById(“directionalG”).value),

parseFloat(document.getElementById(“directional”).value));

以上就是drawScene的全部变化

setMatrixUniforms函数的变化:这里增加四行来复制一个新的矩阵,这个矩阵基于模型视图矩阵。

var normalMatrix=mat3.create();

mat4.toInverseMate3(mvMatrix,normalMatrix);

mat3.transpose(normalMatrix);

gl.uniformMatrix3fv(shaderProgram.nMatrixUniform,false,normalMatrix);

这个矩阵被用来转换法向量矩阵。我们不能像转换一个顶点坐标那样来转换法向量(用一个regular模型视图矩阵来转换),因为法向量会随着移动和旋转而改变。

例如:如果我们忽略旋转,并假设做了一个mvTranslate(0,0,-5),也就是模型视图旋转那么法向量(0,0,1)就变成(0,0,-4),这完全指向了错误的方向。在顶点渲染器中,当我们把3*3的顶点矩阵乘以4*4的矩阵时,为了使乘法能够进行,我们扩展 了矩阵的行列(置1),当然这些1不仅仅是为了乘法能够合法进行,也为了使矩阵相乘后能够应用转换和旋转。如果在末尾置0,我们可以使矩阵相乘忽略translations。不幸的是,这样就无法处理模型视图矩阵包含有不同translation的情况,特别是扩大缩小和裁剪。例如,如果我们有一个模型视图矩阵把我们当前的对象放大两倍,他们的法向量也会延长两倍。一个好的方法是使用上三角阵来转换。------------------------------%>_<%这都什么啊

vLighting 是一个三元数组,用来保存RGB被顶点lighting所计算的调节系数,这个数组被作为一个可变变量从渲染器返回,并在判断渲染器中使用。如果光源关闭,则数组值为默认的(1,1,1)表示颜色不改变。如果灯开了,我们就通过法向量矩阵计算出法向量方向,然后通过法向量和光线方向的dot积来获得一个表示光照的影响的大小的量。这样就能根据这个值和平行光的颜色强度的乘积来计算最后在片段渲染器中用到的最后的light weighting。

attribute vec3 aVertexPosition;

attribute vec3 aVertexNormal;

attribute vec2 aTextureCoord;

 

uniform mat4 uMVMatrix;

uniform mat4 uPMatrix;

uniform mat3 uNMatrix;

 

uniform vec3 uAmbientColor;

 

uniform vec3 uLightingDirection;

uniform vec3 uDirectionalColor;

 

uniform bool uUseLighting;

 

varying vec2 vTextureCoord;

varying vec3 vLightWeighting;

 

void main(void) {

gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);

vTextureCoord = aTextureCoord;

 

if (!uUseLighting) {

vLightWeighting = vec3(1.0, 1.0, 1.0);

} else {

vec3 transformedNormal = uNMatrix * aVertexNormal;

float directionalLightWeighting = max(dot(transformedNormal, uLightingDirection), 0.0);

vLightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;

}

}

OpenGL变换矩阵

CTM:表示当前系统坐标,设置CTM之后定义的顶点都要应用CTM,若改变了CTM,则系统的状态也改变了。OpenGL中,应用到所有的图元的变换矩阵是模型视图矩阵和投影矩阵的乘积。所以他们的乘积就是OpenGL系统的CTM。

下面的函数可以把选定的矩阵设置成任意矩阵:glLoadMatrixf(pointer_to_matrix);

下面的函数把选定的矩阵设置成单位阵:glLoadIdentity();

下面的函数调用把当前的矩阵设置成4*4的齐次坐标矩阵。

glLoadMatrixf();

下面的函数对当前矩阵右乘一个用户定义的矩阵:

glMultMatrixf();

有时候我们希望执行某个变换之后再把矩阵(是不是说的CTM矩阵?)恢复到执行这个变换之前的状态。当执行的某个实例变换只适用于一个特定的对象,而对其余对象不能使用这个实例变换时,就会出现这种情况。我们可以在应用实例变换之前利用函数glPushMatrix把当前的变换矩阵压入栈中,以后再用glPopMatrix恢复。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
webgl笔记
OpenGL 4.0 GLSL 用单光源 实现逐顶点 漫反射光照模型
光照基础
GLSL学习笔记 [转]
高级GLSL
图嵌入(Graph embedding)综述
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服