在三維圖形學中, 霧化用來描述遠處的物體看上去較爲模糊的現象。
實現霧化的方式有很多種,這裏最簡單的一種就是 線性霧化,在線性霧化中,某一點的霧化程度取決於它與視點之間的距離,距離越遠霧化程度越高,線性霧化有起點和終點,起點表示霧化開始之處,終點表示完全霧化之處,兩點之間某一點的霧化程度與該點的距離呈線性關係
比終點更遠的點完全霧化了,即完全看不到東西,某一點的霧化的程度可以定義爲 霧化因子
<霧化因子> = (<終點> - <當前點與視點間的距離>) / (<終點> - <起點>)
這裏
<起點> <= <當前點與視點間的距離> <= <終點>
如果霧化因子爲 1.0
,表示該點完全沒有霧化,可以很清晰的看到此處的物體,如果爲 0.0
,就表示該點完全霧化了,此處的物體完全看不見
在片元着色器中根據霧化因子,計算片元的顏色
<片元顏色> = <物體表面的顏色> * <霧化因子> + <霧的顏色> * (1 - <霧化因子>)
頂點着色器
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_MvpMatrix;
uniform mat4 u_ModelMatrix;
uniform vec4 u_Eye;
varying vec4 v_Color;
varying float v_Dist;
void main(){
gl_Position = u_MvpMatrix * a_Position;
v_Color = a_Color;
// 計算頂點座標和視點座標的距離
v_Dist = distance(u_ModelMatrix * a_Position, u_Eye);
}
片元着色器
precision mediump float;
uniform vec3 u_FogColor;
uniform vec2 u_FogDist;
varying vec4 v_Color;
varying float v_Dist;
void main(){
// 將霧化因子限制在 0.0 - 1.0 之間
float fogFactor = clamp((u_FogDist.y - v_Dist)/(u_FogDist.y - u_FogDist.x),0.0, 1.0);
vec3 color = mix(u_FogColor, vec3(v_Color), fogFactor);
gl_FragColor = vec4(color, v_Color.a);
}
上面的是在頂點着色器中計算頂點與視點的距離,會造成較大的開銷,其實可以使用另一種計算方法,來近似估算出這個距離,那就是使用頂點經過模型視圖投影矩陣變換後的座標 w
分量,也就是gl_Position
的w
分量,實際上,這個w
分量的值就是頂點的視圖座標的z
分量乘以-1
,在視圖座標系中,視點在原點,視線沿着z
軸負方向,觀察者看到的物體其視圖座標系值z
分量都是負的,而gl_Position
的w
分量值正好是z
分量值乘以-1
,所以可以直接使用該值來近似頂點與視點的距離
頂點着色器修改如下
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_MvpMatrix;
varying float v_Dist;
void main(){
gl_Position = u_MvpMatrix * a_Position;
v_Color = a_Color;
// 使用 w 分量來近似表示頂點與視點的距離
v_Dist = gl_Position.w;
}
片元着色器不變
具體代碼可在 gitee上獲取