GLSL 中的光照計算


理論知識轉載地址:http://blog.csdn.net/ym19860303/article/details/25545933

1.Lambert模型(漫反射)

環境光:

Iambdiff = Kd*Ia

其中Ia 表示環境光強度,Kd(0<K<1)為材質對環境光的反射系數,Iambdiff是漫反射體與環境光交互反射的光強。

方向光:

Ildiff = Kd * Il * Cos(θ)

其中Il是點光源強度,θ是入射光方向與頂點法線的夾角,稱入射角(0<=A<=90°),Ildiff是漫反射體與方向光交互反射的光強,若 N為頂點單位法向量,L表示從頂點指向光源的單位向量(注意頂點指向光源),則Cos(θ)等價於dot(N,L),故又有:

Ildiff = Kd * Il * dot(N,L)

最后綜合環境光和方向光源,Lambert光照模型可以寫成:

Idiff = Iambdiff + Ildiff = Kd * Ia + Kd * Il * dot(N,L)

2.Phong模型(鏡面反射)

Phong模型認為鏡面反射的光強與反射光線和視線的夾角相關:

Ispec = Ks * Il * ( dot(V,R) )^Ns

其中Ks 為鏡面反射系數,Ns是高光指數,V表示從頂點到視點的觀察方向,R代表反射光方向。由於反射光的方向R可以通過入射光方向L(從頂點指向光源)和物體的法向量求出,
R + L = 2 * dot(N, L) * N  即 R = 2 * dot(N,L) * N - L

所以最終的計算式為:

Ispec = Ks * Il * ( dot(V, (2 * dot(N,L) * N – L ) )^Ns

3.Blinn-Phong光照模型(修正鏡面光)

Blinn-Phong是一個基於Phong模型修正的模型,其公式為:

Ispec = Ks * Il * ( dot(N,H) )^Ns

其中N是入射點的單位法向量,H是光入射方向L和視點方向V的中間向量,通常也稱之為半角向量(半角向量被廣泛用於各類光照模型,原因不但在於半角向量蘊含的信息價值,也在於半角向量是很簡單的計算:H = (L + V) / |L + V|  )。

4.Rendering Equation(全局光照模型)

Rendering Equation 是Kajia在1986年提出的,

Lo(X, Wo) = Le(X, Wo) + ∫fr(X, Wi, Wo) Li(X, Wi) dot(N, Wi) dWi

其中X表示入射點,Lo(X, Wo)即從物體表面X點,沿方向Wo反射的光強,Le(X, Wo)表示從物體表面X以方向Wo 發射出去的光強,該值僅對自發光體有效,fr(X, Wi, Wo)為,入射光線方向為Wi, 照射到點X上,然后從Wo方向發射出去的BRDF值,Li(X, Wi)為入射方向為Wi照射到點X上的入射光強,N表示點X處的法向量,然后對入射方向進行積分(因為光線入射的方向是四面八方的,積分的意義是對每個方向進行一遍計算后相加),計算的結果就是全局光照的輻射率。

對於單個點光源照射到不會自發光的物體上,公式可以簡化成:

Lo(X, Wo) = fr(X, Wi, Wo) Li(X, Wi) dot(N, Wi)

這個公式非常有用,通常會將該公式分解為漫反射表達式和鏡面表達式之和。對於漫反射表面,BRDF可以忽略不計,因為它總是返回某個恆定值,所以可以寫成如下形式:

Lo(X, Wo) = Idiff + frs(X, Wi, Wo) Li(X, Wi) dot(N, Wi)

其中Idiff表示漫反射分量,使用公式的計算方法,frs(X, Wi, Wo)表示鏡面反射的BRDF函數,前面的Phong高光模型,其實是rendering equation在單一光源下針對理想鏡面反射的特定推導,對於Phong高光而言:

frs(X, Wi, Wo) = Ks (dot(N, H)^Ns  / dot(N, Wi)

 

基於GLSL的實現(所有光照和材質參數在實際應用時,應該從常量改為uniform,由外部進行控制):

// 在頂點着色器中處理光照計算(環境光+漫射光+鏡面反射)
const char* ccPositionTextureColorForLight1_v = " \
uniform vec2 translate; \n\
\n\
attribute vec4 a_position; \n\
attribute vec4 a_color; \n\
attribute vec2 a_texCoord; \n\
attribute vec3 a_normal; \n\
\n\
#ifdef GL_ES \n\
varying mediump vec4 v_color; \n\
varying mediump vec2 v_texCoord; \n\
#else \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
#endif \n\
\n\
const vec3 lightAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightSpecular = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialSpecular = vec3(1.0, 1.0, 1.0); \n\
const int shininess = 8; // 0-128 \n\
\n\
const vec3 eyePosition = vec3(512.0, 128.0, 442.0); \n\
const vec3 lightDirection = vec3(1.0, 1.0, 1.0); \n\
\n\
void main() { \n\
vec4 position = CC_MVMatrix * a_position; \n\
position.x += translate.x; \n\
position.y += translate.y; \n\
gl_Position = CC_PMatrix * position; \n\
\n\
vec3 normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz; \n\
vec3 n_normal = normalize(normal); \n\
vec3 n_lightDirection = normalize(lightDirection); \n\
float cosNL = max(dot(n_normal, n_lightDirection), 0.0); \n\
vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL; \n\
\n\
vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0); \n\
\n\
vec3 n_eyePosition = normalize(eyePosition - position.xyz); \n\
vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection; \n\
vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyePosition, reflection), 0.0), shininess), 1.0); \n\
\n\
v_color = a_color * (diffuse + ambient + specular); \n\
v_texCoord = a_texCoord; \n\
} \n\
";
const char* ccPositionTextureColorForLight1_f = " \
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
\n\
void main() { \n\
vec4 color = v_color * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
\n\
gl_FragColor = color; \n\
} \n\
";

效果:

 

// 在片段着色器中處理光照計算(環境光+漫反射+鏡面反射)
const char* ccPositionTextureColorForLight2_v = " \
uniform vec2 translate; \n\
\n\
attribute vec4 a_position; \n\
attribute vec4 a_color; \n\
attribute vec2 a_texCoord; \n\
attribute vec3 a_normal; \n\
\n\
#ifdef GL_ES \n\
varying mediump vec4 v_position; \n\
varying mediump vec4 v_color; \n\
varying mediump vec2 v_texCoord; \n\
varying mediump vec3 v_normal; \n\
#else \n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
#endif \n\
\n\
void main() { \n\
vec4 position = CC_MVMatrix * a_position; \n\
position.x += translate.x; \n\
position.y += translate.y; \n\
gl_Position = CC_PMatrix * position; \n\
\n\
v_position = position; \n\
v_color = a_color; \n\
v_texCoord = a_texCoord; \n\
v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz; \n\
} \n\
";
const char* ccPositionTextureColorForLight2_f = " \
const vec3 lightAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightSpecular = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialSpecular = vec3(1.0, 1.0, 1.0); \n\
const int shininess = 8; // 0-128 \n\
\n\
const vec3 eyePosition = vec3(512.0, 128.0, 442.0); \n\
const vec3 lightDirection = vec3(1.0, 1.0, 1.0); \n\
\n\
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
\n\
void main() { \n\
vec4 color = v_color * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
\n\
vec3 normal = v_normal; \n\
vec3 n_normal = normalize(normal); \n\
vec3 n_lightDirection = normalize(lightDirection); \n\
float cosNL = max(dot(n_normal, n_lightDirection), 0.0); \n\
vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL; \n\
\n\
vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0); \n\
\n\
vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz); \n\
vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection; \n\
vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0); \n\
//vec3 reflection = normalize(n_eyeDirection + n_lightDirection); \n\
//vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0); \n\
\n\
gl_FragColor = color * (ambient + diffuse + specular); \n\
} \n\
";

效果:

 

// 在片段着色器中處理光照計算(環境光+漫反射+鏡面反射+衰減系數)
const char* ccPositionTextureColorForLight3_v = " \
uniform vec2 translate; \n\
\n\
attribute vec4 a_position; \n\
attribute vec4 a_color; \n\
attribute vec2 a_texCoord; \n\
attribute vec3 a_normal; \n\
\n\
#ifdef GL_ES \n\
varying mediump vec4 v_position; \n\
varying mediump vec4 v_color; \n\
varying mediump vec2 v_texCoord; \n\
varying mediump vec3 v_normal; \n\
varying float v_distance; \n\
#else \n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
varying float v_distance; \n\
#endif \n\
\n\
void main() { \n\
vec4 position = CC_MVMatrix * a_position; \n\
position.x += translate.x; \n\
position.y += translate.y; \n\
gl_Position = CC_PMatrix * position; \n\
\n\
v_position = position; \n\
v_color = a_color; \n\
v_texCoord = a_texCoord; \n\
v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz; \n\
} \n\
";
const char* ccPositionTextureColorForLight3_f = " \
const vec3 lightAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightSpecular = vec3(1.0, 1.0, 1.0); \n\
const float lightAttenuationConst = 1.0; \n\
const float lightAttenuationLinear = 0.0002; \n\
const float lightAttenuationQuadratic = 0.000001; \n\
const vec3 materialAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialSpecular = vec3(1.0, 1.0, 1.0); \n\
const int shininess = 8; // 0-128 \n\
\n\
const vec3 lightPosition = vec3(1024.0, 512.0, 100.0); \n\
const vec3 eyePosition = vec3(512.0, 256.0, 442.0); \n\
\n\
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
varying float v_distance; \n\
\n\
void main() { \n\
vec4 color = v_color * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
\n\
vec3 lightDirection = lightPosition - v_position.xyz; \n\
float distance = length(lightDirection); \n\
float atten = 1.0 / (lightAttenuationConst + lightAttenuationLinear * distance + lightAttenuationQuadratic * distance * distance); \n\
\n\
vec3 normal = v_normal; \n\
vec3 n_normal = normalize(normal); \n\
vec3 n_lightDirection = normalize(lightDirection); \n\
float cosNL = max(dot(n_normal, n_lightDirection), 0.0); \n\
vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL; \n\
\n\
vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0); \n\
\n\
vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz); \n\
vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection; \n\
vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0); \n\
//vec3 reflection = normalize(n_eyeDirection + n_lightDirection); \n\
//vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0); \n\
\n\
float colorA = color.a; \n\
gl_FragColor = vec4(color.rgb * (ambient + diffuse + specular).xyz * atten, colorA); \n\
} \n\
";

效果:

 

// 在片段着色器中處理光照計算(環境光+漫反射+鏡面反射+聚光燈+衰減系數)
const char* ccPositionTextureColorForLight4_v = " \
uniform vec2 translate; \n\
const vec3 spotlightPosition = vec3(512.0, 256.0, 120.0); \n\
const vec3 lightPosition = vec3(512.0, 256.0, 442.0); \n\
const vec3 eyePosition = vec3(512.0, 256.0, 442.0); \n\
\n\
attribute vec4 a_position; \n\
attribute vec4 a_color; \n\
attribute vec2 a_texCoord; \n\
attribute vec3 a_normal; \n\
\n\
#ifdef GL_ES \n\
varying mediump vec4 v_position; \n\
varying mediump vec4 v_color; \n\
varying mediump vec2 v_texCoord; \n\
varying mediump vec3 v_normal; \n\
varying mediump float v_distance; \n\
varying mediump vec3 v_lightDirection; \n\
varying mediump vec3 v_spotlightDirection; \n\
#else \n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
varying float v_distance; \n\
varying vec3 v_lightDirection; \n\
varying vec3 v_spotlightDirection; \n\
#endif \n\
\n\
void main() { \n\
vec4 position = CC_MVMatrix * a_position; \n\
position.x += translate.x; \n\
position.y += translate.y; \n\
gl_Position = CC_PMatrix * position; \n\
\n\
v_position = position; \n\
v_color = a_color; \n\
v_texCoord = a_texCoord; \n\
v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz; \n\
\n\
vec3 lightDirection = lightPosition - position.xyz; \n\
vec3 spotlightDirection = spotlightPosition - position.xyz; \n\
v_distance = length(lightDirection); \n\
v_lightDirection = normalize(lightDirection); \n\
v_spotlightDirection = normalize(spotlightDirection); \n\
} \n\
";
const char* ccPositionTextureColorForLight4_f = " \
const vec3 lightAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightSpecular = vec3(1.0, 1.0, 1.0); \n\
const float lightAttenuationConst = 1.0; \n\
const float lightAttenuationLinear = 0.001; \n\
const float lightAttenuationQuadratic = 0.000001; \n\
const vec3 materialAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialSpecular = vec3(1.0, 1.0, 1.0); \n\
const int shininess = 8; // 0-128 \n\
const int lightSpotExponent = 1; \n\
const float lightSpotCosCutoff = cos(45.0 / 180.0 * 3.1415926); \n\
\n\
const vec3 lightPosition = vec3(512.0, 256.0, 442.0); \n\
const vec3 eyePosition = vec3(512.0, 256.0, 442.0); \n\
\n\
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
varying float v_distance; \n\
varying vec3 v_lightDirection; \n\
varying vec3 v_spotlightDirection; \n\
\n\
void main() { \n\
vec4 color = v_color * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
\n\
// vec3 lightDirection = lightPosition - v_position.xyz; \n\
vec3 n_spotDirection = normalize(lightPosition - vec3(512.0, 256.0, 0.0)); \n\
vec3 n_spotlightDirection = normalize(v_spotlightDirection); \n\
// float distance = length(lightDirection); \n\
float atten = 1.0 / (lightAttenuationConst + lightAttenuationLinear * v_distance + lightAttenuationQuadratic * v_distance * v_distance); \n\
\n\
vec3 normal = v_normal; \n\
vec3 n_normal = normalize(normal); \n\
vec3 n_lightDirection = normalize(v_lightDirection); \n\
float cosNL = max(dot(n_normal, n_lightDirection), 0.0); \n\
vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL; \n\
\n\
vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0); \n\
\n\
vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz); \n\
vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection; \n\
vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0); \n\
//vec3 reflection = normalize(n_eyeDirection + n_lightDirection); \n\
//vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0); \n\
\n\
float cosSpot = dot(-1 * n_spotDirection, -1 * n_spotlightDirection); \n\
if (cosSpot > lightSpotCosCutoff) \n\
{ \n\
float spotEffect = pow(cosSpot, lightSpotExponent); \n\
atten += spotEffect; \n\
} \n\
float colorA = color.a; \n\
gl_FragColor = vec4(color.rgb * (ambient + diffuse + specular).xyz * atten, colorA); \n\
} \n\
";

效果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM