ADS光照模型實例(GLSL實現)
來自專欄技術美術
19 人贊了文章
keywords:ambient diffuse specular、Phong Shading、Phong reflection model
公式概述
ADS光照模型又稱為「馮氏反射模型」(Phong reflection model),為什麼叫馮氏:
裴祥風(Bùi T??ng Phong音譯, 1942年—1975年),美國電腦CG研究學者,于越南出生。他於1973年在尤他大學取得哲學博士學位,並發明了Phong反射模型及Phong著色法,並廣為CG界採用。1975死於白血病。
ADS光照模型公式縮寫:
LightIntensity = Ambient + Diffuse + Specular;
參數說明:
- Ambient 環境光
- Diffuse 漫反射
- Specular 全反射光 / 鏡面光
三個參數渲染效果示例:
三個參數拆解如下:
Ambient = La * Ka;Diffuse = Ld * Kd * max( dot(s, n), 0.0 );Specular = Ls * Ks * pow( max( dot(r, v), 0.0 ), f );
參數說明:
- La 環境光強度(Ambient light intensity)
- Ka 材質環境光反射率 / 材質環境光反射係數(Ambient reflectivity)
- Ld 漫射光強度 / 散射光強度(Diffuse light intensity)
- Kd 材質漫反射率 / 材質漫反射係數(Diffuse reflectivity)
- s 頂點 / 曲面點 到光源方向的單位向量(Direction from the surface point to the light source)
- n 頂點 / 曲面點 的法線單位向量(Normal vector at the surface point)
- Ls 鏡面光強度 / 全反射光強度(Specular light intensity)
- Ks 材質鏡面反射率 / 材質鏡面反射係數(Specular reflectivity)
- r 完全反射向量( the vector of perfect reflection)
- v 頂點 / 曲面點 到攝像機方向的向量( the vector towards the viewer)
- f 鏡面高光(specular highlights),值範圍在1到200之間,值越小,鏡面亮點越大
光源出射強度 / 出射光強度(Intensity of the outgoing light )I
的完整計算公式如下:
渲染實例
OpenGL API 版本為4.1。
假設不考慮環境光和鏡面光,只考慮漫射光,渲染效果:
shader 代碼:
diffuse.vert
#version 410layout (location = 0) in vec3 VertexPosition;layout (location = 1) in vec3 VertexNormal;out vec3 LightIntensity;uniform vec4 LightPosition; // Light position in eye coords.uniform vec3 Kd; // Diffuse reflectivityuniform vec3 Ld; // Diffuse light intensityuniform mat4 ModelViewMatrix;uniform mat3 NormalMatrix;uniform mat4 ProjectionMatrix;uniform mat4 MVP;voidmain(){ vec3 tnorm = normalize( NormalMatrix * VertexNormal); vec4 eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0); vec3 s = normalize(vec3(LightPosition - eyeCoords)); LightIntensity = Ld * Kd * max( dot( s, tnorm ), 0.0 ); gl_Position = MVP * vec4(VertexPosition,1.0);}
diffuse.frag
#version 410in vec3 LightIntensity;layout( location = 0 ) out vec4 FragColor;void main() { FragColor = vec4(LightIntensity, 1.0);}
同時計算環境光、漫反射、鏡面反射的渲染效果:
shader 代碼:
phong.vert#version 410layout (location = 0) in vec3 VertexPosition;layout (location = 1) in vec3 VertexNormal;out vec3 LightIntensity;struct LightInfo { vec4 Position; // Light position in eye coords. vec3 La; // Ambient light intensity vec3 Ld; // Diffuse light intensity vec3 Ls; // Specular light intensity};uniform LightInfo Light;struct MaterialInfo { vec3 Ka; // Ambient reflectivity vec3 Kd; // Diffuse reflectivity vec3 Ks; // Specular reflectivity float Shininess; // Specular shininess factor};uniform MaterialInfo Material;uniform mat4 ModelViewMatrix;uniform mat3 NormalMatrix;uniform mat4 ProjectionMatrix;uniform mat4 MVP;void main(){ vec3 tnorm = normalize( NormalMatrix * VertexNormal); vec4 eyeCoords = ModelViewMatrix * vec4(VertexPosition,1.0); vec3 s = normalize(vec3(Light.Position - eyeCoords)); vec3 v = normalize(-eyeCoords.xyz); vec3 r = reflect( -s, tnorm ); float sDotN = max( dot(s,tnorm), 0.0 ); vec3 ambient = Light.La * Material.Ka; vec3 diffuse = Light.Ld * Material.Kd * sDotN; vec3 spec = vec3(0.0); if( sDotN > 0.0 ) spec = Light.Ls * Material.Ks * pow( max( dot(r,v), 0.0 ), Material.Shininess ); LightIntensity = ambient + diffuse + spec; gl_Position = MVP * vec4(VertexPosition,1.0);}
phong.frag
#version 410in vec3 LightIntensity;layout( location = 0 ) out vec4 FragColor;void main() { FragColor = vec4(LightIntensity, 1.0);}
demo完整代碼:
https://github.com/dawnarc/ShadingDemo推薦閱讀:
※ue4卡通渲染的概念及技巧
※第1章 引擎的紛爭 (感謝大食堂對本章的校驗)
※第十一章 場景管理 Part4(11.5 To 11.7)
※[Siggraph15] GPU-Driven Rendering Pipelines
※遊戲引擎列表