目的:
在ue4中RayMarch雲層效果。
本篇參考IQ的shader進行着色。
參考:
見上篇
&&
https://zhuanlan.zhihu.com/p/34836881
觀察:
(電影《一一》)
(知乎Grfxlf,基於Henyey-Greenstein模型的雲)
IQ的雲大致看還行。但不能細看。有2個毛病:
1.不基於物理,十分hack的光照模型(最大問題是沒有清晰邊緣)
2.規模單一,難以控制的噪聲
這是本篇參考IQ,尚未解決的問題。
但其優點有3:
1.體現了雲的密度:厚白薄黑
2.“陰影”效果/雲的亮邊暗內效果:有灰有白。
3.有明顯的光照方向感
分析
非常地hack,不作過多解釋。原代碼中blend背景色的效果也不明顯,去了。
diffuse 光線方向上density的變化越大,越亮
col density越稀薄,越亮
多次迭代乘cloudA,模擬衰減,傳統做法爲exp(-t^n)。
float4 GainCloud(float4 re4,float3 sunDir,float t,float3 pos,float stepGain,float CloudSample,float maxHeight,float minHeight,float minX,float maxX,float minY,float maxY,float thre,float cloudA)
{
if(pos.z>minHeight && pos.z<maxHeight && pos.x>minX && pos.x<maxX && pos.y>minY && pos.y<maxY)
{
float den = stepGain*mfbm(pos/CloudSample);
if( den>thre )
{
float dif = clamp((den - mfbm(pos/CloudSample+0.3*sunDir))/0.6, 0.0, 1.0 );
float3 lin = float3(0.65,0.7,0.75)*1.4 + float3(1.0, 0.6, 0.3)*dif;
float4 col = float4( lerp( float3(1.0,0.95,0.8), float3(0.25,0.3,0.35), den ), den );
col.xyz *= lin;
//float3 bgcol=float3(0,1,0);
//col.xyz = lerp( col.xyz, bgcol, 1.0-exp(-0.003*t*t) );
// front to back blending
col.a *= cloudA;
col.rgb *= col.a;
return re4 + col*(1.0-re4.a);
}
else
{
return re4;
}
}
else
{
return re4;
}
int i=0;
float3 nowPos;
float4 re4=float4(0,0,0,0);
for(i=0;i<RayDis;i++)
{
nowPos = camPos+ RayStep*rayDir*i;
re4=GainCloud(re4,sunDir,RayStep*i*tMul,nowPos,stepGain,CloudSample,MaxHeight,minHeight,minX,maxX,minY,maxY,thre,cloudA);
}
re4 = clamp(re4,0,1);
return re4.rgb*reMul;
結果
優點:實時渲染勉強達標。
調整參數做天空雲可以,但太醜且沒必要。(主要是形狀原因,顏色和透明度可以調)
缺點:
複雜場景下fps仍然喫力,若範圍小了又出現明顯地"march紋",若實際用需要更多hack。
proceddual fbm可以進一步優化掉。
光照模型hack且醜,噪聲難以控制形狀細節,導致看起來模糊。
之後若有實際需求,可以研究下Henyey-Greenstein模型。
結語
總體來說,rayMarch雲在實時渲染中處理仍屬於費力不討好的地位(不知道在光追顯卡下會不會好些)。在特殊需求下可以提升視效,如《Bioshock Infinite》這種穿梭雲層的東西。但成品裏基本都是非常hack和優化的操作(手繪面片...),估計沒有rayMarch。