Lighting 打光公式白話與WebGL shader code

WebGL lighting ambient diffuse specular color 白話 shader code

Ambient color
環境光顏色,基本的亮度。
highp vec3 ambientLight = vec3(0.8, 0.8, 0.8);
 
Diffuse color 
擴散光顏色,強度為頂點的法線向量與光的方向的夾角,夾角越小強度越強,90度時強度為0,0度時強度為1最大值。
公式=Kd * dot(N,L) 

 
PS:N法向量,L光源方向(依據頂點為起始,光源為終點的向量),Kd為diffuse color的係數
highp float directional = max(dot(normal, lightDirection),
 0.0);
 
Specular color
反射光顏色,強度為頂點上的反射光與頂點到眼睛的向量夾角,夾角越小強度越強,90度時強度為0,0度時強度為1最大值。
公式=Ks * dot(R,V)^ns
PS: R = reflect(-L,N)
PS:N法向量,L光源方向,R反射光,V為眼睛的位置,ns為specular-reflection coefficient,Ks為specular color的係數

 // 定義鏡面高光點光源顏色
 highp vec3 uPointLightingSpecularColor = vec3(0.8, 0.8, 0.75);
 // 定義物體表面光澤度指數
 float uMaterialShininess = 32.0;

 // 獲取觀察點接收光線的方向向量,注意將向量歸一化
 vec3 eyeDirection = normalize(-vMVVertexPosition.xyz);
 // 根據光照方向和法線方向計算鏡面反射光的方向向量
 vec3 reflectionDirection = reflect(-lightDirection, normal);
 // 計算鏡面反射光與觀察點的夾角
 float specularLightDirectional = max(dot(reflectionDirection,
 eyeDirection),
 0.0);
 // 計算鏡面反射光影響係數
 float specularLightWeighting = pow(specularLightDirectional,
 uMaterialShininess);

總和光的公式

 // 環境光 + 擴散光 + 反射光 = 光照係數
 vec3 vLighting = ambientLight +
 (uPointLightingColor * directional) +
 (uPointLightingSpecularColor * specularLightWeighting);

// 首先計算出物體紋理的顏色
 vec4 texelColor = texture2D(uSampler, vec2(vTextureCoord.s,
 vTextureCoord.t));
 // 讓紋理顏色與環境光相乘
 gl_FragColor = vec4(texelColor.rgb*vLighting,
 texelColor.a); 
 
 
光線越強,飽和度越低
光線越暗,飽和度越高
 
Fresnel
 
Complete WebGL shader code(WebGL 專業級3D引擎降臨 使用瀏覽器語言開發 chapter10):

<!-- 創建頂點著色器 Specualr 平行光-->
<script id="shader-vs-specular" type="x-shader/x-vertex">
 /* 定義attribute變數 */
 attribute highp vec3 aVertexNormal; // 法線座標
 attribute vec3 aVertexPosition;      // 定義一個3維浮點向量,用於頂點
 attribute vec2 aTextureCoord;        // 定義一個2維浮點向量,用於紋理座標

 /* 定義uniform變數,通常就是傳進來的一個常量 */
 uniform highp mat4 uNormalMatrix;   // 用於法線轉換的逆轉置矩陣
 uniform mat4 uMVMatrix;               // 定義一個變數用於轉換矩陣
 uniform mat4 uPMatrix;                // 定義一個變數用於投影矩陣

 /* 定義varying變數向片元著色器傳值 */
 varying highp vec2 vTextureCoord;       // 紋理座標
 varying highp vec4 vMVVertexPosition;  // 應用轉換後的頂點座標
 varying highp vec4 vTransformedNormal; // 轉換後的法線向量
 void main(){
 // 將紋理座標的值賦給varying變數
 vTextureCoord = aTextureCoord;
 // 計算物體變換後的位置
 vMVVertexPosition = uMVMatrix * vec4(aVertexPosition, 1.0);
 // 指定頂點座標
 gl_Position = uPMatrix * vMVVertexPosition;
 // 轉換法線
 vTransformedNormal = uNormalMatrix * vec4(aVertexNormal, 1.0);
 }
</script>

 

<!-- 創建片元著色器 Specular 平行光-->
<script id="shader-fs-specular" type="x-shader/x-fragment">
 precision highp float;       // 聲明float類型為高精度
 uniform sampler2D uSampler; // 定義一個變數作為2D紋理採樣器

 /* 定義varying變數從頂點著色器接收值 */
 varying highp vec2 vTextureCoord;       // 紋理座標
 varying highp vec4 vMVVertexPosition;  // 應用轉換後的頂點座標
 varying highp vec4 vTransformedNormal; // 轉換後的法線向量
 void main(){
 /* 下面計算光照效果 */

 // 環境光顏色
 highp vec3 ambientLight = vec3(0.8, 0.8, 0.8);
 // 點光源顏色
 highp vec3 uPointLightingColor = vec3(0.5, 0.5, 0.75);
 // 點光源座標
 highp vec3 uPointLightingLocation = vec3(1.0, 1.0, 0.75);

 // 計算光線方向向量
 vec3 lightDirection = normalize(uPointLightingLocation -
 vMVVertexPosition.xyz);

 // 將片元的法線向量歸一化
 // 頂點法線在經過線線性插值之後,法線的長度會改變,所以我們必須進行歸一化處理
 vec3 normal = normalize(vTransformedNormal.xyz);

 // 計算光照強度
 highp float directional = max(dot(normal, lightDirection),
 0.0);

 // 定義鏡面高光點光源顏色
 highp vec3 uPointLightingSpecularColor = vec3(0.8, 0.8, 0.75);
 // 定義物體表面光澤度指數
 float uMaterialShininess = 32.0;

 // 獲取觀察點接收光線的方向向量,注意將向量歸一化
 vec3 eyeDirection = normalize(-vMVVertexPosition.xyz);
 // 根據光照方向和法線方向計算鏡面反射光的方向向量
 vec3 reflectionDirection = reflect(-lightDirection, normal);
 // 計算鏡面反射光與觀察點的夾角
 float specularLightDirectional = max(dot(reflectionDirection,
 eyeDirection),
 0.0);
 // 計算鏡面反射光影響係數
 float specularLightWeighting = pow(specularLightDirectional,
 uMaterialShininess);

 // 環境光 + 平行光 + 鏡面反射光 = 光照係數
 vec3 vLighting = ambientLight +
 (uPointLightingColor * directional) +
 (uPointLightingSpecularColor * specularLightWeighting);

 // 首先計算出物體紋理的顏色
 vec4 texelColor = texture2D(uSampler, vec2(vTextureCoord.s,
 vTextureCoord.t));
 // 讓紋理顏色與環境光相乘
 gl_FragColor = vec4(texelColor.rgb*vLighting,
 texelColor.a);
 }
</script>

 
Reference:
Computer Graphics with OpeGL 3rd
WebGL 專業級3D引擎降臨 使用瀏覽器語言開發