OpenGl ES光照

一、光照原理

光照效果是由发射光,环境光,漫反射光以及镜面高光四部分组成,这四部分各自独立计算,然后再累加起来得到最终的光照效果。

1、光特性发射光(emission):由物体自身发射的光。如果物体本身不发光,则无此属性。

计算方法:

发射颜色 = 物体的发射材质颜色

2、环境光(ambient):就是哪些在环境中进行了充分散射的光,而无法分辨其方向的光。光线在物体表面上向各个方向上均匀泛射,场景中的物体都会泛射光,这些泛射光又会照射到其他物体上继续被泛射,直到光子能量耗尽为止,这样整个场景中散布着这样的泛射光。在编程时,可通过设置一个颜色常量来表示环境光或使用 ambient occlusion map (环境闭包贴图)来处理环境光。在 OpenGL 中,全局环境光的强度为 (0.2, 0.2, 0.2, 1.0),这弱弱的白色全局环境光确保即使没有额外的光源,场景中的物体依然是可见的。

计算方法:

环境颜色 = 光源的环境光颜色 × 物体的环境材质颜色

3、漫反射光(diffuse):光线来自某个方向,但在物体表面上向各个方向上反射,无论在何处观察,散射光看上去亮度都相同。我们之所以能看到物体,就是因为物体将入射的光然后向各个方向反射(所以称之为漫反射)。物体的漫反射材质属性对物体的颜色起着决定性作用。

计算方法:

漫反射颜色 = 光源的漫反射光颜色 × 物体的漫反射材质颜色 × DiffuseFactor

DiffuseFactor = max(0, dot(N, L))

其中漫反射因子 DiffuseFactor 是光线与顶点法线向量的点积。在图形学中,点积几何意义其实就是表示两个向量之间夹角的 cos 值。因此漫反射的规律是:光线与定点法线夹角越小时,漫反射效果越强。

OpenGl ES光照_第1张图片

4、镜面高光(specular):光线来自一个特定的方向,然后在物体表面上以一个特定的方向反射出去(镜面反射)。正是由于镜面高光让物体看起来有光泽,如台球,金属表面的光泽。镜面反射与物体的镜面反射材质属性有很大关系,如金属表面能产生很高的镜面发射,而地毯几乎没有镜面反射。在 OpenGL 中,镜面光的强度可通过光泽度(shininess)来调节。

计算方法:

镜面反射颜色 = 光源的镜面光颜色 × 物体的镜面材质颜色 × SpecularFactor

SpecularFactor = power(max(0, dot(N, H)), shininess)

H = normalise(L + E)

镜面反射受观察者的位置影响,这一点在上面的计算公式中可以清楚地看出来。H 向量是视线向量 E 与光线向量 L 的半向量(注意:它经过规划化的),其几何意义就是视线与光线夹角的平分线。而 H 和 N 的点积的几何意义就是说这个平分线与法线的夹角的 cos 值,然后将这个 cos 值进行 shininess 次乘方计算得到最终的镜面反射因子 Specularfactor。因此镜面反射规律:当视线与光线在表面处的反射光线夹角(可看成是N与H的夹角)越少时,镜面反射效果最明显(角度越小,cos 值越大)。

OpenGl ES光照_第2张图片


二、一个光照渲染实例

首先知道几个函数的意思:

dot(v1,v2)       向量点积
normalize(v)     向量单位化
mod(v1,v2) v1/v2求余
max(v1,v2)     求最大值
pow(v1,v2)     求v1的v2次幂

1、顶点渲染

uniform mat4 uMVPMatrix; 	//总变换矩阵
uniform mat4 uMMatrix; 		//变换矩阵
uniform vec3 uCamera;		//摄像机位置
uniform vec3 uLightLocationSun;	//太阳光源位置
attribute vec3 aPosition;  	//顶点位置
attribute vec2 aTexCoor;   	//顶点纹理坐标
attribute vec3 aNormal;    	//法向量
varying vec2 vTextureCoord;  	//用于传递给片元着色器的变量
varying vec4 vAmbient;
varying vec4 vDiffuse;
varying vec4 vSpecular;

//定位光光照计算的方法
void pointLight(					
  in vec3 normal,			//法向量
  inout vec4 ambient,			//环境光最终强度
  inout vec4 diffuse,			//散射光最终强度
  inout vec4 specular,			//镜面光最终强度
  in vec3 lightLocation,		//光源位置
  in vec4 lightAmbient,			//环境光强度
  in vec4 lightDiffuse,			//散射光强度
  in vec4 lightSpecular			//镜面光强度
){
//环境光是完全散射的光照部分,取平均值即可
  ambient=lightAmbient;			//直接得出环境光的最终强度  
  
  vec3 normalTarget=aPosition+normal;	//计算变换后的法向量
  vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4(aPosition,1)).xyz;
  newNormal=normalize(newNormal); 	//对法向量单位化
 
//散射光:法向量与光线角度
  //计算从表面点到光源位置的向量vp
  vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz);  
  vp=normalize(vp);
  float nDotViewPosition=max(0.0,dot(newNormal,vp)); 	//求法向量与vp的点积与0的最大值
  diffuse=lightDiffuse*nDotViewPosition;		//计算散射光的最终强度
  
//表面光:视线+光线+法线
   //计算从表面点到摄像机的向量
  vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz);  
  vec3 halfVector=normalize(vp+eye);					//求视线与光线的半向量    
  float nDotViewHalfVector=dot(newNormal,halfVector);			//法线与半向量的点积 
  float shininess=50.0;				  			//光泽度,越小越光滑
  float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess)); 	//镜面反射光强度因子
  specular=lightSpecular*powerFactor;    				//计算镜面光的最终强度
}



void main()     
{                            		
   gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置  
   
   vec4 ambientTemp=vec4(0.0,0.0,0.0,0.0);
   vec4 diffuseTemp=vec4(0.0,0.0,0.0,0.0);
   vec4 specularTemp=vec4(0.0,0.0,0.0,0.0);   
   
   pointLight(normalize(aNormal),ambientTemp,diffuseTemp,specularTemp,uLightLocationSun,vec4(0.05,0.05,0.05,1.0),vec4(1.0,1.0,1.0,1.0),vec4(0.3,0.3,0.3,1.0));
   
   vAmbient=ambientTemp;
   vDiffuse=diffuseTemp;
   vSpecular=specularTemp;
   
   //将顶点的纹理坐标传给片元着色器
   vTextureCoord=aTexCoor;
}  

 2、片元渲染 
 

precision mediump float;
varying vec2 vTextureCoord;      //接收从顶点着色器过来的参数
varying vec4 vAmbient;
varying vec4 vDiffuse;
varying vec4 vSpecular;
uniform sampler2D sTextureDay;   //纹理内容数据

void main()                         
{  
  //给此片元从纹理中采样出颜色值   
  vec4 finalColor;     
  
  finalColor= texture2D(sTextureDay, vTextureCoord);
  finalColor = finalColorDay*vAmbient+finalColorDay*vSpecular+finalColorDay*vDiffuse;
 
  
  gl_FragColor=finalColor;    
  
} 



你可能感兴趣的:(3D,OpenGL,es,顶点渲染,光照渲染,片元渲染)