1.光源
1.1点光源
点光源通过位置和发射光颜色来定义.
光辐射衰减 : 点光源在空间中传播,会随着光源的的距离进行衰减.
如果点光源的位置在无穷远,解释 : 实际上光源的距离为d时,它的振幅将按照因子 进行衰减,但是对于接近光源的对象, 会产生过大的强度变化,而d很大时变化又太小,造成这样的原因是实际的光源并不是无穷小的点,而是用点发光体照明一个场景是真实光照效果的简单近似.所以加上 ,使用者可以通过调整这三个系数的值,以得到场景中不同的光照效果,例如,当d非常小的时候,可以赋予 一个大的值来防止 变得很大.
对应WebGl和Three.js里面的光 :
1 . 光的距离在无穷远时,d=正无穷时,对应WebGL里面的平行光, 对应Three.js里面的方向光
- WebGL里需要给着色器传两个矢量,光色和光方向 : uniform vec3 u_LightCorlor和 uniform vec3 u_LightDirection.
- Three.js里面定义方向光的构造器DirectionalLight( color, intensity ).
//Three.js定义方向光的WebGL源码.
var uniforms = lightCache.get( light );
uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
_vector3.setFromMatrixPosition( light.target.matrixWorld );
uniforms.direction.sub( _vector3 );
uniforms.direction.transformDirection( viewMatrix );
2.光的位置在局部时,对应WebGL和Three.js里面的点光源.
- WebGL编程指南并没有关于点光源定义的着色器代码.
- Three.js里面定义点光源的构造器PointLight( color, intensity, distance, decay ).
//Three.js定义点光源的WebGL源码.
var uniforms = lightCache.get( light );
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
uniforms.distance = light.distance;
uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
1.2方向光
一个方向光通过一个方向向量和从该方向开始的角度范围
来确定(类比成光锥).
表示光源到光照对象的单位方向向量.
角强度衰减 :
如果光源不是一个投影光源, 如果对象处于光锥之外,解释 : 衰减指数a是某个正值, 指圆锥轴到圆锥表面之间的夹角范围内的某个角度值.
对应Three.js里面的聚光灯 :
- Three.js里面定义聚光灯的构造函数:SpotLight( color, intensity, distance, angle, penumbra, decay )
//Three.js定义聚光灯的源码.
var uniforms = lightCache.get( light );
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
uniforms.color.copy( color ).multiplyScalar( intensity );
uniforms.distance = distance;
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
_vector3.setFromMatrixPosition( light.target.matrixWorld );
uniforms.direction.sub( _vector3 );
uniforms.direction.transformDirection( viewMatrix );
uniforms.coneCos = Math.cos( light.angle );
uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
1.3环境光
通过设定场景的亮度来定义环境光.所有对象都相同的一个环境光,并且近似的给出了各个光照表面的全局漫反射.
Three.js定义环境光的构造函数 : AmbientLight( color, intensity )
//Three.js里面定义环境光的源码.
r += color.r * intensity;
g += color.g * intensity;
b += color.b * intensity;
1.4Three.js里面的其他光
- 半球光:构造函数HemisphereLight( skyColor, groundColor, intensity )
//Three.js里面定义半球光的源码
var uniforms = lightCache.get( light );
uniforms.direction.setFromMatrixPosition( light.matrixWorld );
uniforms.direction.transformDirection( viewMatrix );
uniforms.direction.normalize();
uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
- 长方形面光:构造函数RectAreaLight( color, intensity, width, height )
var uniforms = lightCache.get( light );
uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height ) );
uniforms.position.setFromMatrixPosition( light.matrixWorld );
uniforms.position.applyMatrix4( viewMatrix );
_matrix42.identity();
_matrix4.copy( light.matrixWorld );
_matrix4.premultiply( viewMatrix );
_matrix42.extractRotation( _matrix4 );
uniforms.halfWidth.set( light.width * 0.5,0.0, 0.0 );
uniforms.halfHeight.set(0.0, light.height * 0.5, 0.0 );
uniforms.halfWidth.applyMatrix4( _matrix42 );
uniforms.halfHeight.applyMatrix4( _matrix42 );
2.对象表面光照效果
- 物体的光学特性是影响光照效果的主要因素,这些特性包括透明度,颜色反射系数,表面纹理参数.
2.1漫反射
粗糙或颗粒状表面会将反射光向各个方向发散出去,这样的反射称为漫反射.
- 理想漫反射体 : 假设入射光在各个方向以相同的强度发散而与观察者的位置无关 . 理想漫反射体表面上反射光能量由朗伯余弦定律来计算.因此也被称为朗伯反射体.对于朗伯反射,光强度在所有观察方向都相同.
如果每一个表面都按照理想漫反射体来对待,不同的光源在漫反射下的反射光强度如下:
环境光下的漫反射 :
点光源下的漫反射 :
环境光和点光源同时存在下的漫反射 :
2.2镜面反射
反射光集中成醒目或明亮的一个点,成为镜面反射.假设现有一表面,法向量是N,L表示光源方向,R表示反射光方向,V表示视点方向,L与N的夹角=R与N的夹角= R与V的夹角是 .理想的镜面反射材料只有当 的时候,观察者才能看到反射光 .
非理想反射体系统系统的反射方向分布在向量R周围的有限范围内.较光滑的反射范围比较小,较粗糙的反射范围比较大.Phong Bui Tuong提出了一个计算镜面范围的经验公式,被成为Phong的反射模型.
简化版的Phong模型可以用N•H代替V•R,H表示L和V的半角向量.
2.3漫反射和镜面反射的合并
2.4多光源的漫反射和镜面反射的合并
3.表面绘制算法
Gouraud明暗处理
- 确定每个多边形顶点处的平均单位法向量.
- 对于每个顶点根据光照模型来计算其光强度.
- 在多边形投影区域对顶点强度进行线性插值.
缺点 : 表面上的高光有时会出现异常形状,线性光强度插值会造成表面上出现过亮或过暗的条纹,这被成为马赫带效应.
Phong明暗处理
- 确定每个多边形顶点处的平均单位法向量.
- 在多边形投影区域上对顶点法向量进行线性插值.
- 根据光照模型,使用插值的法向量,沿每条扫描线计算投影像素的光强度.
缺点:需要比Gouraud方法更多的计算.
快速Phong明暗处理
缺点 : 虽然快速Phong的方法减少了Phong表面绘制算法的计算量,但它的计算量仍然相当于Gouraud表面绘制算法的两倍的时间.基本的Phong表面绘制算法比Gouraud绘制多耗时6到7倍.