初探霧效果!shader 原始碼分析與講解! Cocos Creator 3D Shader Fog !
初探霧效果!shader 原始碼分析與講解! Cocos Creator 3D Shader Fog !
隨便講講霧的原理以及舊版本的使用霧的方法。
效果
原理
霧效(fog
)是遊戲中常用的一種效果,根據遠近產生不同的深度的霧效果。
這個效果涉及兩個關鍵字。
- 距離
- 顏色
在著色器中,霧效的距離
,一般轉成換計算霧效因素(factor_fog
),這個數字範圍是0-1
。
1
表示完全不受霧影響0
表示完全被霧籠罩
接著再根據這個霧效因素去計算顏色
,混合當前顏色color
和霧factor_fog
的顏色即可。
mix(cc_fogColor.rgb, color.rgb, factor_fog)
接下來就是如何去計算這個霧效因素了。
霧效因素一般是通過由攝像機位置(cc_cameraPos
)和當前點位置(世界座標,由世界空間矩陣和模型座標計算的wPos
)的距離去計算的。
float cam_dis = distance(cc_cameraPos, wPos);
不同的霧效果,採用不同的方式去計算霧效因素。
線性霧
線性一般會有兩個引數去計算。霧開始的地方fogStart
和霧最遠的地方fogEnd
。
- 當距離小於霧開始的地方,表示沒有霧,即霧效因素為
1
- 當距離大於霧最遠的地方,完全被霧給覆蓋了,即霧效因素為
0
factor_fog = clamp((fogEnd - cam_dis) / (fogEnd - fogStart), 0., 1.);
當然也可以改造一下,在0-1
之間平滑一些。
factor_fog = 1.0 - smoothstep(fogStart, fogEnd, fogDistance);
指數霧
指數霧就是用指數函式根據距離計算霧效因素。
一般會有一個霧濃度fogDensity
去控制這個指數函式。
一般指數霧:
factor_fog = exp(-cam_dis * fogDensity);
平方指數霧:
factor_fog = exp(-cam_dis * cam_dis * fogDensity * fogDensity);
層級霧
層級霧計算過程相對複雜,大致過程就是計算水平面的距離和高度距離以及濃度引數,具體實現過程可以參考原始碼 cc-fog.chunk
fDensity = (sqrt(1.0 + ((fDeltaD / fDeltaY) * (fDeltaD / fDeltaY)))) * fDensityIntegral;
factor_fog = exp(-fDensity);
移植
在 Cocos Creator 3D v1.2
版本之前還未提供霧效果,那麼該如何移植或定製呢?
把控一個重點,霧效果的關鍵就是計算霧效因素。
因為材質預設使用的是 builtin-standard.effect
,可以拷貝一份重新寫個build-in-fog.effect
,然後再將需要霧化的材質選擇這個effect
。
先在頂點著色器中加一個霧效因素的計算方法。
out float v_fogFactor;
float computeFogFactor(float fogDistance){
const float start = 1000.0;
const float end = 3000.0;
const float density = 0.0002;
// return clamp((end-fogDistance)/(end-start), 0.0, 1.0); //霧化因子線性變化
return 1.0 - smoothstep(start,end,fogDistance); //霧化因子非線性變化
// return exp(-(density*fogDistance)); // 指數霧
// return exp(-density*density*fogDistance*fogDistance); // 指數霧2
}
把霧效因素傳給片元著色器。
v_fogFactor = computeFogFactor(length(cc_cameraPos.xyz - pos.xyz));
在片元著色器中接收霧效因素。
in float v_fogFactor;
計算混合顏色。
color.rgb = mix(fogColor, color.rgb, v_fogFactor);
效果預覽(示例專案 ):
小結
霧
fog
! 計算霧效係數 !混合顏色 !shader
!
以上為白玉無冰講解 Cocos Creator 3D v1.2
中的 "霧效果(fog)原理解析"
的技術分享。歡迎分享給身邊的朋友!
天下事有難易乎?為之,則難者亦易矣;不為,則易者亦難矣。人之為學有難易乎?學之,則難者亦易矣;不學,則易者亦難矣。