這篇文章是這個系列最後一篇啦,前情回顧:

有了動態的天空,動態的水面反射,距離心中想的比賽作品還差最後一個最大的挑戰,那就是可以互動的實時焦散。UE4 連水都沒有,更別提焦散,所以這部分內容完全得靠自己。

在組裡其他小夥伴的幫忙下,在比賽距離比賽截止還剩不到4天的時間,完成了效果原型。因為涉及到一些專案內部的資訊,所以目前這篇文章只對我認為可以放出的內容,稍微點一下。據說NV 有意要把焦散的實現給UE4,那到時候再給大家做具體的分析。

當然,NV 也在18年GDC 上給出了焦散相關的資訊,有興趣的小夥伴可以到這裡檢視:

這篇文章,我將分享下面的內容

遊戲裡面最常用的

焦散

場景?

實時可互動

的焦散是什麼樣的?

水面焦散的

原理

【水面上下,水的反射折射】。

遊戲裡面常規的焦散如何做,如何使用

RayTracing

實現焦散【只分享過程部分截圖,不會涉及具體程式碼】。

廢話不多說,這就開始。

1、什麼是焦散?

【魔改UE4】Rtx實時焦散的一次嘗試

【魔改UE4】Rtx實時焦散的一次嘗試

游泳池裡面的焦散效果最常見了,這些跟著水面一起晃動的亮斑,其實就是這裡所謂的“焦散”,它們會出現在水底,也會出現在水上,岸邊天花板都有。

遊戲裡面,

傳統的焦散

,一般是透過某些專業軟體,匯出一個焦散序列,然後透過uv動畫來製作的。

優點:效率快,效果可以控制。

缺點:無法互動。

NV 在推他的RayTracing就一直提到 焦散,那麼這個實時的焦散張啥樣?

其實遠的不說,就拿國產遊戲Rtx來說,《逆水寒》、《劍網三》都曾指出自己實現了rtx 焦散。因為劍三已經正式交付到玩家手裡,我以《劍網三》為例說明。

【魔改UE4】Rtx實時焦散的一次嘗試

jx3_caustic_realtime。wmv

https://www。zhihu。com/video/1191764443942563840

以上畫面是從劍網三正式服蓬萊場景擷取的,可以看出,當你在水裡跑動的時候,焦散會跟著一起動。這便回答了上述的問題啦。

2、焦散原理

關於焦散的原理的準確闡述,大家可以看上面NV 的Gdc 影片,也可以查一下。我這裡說一下我們遊戲裡面,要實現的水面這個焦散的大致情況。

其實說的通俗簡單一點,對於水面,我們並不是是為了焦散而去做焦散,真正要做的是,模擬光線從空氣進入水面後發生的一些事情。

【魔改UE4】Rtx實時焦散的一次嘗試

由上面那張圖可以看到,光線打到水面上的一個點,會根據水面的發現發生反射和折射。當一束平行光線過來,因為水面並不平,反射以後的光線並不是平行的,會朝著各個方向繼續傳播,當他們碰到下一個平面,很多光子聚集到一起,就形成了一系列的“亮點”,遠距離看起來,這些亮點看上去,有了形狀,就是我們所說的由於反射,而產生的水面上面的焦散了。折射產生的水下焦散也是這個道理。

反射形成的焦散會打到水面的上方。

折射形成的焦散會達到水面的下方。

3、焦散的實現

我們知道,在RTX 的框架下,處理這種已知位置和方向的射線求交是非常方便的。其實焦散的實現非常方便,實際程式碼和反射非常相似。只不過,反射是一個畫素被動的去計算一個畫素被反射到的顏色,而焦散則是主動發出射線去照亮場景。

簡而言之,一共有下面三個步驟:

【光柵化】繪製水面,得到水面位置和法線資訊。

【RayTracing】做射線求交,得到求交結果。

【光柵化,可選】根據實際情況,選擇是否繪製Caustic 網格。

值得注意的有兩點:

焦散 實際是透過RayTracing 和 光柵化共同完成的結果。

第三步是可選的,當發出的射線不夠多時,點亮場景的點非常散,沒辦法聚成一定的形狀。這個時候就需要透過降噪的手段來處理這些噪點了。當然,如果只是一個為了一個製作一個效果原型,不扣細節,我們可以選擇要不加多射線,也有一個很討巧的辦法,把這些點實時匯出,拼成三角形,CS計算三角形的面積,決定三角形的亮度,最後在PS 裡面三角形畫出來即可。

此外,要想實現一個非常漂亮的焦散效果,對水面的法線要求很高。最終焦散的效果是來自水面法線的,這也是美術控制焦散最主要的方式。

綜上所述,焦散的具體實現步驟:

【光柵化】 正交繪製水面,RT 為水面的世界座標和法線。

【RayTracing,GenRay】根據螢幕上一個畫素水面的法線,和光線的方向,計算反射、折射方向。

【RayTracing,DispatchRay】沿著這兩個方向,主動像場景發射射線。

【RayTracing,HitGroup】當碰到場景時,計算這一點在螢幕上的座標,把SceneColor 上對應的點 點亮,降噪,使場景顏色平滑乾淨。

【RayTracing,HitGroup】必要時,不做第4步,直接匯出碰到的世界座標點,和其他關心的資訊。

【CS】拼接三角形,根據三角形面積,計算三角形亮度強度。

【光柵化】GS 剔除不符合的三角形,PS 繪製三角形,完成焦散。

下面做一個簡單的概述,以及我部分完成的情況,供有興趣的小夥伴參考:

3。1 正交繪製水面,得到水面世界座標,和法線的資訊

這一步在最開始的時候,我是新建了兩個和螢幕一樣大小的RT,從主相機的角度透視拍水面的。這麼做確實很方便,不用管理相機,但是它的問題是,首先會浪費很多畫素,其次精度不夠,會出現摩爾紋以及各種莫名其妙的問題。

最終決定使用正交相機。

如果是使用正交相機,在水面正上方,垂直向下拍,那麼得到的世界座標,及法線精度是足夠的了。

為了方便演示,我僅僅使用一張法線貼圖,和一個平面來表示水面,機器波動。

【魔改UE4】Rtx實時焦散的一次嘗試

如圖所示,圖裡是個非常簡單的場景,只有一塊兒水面,2張rt,解析度是512*512,分別記錄了水面的世界座標,和壓縮過的法線。

3。2 RayTracing,點亮場景

一開始,因為reproject 到螢幕上 計算錯誤,出了下面的一些問題,沒辦法打到正確的場景物件上,立起來了:

【魔改UE4】Rtx實時焦散的一次嘗試

【魔改UE4】Rtx實時焦散的一次嘗試

https://www。zhihu。com/video/1191774046361186304

後來改正reproject 以後,得到了和想象中非常接近的效果

【魔改UE4】Rtx實時焦散的一次嘗試

好是好,但是正如上文提到的,這麼做存在精度問題。

UE4的原現場有點久遠了,我用一個獨立的小demo 演示一下它的問題。

【魔改UE4】Rtx實時焦散的一次嘗試

https://www。zhihu。com/video/1191775655585521664

好了,最後在同事幫忙下,開始轉正交做。有了如下結果。

在RayTracing 這一步,我一開始是直接一個點一個點打亮場景的,結果發現發出的射線不夠多,出來很多小點點:

【魔改UE4】Rtx實時焦散的一次嘗試

【魔改UE4】Rtx實時焦散的一次嘗試

3。3 失敗的降噪

降噪這部分,我只知到可以透過每幀隨機數 + taa 的方式 來做時間上的降噪。對空間降噪演算法不是很瞭解。

一開始試圖透過降噪來處理這些點,並沒有得到非常好的結果。眼看比賽截止時間臨近,最後在同事的講解下,開始考慮第二種方法,點雲拼接三角形。

3。4 點陣 拼接三角形,回頭走光柵化流程

在上面的rtx 步驟中,實際上並沒有對SceneColor 做任何操作,而是輸出了 世界座標和一些其他引數的Buffer。

世界座標buffer 直接作為VertextBuffer,走光柵化流程~

【魔改UE4】Rtx實時焦散的一次嘗試

上圖展示了大致的結果,已經非常非常接近最終結果了。

接下來,就是把根據亮度篩選三角形,透過一個CS,計算三角形面積,得出三角形的亮度強度,再走GS ,剔除不符合要求的三角形,最終就能得到下面的結果啦~

【魔改UE4】Rtx實時焦散的一次嘗試

【魔改UE4】Rtx實時焦散的一次嘗試

標題圖get~

ok,基本到了這一步,整個焦散的實現過程就算完成了,當然中間有很多可以新增引數,給美術控制的地方,我這裡就不方便說太多了~

好的,焦散部分就說到這裡了,這個系列的三篇文章也按照預期更新完了。小夥伴們,有緣再見~