Raymaching其實就是實時場景的一種渲染方法。主要原理網上有很多詳細介紹。簡單來說就是,以錄影機為原點,發射很多條射線,而每一條射線以步長為機關向前采樣,同時以采樣點和最近的物體像素的距離為半徑進行一個球形檢測。檢測到錄影機和場景像素在目前射線方向的距離差小于某個值,就表示射線到達物體表面,然後畫這個像素。
開始在unreal裡面進行簡單的實作
首先上才藝
圖檔僅供參考,具體以實物為準
1、custom節點算出球體
先上代碼
float distance = length(pos-ObjectPosition)-50;
減去50表示小球的半徑
2、去掉被遮擋的部分
為了對算法進行優化,我們可以去掉球體被遮擋的部分,比如說地面以下的部分。
判斷場景深度是否小于錄影機到物體像素的距離,小球處于地面以下後,深度值就會取平面的深度值,是以如果深度值小于錄影機到像素距離的話,不進行檢測。
3、添加法線
求法線就簡單粗暴的對檢測結果求一個梯度變化,設定一個值,求在這個值前後的檢測結果的插值。最後把normal的資訊也輸出出來。具體結果如下
注意材質球的normal要取消勾選targent space normal,因為算出來的是一個世界法線
4、跟地面的融合效果
參考文檔https://iquilezles.org/articles/distfunctions/,裡面有很多算形狀等基本運算的公式代碼,以及詳細推導
關于這個公式的詳細算法推導連結如下
https://iquilezles.org/articles/smin/
主要就是一個分段函數,d1是檢測出來的小球,d2是與其相交的一個物體的距離場,k表示兩個相交的物體在相交那部分的一個過渡值,即達到這個值開始相交。
是以d1 = RM.RMSphere(pos-ObjectPosition);
而d2,這裡用深度代替距離場,就等于射線方向上那個物體對應的場景深度減去錄影機到小球像素的距離
float d2 = SceneDepth - length(pos - CameraPosition);
這裡混合d1和d2用lerp。
最終效果
調整采樣步數等可以解決邊緣鋸齒,但是性能計算會更大,目前還沒有找到一個更好的解決辦法。