Vulkan 片元著色器特效1 體積霧

2021-10-08 23:10:12 字數 2374 閱讀 3977

我們在之前做過的案例:vulkan_動態地形細分(tessellation shader)(本次特效也是基於此場景實現)中介紹過簡單的霧特效,通過它可以模擬很多現實世界中與霧、煙等相關的場景。但是簡單的霧特效也有一定的侷限性,如在實現山中煙霧繚繞的效果時就比較假。這是由

於簡單的霧特效沒有考慮到變化的情況,只是採用簡單的與距離相關的公式計算霧濃度因子。

而現實世界中的山中霧氣往往是隨風變化的,並不是在所有的位置都遵循完全一致的霧濃度因子計算公式。本此我們來看一種能更好地模擬山嵐煙雲效果的霧特效技術——體積霧,通過它可以開發出非常真實的山中煙霧繚繞的效果。

介紹具體的案例之前,首先需要了解本節案例實現體積霧的基本原理。體積霧實現的關鍵在於計算出每個待繪製片元的霧濃度因子,然後根據霧濃度因子、霧的顏色及片元本身取樣的紋理顏色計算出片元的最終顏色。

你可能會有疑問:簡單的霧特效採用的不也是這樣的策略嗎?確實如此,基本的大思路很類似,但體積霧霧濃度因子的計算模型不像簡單的霧特效那樣是乙個簡單呆板的公式,具體的計算策略如圖所示。

從圖中可以看出,體積霧具體的計算策略如下(此計算由片元著色器完成):

為了進一步增加真實感,實際案例中的霧平面並不是乙個完全的平面,而是加入了正弦函式的高度擾動使得霧平面看起來有波動效果,如上圖中右側所示。(可參見vulkan_頂點著色器特效1(流動的水面或飄揚的紅旗)實現原理)

我們主要是實現了兩種霧化,乙個是遠處場景霧化,還有乙個是低窪處體積霧動態效果,可見下邊兩幅圖:

具體片元著色器如下:

#version 450

layout (set =

0, binding =

1) uniform sampler2d samplerheight;

layout (set =

0, binding =

2) uniform sampler2darray samplerlayers;

layout (set =

0, binding =

3) uniform ubocon //體積霧控制引數

ubocon;

layout (location =

0) in vec3 innormal;

layout (location =

1) in vec2 inuv;

layout (location =

2) in vec3 inviewvec;

layout (location =

3) in vec3 inlightvec;

layout (location =

4) in vec3 ineyepos;

layout (location =

5) in vec3 inworldpos;

layout (location =

0) out vec4 outfragcolor;

//根據地形高度獲取不同紋理

vec3 sampleterrainlayer()

return color;

}//遠方霧化

float

fog(

float density)

//動態體積霧

float

tjfogcal

(vec4 plocation)

else

}void

main()

片元著色器的 main 方法,其中首先執行了基礎光照和過程紋理計算,根據片元高度計算出了待處理片元的紋理取樣顏色值。之後霧化遠處操作,最後計算出體積霧濃度因子,最後根據霧濃度因子、霧的顏色及片元本身的紋理取樣顏色計算出片元的最終顏色值。

最後執行結果可見下圖或者文章開頭**:

到這裡為止,體積霧技術就介紹完了,經過上面的介紹你可能已經發現體積霧並不是實際存在的 3d 模型,只是在應該被霧覆蓋的片元上通過某種計算模型的計算混合了霧的顏色,最後造成了有霧覆蓋的效果。體積霧的實際計算模型有很多,本部分只給出了比較簡單的一種(體積霧實現原理參照《opengl es 3.x 遊戲開發》實現,有興趣的可購買書籍詳看)。

Vulkan 片元著色器特效2 反射 折射 色散

反射與折射的效果我們可以參照之前vulkan shader 環境對映天空盒檢視,之前也有簡述過兩者原理,今天除了上述兩種效果外,我們主要來看一下色散的效果 在此之前我們首先來簡單的回顧一下反射與折射,首先我們得理解立方體貼圖 立方圖紋理是一種特殊的紋理對映技術,主要包括如下兩個要點。從圖中可以看出,...

頂點著色器與片元著色器

頂點著色器 在管線中的位置 1號 這圖作的跟病毒似的 可以替代下面這些傳統的操作 頂點變換 法線變化及規範化 紋理座標生成 紋理座標變換 光照彩色材質應用 頂點著色器可以用來指定一系列完全通用的 並將應用於各個頂點及相關資料上的操作。理解這點很重要。頂點著色器不會取代一次需要多個頂點的情況或者需要拓...

WebGL著色器discard捨棄片元

本文是webgl電子書的2.15節內容 discard關鍵字通常出現在片元著色器的if語句或for語句中,discard的使用語法就像for語句中的continue和break關鍵字一樣,直接編寫discard 即可,但是discard的功能比較特殊,專門用於著色器片元處理。如果想理解discard...