1. 程式人生 > >OpenGL ES 光照(三)

OpenGL ES 光照(三)

鏡面光(Specular):

當光滑物體表面被照射時會有方向很集中的反射光鏡面光的最終強度依賴於入射光、觀察者的位置

鏡面光的計算模型比前面的兩種光都要複雜一些,具體公式如下。

鏡面光照射結果=材質的反射係數×鏡面光強度×max(0,(cos(半向量與法向量的夾角)) ^粗糙度)

實際開發中往往分兩步進行計算,此時公式被拆解為如下情況。

鏡面光最終強度=鏡面光強度×max(0,(cos(半向量與法向量的夾角))^ 粗糙度)
鏡面光照射結果=材質的反射係數×鏡面光最終強度

半向量(H)

指的是從被入射點到光源的向量(L)與從被照射點到觀察點向量(V)的平均向量 向量L 與向量 V 與H向量是同個平面  並且H與V  和 H與L的夾角相等;所以
H = normal(normal(V)+normal(L))
Cosα = dot(H,N)

這裡寫圖片描述

頂點著色器

#version 300 es
uniform mat4 uMVPMatrix;    //總變換矩陣
uniform mat4 uMMatrix;      //變換矩陣
uniform vec3 uLightLocation;    //光源位置
uniform vec3 uCamera;       //攝像機位置
in vec3 aPosition;      //頂點位置
in vec3 aNormal;    //法向量
out vec3 vPosition;     //用於傳遞給片元著色器的頂點位置
out vec4 vSpecular;     //用於傳遞給片元著色器的鏡面光最終強度
void pointLight( //定位光光照計算的方法 in vec3 normal, //法向量 inout vec4 specular, //鏡面光最終強度 in vec3 lightLocation, //光源位置 in vec4 lightSpecular //鏡面光強度 ){ vec3 normalTarget=aPosition+normal; //計算變換後的法向量 vec3 newNormal=(uMMatrix*vec4(normalTarget,1)).xyz-(uMMatrix*vec4
(aPosition,1)).xyz; newNormal=normalize(newNormal); //對法向量規格化 //計算從表面點到攝像機的向量 vec3 eye= normalize(uCamera-(uMMatrix*vec4(aPosition,1)).xyz); //計算從表面點到光源位置的向量vp vec3 vp= normalize(lightLocation-(uMMatrix*vec4(aPosition,1)).xyz); vp=normalize(vp);//格式化vp vec3 halfVector=normalize(vp+eye); //求視線與光線的半向量 float shininess=50.0; //粗糙度,越小越光滑 float nDotViewHalfVector=dot(newNormal,halfVector); //法線與半向量的點積 float powerFactor=max(0.0,pow(nDotViewHalfVector,shininess)); //鏡面反射光強度因子 specular=lightSpecular*powerFactor; //最終的鏡面光強度 } void main() { gl_Position = uMVPMatrix * vec4(aPosition,1); //根據總變換矩陣計算此次繪製此頂點的位置 vec4 specularTemp=vec4(0.0,0.0,0.0,0.0); pointLight(normalize(aNormal), specularTemp, uLightLocation, vec4(0.7,0.7,0.7,1.0));//計算鏡面光 vSpecular=specularTemp; //將最終鏡面光強度傳給片元著色器 vPosition = aPosition; //將頂點的位置傳給片元著色器 }

片段著色器

#version 300 es
precision mediump float;
in vec3 vPosition;//接收從頂點著色器過來的頂點位置
in vec4 vSpecular;//接收從頂點著色器過來的鏡面反射光最終強度
out vec4 fragColor;
void main()                         
{
   //最終顏色
   vec4 finalColor=vec4(物體顏色);
    //根據鏡面光最終強度計算片元的最終顏色值
   fragColor=finalColor*vSpecular;
}     

關於頂點法向量變換可檢視 http://www.songho.ca/opengl/gl_normaltransform.html