您的位置:首页 > 其它

WebGL 第七课 中文翻译

2011-07-24 21:03 225 查看
第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恢复。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: