體積云染色方案

最近接了一個實現(xiàn)體積云風(fēng)格化染色的需求拔创,策劃大致的意思是想實現(xiàn)如下面幾張圖片示意的效果:

Ref 1
Ref 2
Ref 3
Ref 4

目前實現(xiàn)的體積云顏色效果大多是通過以白色作為基色奸笤,經(jīng)過陰影疊加后呈現(xiàn)出來的克蚂,大致如下圖所示:

在疊加了太陽光之后俱诸,可以做到如下的效果:

可以看到垂攘,其效果距離預(yù)期還有不小的差距维雇,因此需要對方案做修正。

先對參考圖中的效果做一下簡單的分析晒他,Ref 2中表現(xiàn)出來的效果通過一個簡單的疊色就能夠輸出吱型,而不同區(qū)域不同的顏色效果就需要結(jié)合疊色貼圖來給出(或者按照某些規(guī)則,比如與大氣散射相結(jié)合來給出不同位置的不同疊色)陨仅;其余三張貼圖津滞,假如不考慮陽光打在云層底部散射造成的明亮著色,其實也就是一個簡單的疊色就能輸出灼伤,因此總的來說触徐,參考圖中的效果主要包含兩項:

  1. 疊色,如果想要實現(xiàn)局部疊色狐赡,就需要給出一種規(guī)則撞鹉,在不同的區(qū)域輸出不同的疊色效果。
  2. inscattering散射颖侄,通過相函數(shù)對太陽光散射效果進(jìn)行模擬

下面我們一起來看一下要想實現(xiàn)給定的著色效果鸟雏,需要做怎么樣的處理。

為了快速確定方案览祖,這里使用shadertoy上現(xiàn)成的案例來進(jìn)行驗證孝鹊,這里是測試方案地址,如不做說明展蒂,下面不同方案嘗試中的效果截圖都來自于此方案又活。

1. 方案預(yù)研

1.1 原始著色

首先來看一下,不做任何處理下的云層效果表現(xiàn)锰悼,如下圖所示:

基本顏色為白色柳骄,通過一些灰色來表示云層對光線的遮擋效果。

1.2 全局疊色

所謂的全局疊色指的是在原始著色的基礎(chǔ)上乘上一個給定的顏色值來實現(xiàn)云層著色的方案箕般,這個方案用如下公式來表示:

return float4(originCol.rgb * tintCol, originCol.a);

效果圖:

tintCol = float3(1.0, 0.3, 0.0)
tintCol = float3(1.0, 0.9, 0.0)
tintCol = float3(0.0, 0.9, 0.8)
tintCol = float3(0.0, 0.8, 1.8)

從結(jié)果可以看出夹界,雖然相對于原始著色方案而言,確實可以給出非常豐富的著色效果隘世,但是相距預(yù)期方案中豐富的層次變化還有一定距離可柿。

1.3 明暗過渡著色

所謂的明暗過渡著色,指的是根據(jù)原始方案中的著色結(jié)果作為權(quán)重值對兩個給定的顏色進(jìn)行混合的著色方案丙者,用公式來表示:

float3 finalCol = saturate(lerp(darkCol, brightCol, originCol.rgb));
return float4(finalCol, originCol.a);

效果圖:

darkCol = vec3(0.0, 0.3, 0.1), brightCol = vec3(1.0, 0.3, 0.0)
darkCol = vec3(0.0, 0.0, 0.0), brightCol = vec3(1.0, 0.0, 0.0)
darkCol = vec3(-0.5, 0.0, 0.0), brightCol = vec3(1.0, 0.0, 0.0)

從效果上來看复斥,明暗過渡顏色在明暗顏色一脈相承(比如都是紅色,只是亮度不相同)時械媒,可以得到比較自然的表現(xiàn)目锭,且對于顏色過渡的力度控制更為細(xì)膩,但是在明暗顏色相去較遠(yuǎn)時痢虹,就會使得效果比較魔幻。

1.4 漸變著色

明暗過渡是通過兩個顏色的混合來實現(xiàn)顏色過渡的主儡,但是從前面的參考效果來看奖唯,云層顏色效果可能會涉及到不少于兩種顏色的參與,比如可以從顏色A過渡到B糜值,再過渡到C的情況丰捷,對于這種情況,可以考慮使用類似photoshop的漸變方案來進(jìn)行著色寂汇,其實現(xiàn)可以用如下公式來表示:

    float points[] = float[](0.25, 0.55, 0.9, 0.93, 0.98);
    vec3 cols[] = vec3[](
        vec3(1.5, 0.0, 0.0),
        vec3(1.0, 0.4, 0.6),
        vec3(1.0, 0.6, 0.7),
        vec3(1.0, 0.8, 0.2),
        vec3(1.0, 1.0, 0.0)
        );
    int colNum = points.length();
    float originalCol = OriginalColor.r;
    float scale = 1.0;
    originalCol = originalCol * scale;
    if(originalCol < points[0])
        return cols[0];
    for(int i = 1; i < colNum; i++)
    {
        if(originalCol < points[i])
            return mix(cols[i - 1], cols[i], (OriginalColor.r - points[i - 1])/(points[i] - points[i - 1]));
    }
    if(originalCol > points[colNum - 1])
        return cols[colNum - 1];

效果圖:

    float points[] = float[](0.0, 0.25, 0.55, 0.9, 0.93);
    vec3 cols[] = vec3[](
        vec3(0.0, 0.0, 0.0),
        vec3(0.6, 0.0, 0.0),
        vec3(1.0, 0.4, 0.6),
        vec3(1.0, 0.65, 0.6),
        vec3(1.0, 0.8, 0.6)
        );
    float points[] = float[](0.0, 0.25, 0.55, 0.9, 0.93, 1.0);
    vec3 cols[] = vec3[](
        vec3(0.0, 0.0, 0.0),
        vec3(1.0, 0.4, 0.6),
        vec3(0.5, 0.5, 0.6),
        vec3(1.0, 0.6, 0.7),
        vec3(1.0, 0.7, 0.7),
        vec3(1.0, 1.0, 0.7)
        );
    float points[] = float[](0.0, 0.25, 0.55, 0.9, 0.93);
    vec3 cols[] = vec3[](
        vec3(0.0, 0.0, 0.1),
        vec3(0.6, 0.0, 0.6),
        vec3(1.0, 0.4, 0.6),
        vec3(1.0, 0.65, 0.6),
        vec3(1.0, 0.7, 0.6)
        );

這種方案可以給出多層漸變的著色效果病往,但是存在如下的一些問題:

  1. 參與漸變的顏色需要保持一致,顏色跳變會使得效果非常難看
  2. 依然無法模擬參考圖中太陽光打在云層底部經(jīng)由相函數(shù)散射出來的明亮效果(如Ref4的明黃色)骄瓣。

1.5 添加inscattering相函數(shù)散射

在原始方案中添加相函數(shù)控制的inscattering停巷,已經(jīng)能基本模擬底部受太陽光照下的金邊效果:

在此基礎(chǔ)上再添加疊色方案,可以得到如下結(jié)果:

這個方案雖然可以生成邊緣處的金邊榕栏,但是在背光處的黑色太深了畔勤,這是因為只考慮了單次散射的效果,為了消除這種死黑的表現(xiàn)臼膏,還需要添加天光與大地反射導(dǎo)致的散射硼被。

添加了大地散射后,可以做到如下的效果:

在此基礎(chǔ)上再添加天光散射渗磅,可以得到如下效果:

這是未做任何疊色的情況下輸出的結(jié)果嚷硫,其中黃色表示的是太陽光散射的效果,紫色表示的是大地散射的效果仔掸,藍(lán)色表示的是天光散射的效果起暮。

可以看到会烙,在這種算法作用下,不需要做疊色方案系吭,就已經(jīng)能夠得到比前面的疊色方案還要好的結(jié)果肯尺。

2. 方案驗證

shadertoy的實現(xiàn)較為簡單,不過已經(jīng)基本驗證了體積云著色的相關(guān)效果锄蹂,為了能應(yīng)用到項目中寨昙,最終還是需要在引擎中進(jìn)行相關(guān)著色處理舔哪,下面給出在UE4.26中應(yīng)用各種inscattering之后的效果表現(xiàn)捉蚤。

2.1 現(xiàn)有染色方案

2.1.1 太陽光染色

UE4.26提供了一種雙光源體積云著色方案,其中第一盞光源是默認(rèn)的太陽光陕悬,通過對太陽光顏色與亮度進(jìn)行調(diào)整捉超,可以影響到云層的染色效果:

這種方案的一個問題是,這種染色不但會影響到云層染色效果惜纸,還會影響到大氣(天空)散射效果祠够,沒有辦法做到解耦哪审。而要想避開對大氣散射的影響,則需要調(diào)整光源的另一項屬性:

Atmosphere Sun Light開關(guān)用于控制此光源是否用于Cloud/Atmosphere著色,當(dāng)關(guān)閉時痛侍,云層繪制全黑主届。當(dāng)開啟后,就可以通過調(diào)整Cloud Scattered Luminance來調(diào)整散射顏色绘闷。

這種狀態(tài)下的云層著色就不會影響到大氣散射了印蔗。

2.1.2 雙太陽光染色

再嘗試打開第二盞光源华嘹,依然是平行光耙厚,得到的效果并不能令人滿意,除了效果調(diào)整十分費(fèi)勁之外泛豪,且沒有辦法如前面shadertoy demo一樣臀叙,能夠?qū)崿F(xiàn)多層染色劝萤。

2.1.2 Ground染色

VolumetricCloudComponent上有一個變量叫GroundAlbedo,從描述上來看跟我們前面在shadertoy demo中的ground inscattering相似厌处,先來看下這個參數(shù)調(diào)整是否能得到不一樣的表現(xiàn)。

這個開關(guān)的打開需要在材質(zhì)的Volumetric Advanced節(jié)點(diǎn)中打開GroundContribution開關(guān)瑰排,但實際上這個節(jié)點(diǎn)并沒有這個選項:

這是怎么回事呢?實際上這個是在此節(jié)點(diǎn)的選項面板中進(jìn)行打開的:

此外,在源碼追蹤的過程中傻挂,我們發(fā)現(xiàn)Shader在處理Ground相關(guān)的著色時金拒,還存在一個由宏MATERIAL_VOLUMETRIC_ADVANCED_GROUND_CONTRIBUTION進(jìn)行控制的實現(xiàn)邏輯,這個宏
同樣也是由上述開關(guān)進(jìn)行控制幢码。

打開之后症副,調(diào)節(jié)GroundAlbedo闹啦,效果對比如下所示:


GroundAlbedo = (255, 0, 0)
GroundAlbedo = (0, 255, 0)

可以看到,通過對顏色的調(diào)節(jié),可以實現(xiàn)底部染色的修正挚歧,不過這個修正效果不是很明顯,也就是說,GroundAlbedo對云層的影響力度比較小啄骇,是否可以增強(qiáng)這個影響呢?通過對源碼的分析虽惭,發(fā)現(xiàn)當(dāng)前并無此scale因子,而要想實現(xiàn)就需要添加額外的代碼進(jìn)行處理。

下面給出Cloud Scattered Luminance為綠色谱邪,GroundAlbedo為紫色時的表現(xiàn):

在此基礎(chǔ)上對陽光顏色及亮度進(jìn)行修正,可以得到如下效果:

從上面給出的效果可以看到惦银,GroundAlbedo跟CloudScattered Luminance兩個參數(shù)都是能夠很好的用于調(diào)整云層著色效果的咆课,只是GroundAlbedo影響的強(qiáng)度是固定的(CloudScattered Luminance由于數(shù)據(jù)使用的是浮點(diǎn)數(shù)末誓,可以直接調(diào)整亮度),使用起來不太靈活傀蚌,這里嘗試增加GroundAlbedoScale參數(shù)基显,用于對這個參數(shù)進(jìn)行增強(qiáng)。

2.1.3 Modified CloudScattering/GroundAlbedo

在shader與cpp代碼中添加了GroundAlbedoScale參數(shù)后,可以實現(xiàn)更為明顯的GroundAlbedo調(diào)整效果艺谆,下面給出的是僅僅調(diào)整GroundAlbedoScale的效果對比:

Scale = 20
Scale = 1

測試的過程中發(fā)現(xiàn)抹估,Shader中存在multiscattering相關(guān)的邏輯贸典,這個邏輯是通過Volumetric Advanced Output節(jié)點(diǎn)的Multi Scattering Approximation Octave Count參數(shù)進(jìn)行控制的班利,此參數(shù)對應(yīng)的是在RayMarching的過程中,射線上的每個Sample在沿著太陽光方向的二次采樣的采樣點(diǎn)數(shù)目丙笋,默認(rèn)為1.0(實際上shader使用的采樣點(diǎn)數(shù)目是在這個基礎(chǔ)上加了1),下面我們改成0換個角度看下效果:

Scale = 1
Scale = 20
Scale = 5

其中綠色是GroundAlbedo的顏色者甲,黃色是太陽光顏色,紫色是Cloud Scattered Luminance的顏色,看起來效果相對于1.0還更柔和一點(diǎn)氧骤。

此外并思,在Volumetric Advanced Output節(jié)點(diǎn)的屬性面板上還有一個Per Sample Phase Evaluation開關(guān)占贫,這個從名字上來判斷,就是用于為射線上的每個sample做單獨(dú)的phase計算凡蜻,這個開關(guān)打開會加重計算消耗,因此在使用的時候需要確認(rèn)是否有必要。

通過對各種參數(shù)的調(diào)整寓免,我們是可以實現(xiàn)如下的一些效果的:

Cloud Scattered Luminance = (0, 200, 5), CloudAlbedo = (123, 0, 170), CloudAlbedoScale = 100

相對于ShaderToy的Demo而言袜香,UE4.26渲染的體積云蜈首,在底部缺少了云層遮蔽導(dǎo)致的黑色效果,從而顯得立體感不足辣卒,我們嘗試來確定這是UE實現(xiàn)機(jī)制的問題疗杉,還是因為參數(shù)調(diào)整不當(dāng)導(dǎo)致狸演。

下面給出了不同Albedo Color下的云層表現(xiàn),可以看到僻他,Albedo Color是可以用于調(diào)整云層底部的亮度的宵距。

Albedo Color = 0.1
Albedo Color = 0.3
Albedo Color = 0.9

雖然如此,云層底部顏色依然無法出現(xiàn)demo中接近黑色的表現(xiàn)吨拗,理論上來說满哪,太陽光從上往下照射時,如果不考慮天光等間接光劝篷,那么云層底部肯定是黑色的哨鸭,而當(dāng)前這種表現(xiàn)只能說明是間接光對于云層渲染具有較大的影響,如果希望削弱這個影響娇妓,就需要降低間接光對云層著色效果的比重像鸡。

反應(yīng)到shader代碼中,我們可以將DistantLightLuminance對SunSkyLuminance的累加作用置為0峡蟋,就可以得到如下這種比較接近的效果(遠(yuǎn)景處存在一些問題坟桅,可能因為相對于近景處,采樣數(shù)目存在差異導(dǎo)致)

作為對比蕊蝗,打開這個邏輯時的效果表現(xiàn)如下圖所示:

不考慮染色效果作用的話仅乓,后者相對而言更接近現(xiàn)實情況中的表現(xiàn)。

此外蓬戚,在調(diào)試效果的過程中夸楣,發(fā)現(xiàn)GroundAlbedo并不是像此前Demo中一樣通過沿著大地散射方向二次采樣得到,而是按照如下的公式計算得到ScatteredLightLuminance之后疊加到最終輸出的Color上面子漩。

float3 ScatteredLightLuminance = AtmosphereTransmittanceToGround * LightIlluminance * GroundToCloudTransfertIsoScatter;

其中AtmosphereTransmittanceToGround從名字上推斷應(yīng)該是從Ground到當(dāng)前被采樣點(diǎn)位置的Atmosphere Transmittance豫喧,即未考慮云層遮擋情況下的Transmittance,但實際我們知道幢泼,對于云層表面的點(diǎn)紧显,這種計算是合理的,而如果采樣點(diǎn)位于云層內(nèi)部缕棵,這種做法就存在較大誤差了孵班;LightIlluminance對應(yīng)的是AtmosphereLightColor,從C++側(cè)賦值邏輯來看招驴,這個值就是太陽光顏色篙程;最后GroundToCloudTransfertIsoScatter對應(yīng)的是GroundAlbedo經(jīng)過一系列加工后的結(jié)果,反映的是光照打在大地上的反射輸出關(guān)系(相當(dāng)于經(jīng)過了BRDF處理)别厘。

從這個公式看出虱饿,ScatteredLightLuminance實際上指的是太陽光顏色經(jīng)過大地反射后加上大氣散射衰減后的結(jié)果。不過正如前面所說,這里的結(jié)果沒有考慮云層內(nèi)部遮擋作用氮发,因此效果上會有些差異渴肉。這里嘗試對散射衰減項進(jìn)行修正,添加上云層內(nèi)部穿透代價折柠,看看效果上是否能有所改善宾娜。

2.1.4 Secondary Raymarching Scattering

UE實現(xiàn)中是增加了沿著太陽光方向的二次散射計算以實現(xiàn)云層背離太陽時的陰影效果的,而這個功能是通過Volumetric Advanced Output節(jié)點(diǎn)屬性面板的RayMarchVolumeShadow開關(guān)進(jìn)行打開的扇售,關(guān)閉這個開關(guān)時前塔,就會使用shadow map來計算云層陰影(包括light shaft),打開時就會啟用沿著光源方向的二次RayMarching進(jìn)行計算承冰,關(guān)閉跟打開開關(guān)時的效果對比如下所示:

On
Off

看起來對比不是特別明顯华弓,不過在關(guān)閉情況下,底部相對更暗一點(diǎn)困乒。

這里增加沿著向下方向的Ground Inscattering處理邏輯寂屏,查看是否對效果有所增益:

Ground Inscattering On
Ground Inscattering Off

從效果上來看,是有變化的娜搂,但是這個變化方向是有還是劣暫時還不清楚迁霎,調(diào)整下其他效果看下:

On
Off
On
Off

看起來關(guān)閉情況下飽和度要高一點(diǎn),不過也不清楚美術(shù)同學(xué)傾向于哪種風(fēng)格百宇,這里將這套邏輯通過Volumetric Advanced Output節(jié)點(diǎn)的選項面板上的RayMarchVolumeGroundScatter開關(guān)進(jìn)行控制考廉,默認(rèn)關(guān)閉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末携御,一起剝皮案震驚了整個濱河市昌粤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啄刹,老刑警劉巖涮坐,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異誓军,居然都是意外死亡袱讹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門昵时,熙熙樓的掌柜王于貴愁眉苦臉地迎上來廓译,“玉大人,你說我怎么就攤上這事债查。” “怎么了瓜挽?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵盹廷,是天一觀的道長。 經(jīng)常有香客問我久橙,道長俄占,這世上最難降的妖魔是什么管怠? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮缸榄,結(jié)果婚禮上渤弛,老公的妹妹穿的比我還像新娘。我一直安慰自己甚带,他們只是感情好她肯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鹰贵,像睡著了一般晴氨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碉输,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天籽前,我揣著相機(jī)與錄音,去河邊找鬼敷钾。 笑死枝哄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的阻荒。 我是一名探鬼主播挠锥,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼财松!你這毒婦竟也來了瘪贱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤辆毡,失蹤者是張志新(化名)和其女友劉穎菜秦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舶掖,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡球昨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了眨攘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片主慰。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鲫售,靈堂內(nèi)的尸體忽然破棺而出共螺,到底是詐尸還是另有隱情,我是刑警寧澤情竹,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布藐不,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏雏蛮。R本人自食惡果不足惜涎嚼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望挑秉。 院中可真熱鬧法梯,春花似錦、人聲如沸犀概。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阱冶。三九已至刁憋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間木蹬,已是汗流浹背至耻。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留镊叁,地道東北人尘颓。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像晦譬,于是被迫代替她去往敵國和親疤苹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 如果太陽光線被一個處于包含濃密氣體粒子(molecules & aerosols)空間的物體所遮擋住的話敛腌,在這個物...
    離原春草閱讀 1,313評論 0 3
  • 前言 最近在工作中越來越多地接觸到一些3D以及相比常見特性更酷炫的效果卧土,因此萌發(fā)了想要自己從0開始打造一個渲染引擎...
    格子林ll閱讀 1,842評論 0 2
  • 夜鶯2517閱讀 127,720評論 1 9
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭像樊,有人歡樂有人憂愁毕骡,有人驚喜有人失落缝彬,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,536評論 28 53
  • 兔子雖然是枚小碩 但學(xué)校的碩士四人寢不夠 就被分到了博士樓里 兩人一間 在學(xué)校的最西邊 靠山 兔子的室友身體不好 ...
    待業(yè)的兔子閱讀 2,604評論 2 9