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

OpenGL ES 光照(二)

散射光(Diffuse):

從物體表面向全方位360度均勻反射的光,反射後的散射光在各個方向是均勻的,但反射光的反射強度與入射光的強度以及入射角度密切相關。垂直地照射到物體表面時比斜照時要亮。

散射光具體計算公式:

其中設光照入射角為α. 
散射光照射結果=材質的反射係數×散射光強度×max(cosα,0)

實際開發分兩步計算

散射光最終強度=散射光強度×max(cosα,0)
散射光照射結果=材質的反射係數×散射光最終強度

這裡寫圖片描述

入射角越大,反射強度越弱,當入射角的餘弦值為負值時(即入射角大於90度),反射強度為0。由於入射角是光向量與法向量的夾角,cosα= 規格化(光向量)·規格化(法向量)

頂點著色器

#version 300 es
uniform mat4 uMVPMatrix;                        //總變換矩陣
uniform mat4 uMMatrix;                          //變換矩陣(包括平移、旋轉、縮放)
uniform vec3 uLightLocation;                        //光源位置
in vec3 aPosition;                          //頂點位置
in vec3 aNormal;                            //頂點法向量
out
vec3 vPosition; //用於傳遞給片元著色器的頂點位置 out vec4 vDiffuse; //用於傳遞給片元著色器的散射光分量 void pointLight ( //散射光光照計算的方法 in vec3 normal, //法向量 inout vec4 diffuse, //散射光計算結果 in vec3 lightLocation, //光源位置
in vec4 lightDiffuse //散射光強度 ){ 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); //規格化vp float nDotViewPosition=max(0.0,dot(newNormal,vp)); //求法向量與vp向量的點積與0的最大值 diffuse=lightDiffuse*nDotViewPosition; //計算散射光的最終強度 } void main(){ gl_Position = uMVPMatrix * vec4(aPosition,1); //根據總變換矩陣計算此次繪製此頂點的位置 vec4 diffuseTemp=vec4(0.0,0.0,0.0,0.0); pointLight(normalize(aNormal), diffuseTemp, uLightLocation, vec4(0.8,0.8,0.8,1.0)); vDiffuse=diffuseTemp; //將散射光最終強度傳給片元著色器 vPosition = aPosition; //將頂點的位置傳給片元著色器 }

片段著色器

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