小程序[渲染层网络层错误] failed to load image_游戏中水的渲染技术
水的渲染一直是圖形學(xué)需要解決的問題,本篇博客主要介紹用傅里葉變換算法實(shí)現(xiàn)的水反射,也是一種假反射效果,目的是優(yōu)化效率。實(shí)現(xiàn)的效果如下圖所示:
使用傅里葉系數(shù)來表示地形高度的假反射效果,在我們開發(fā)的游戲中使用水著色器,告訴讀者我將如何利用引擎處理水的反射,我們自己開發(fā)水渲染效果,需要在優(yōu)化方面考慮,計(jì)算每幀渲染時(shí)間。我們要處理渲染簡(jiǎn)化的低分辨率反射地圖,因?yàn)槲覀冞€要渲染對(duì)于流動(dòng)的水平面。算法的實(shí)現(xiàn)其實(shí)都是源于生活,大家如果平時(shí)出去旅游,經(jīng)常會(huì)看到山丘的反射,近處反射的比較清晰,但在遠(yuǎn)處它只是一個(gè)黑色的斑點(diǎn)。試想一下,如果我們能夠記錄每個(gè)水點(diǎn)周圍的水面上方的地形的角度,然后我可以在水著色器中使用這個(gè)反射光線,它應(yīng)該是從“天空”過渡到“地形”的點(diǎn)。(Spherical harmonics)球面諧波是一種眾所周知的技術(shù),通常用于全局照明。非常簡(jiǎn)要地總結(jié):每個(gè)頂點(diǎn)存儲(chǔ)一組預(yù)先計(jì)算的系數(shù),這允許我們重建擊中對(duì)象的環(huán)境光。這些系數(shù)基本上存儲(chǔ)從每個(gè)方向照射該點(diǎn)的光的映射圖。反射/環(huán)境光通常是非常低的頻率,因此這是這些系數(shù)如何包含這么“多”的信息原因。我決定用我引擎中的水嘗試類似的技術(shù),每個(gè)頂點(diǎn)保存一組小系數(shù),描述地形在水上方圍繞該點(diǎn)的每個(gè)方向上升的角度。這可以用一個(gè)四元系列的系數(shù)來描述 - 基本上是球面諧波的2d方程。當(dāng)在頂點(diǎn)之間插值時(shí),這些傅里葉系數(shù)就可以計(jì)算出來了,給讀者展示一下效果圖吧。在水上的一個(gè)點(diǎn)周圍的采樣方向上的各種角度。
我們計(jì)算每個(gè)水頂點(diǎn)的系數(shù),這涉及每個(gè)頂點(diǎn)的操作:
1、在點(diǎn)周圍選擇 ?k個(gè)均勻間隔的采樣方向。k的值只影響計(jì)算,因此您可以將其設(shè)置為一定
的高以實(shí)現(xiàn)其仿真度,我目前使用13。
2、對(duì)于每個(gè)采樣方向,執(zhí)行光線跟蹤。一次執(zhí)行一個(gè)高度地圖像素,測(cè)量水面上方的地形角度。你想要精確的反射取決于你離岸的距離,在本文的示例應(yīng)用程序中,我目前使用5個(gè)像素。如果你的游戲涉及從低水平面的不同的水觀察視角,你將需要使用更多(后面更多)。
3、現(xiàn)在我們有一個(gè)函數(shù)(每2π循環(huán))表示點(diǎn)周圍的地形高度。
4、為了獲得表示該函數(shù)的傅里葉系數(shù),我們需要對(duì)每個(gè)系數(shù)的表達(dá)式進(jìn)行積分計(jì)算,確切的表達(dá)式可以在網(wǎng)上找到。我使用數(shù)值積分,分辨率為400(例如每個(gè)函數(shù)400個(gè)樣本),使用的數(shù)字僅影響計(jì)算。
?5、我計(jì)算前8個(gè)系數(shù),這個(gè)數(shù)字直接影響效果的品質(zhì)和性能。8對(duì)我的目的來說肯定夠好了,當(dāng)然我們會(huì)盡量降低。
我把我的系數(shù)作為16位浮點(diǎn)存儲(chǔ)在我的頂點(diǎn)結(jié)構(gòu)中(因此每個(gè)頂點(diǎn)占用16個(gè)字節(jié))。
在水著色器中,我使用反射向量來確定我設(shè)置的角度,代碼如下:
float3 reflectionRay = reflect(worldPosition - CameraPosition, normal);float angle = atan2(-reflectionRay.z, -reflectionRay.x) + PI;//這給出了0和2π之間的角度,然后我們能夠使用它來查找地形高度。本文實(shí)現(xiàn)的傅里葉評(píng)估函數(shù)看起來像這樣(t是角度):
float EvaluateFourier(float t, float4 coefs1, float4 coefs2){ float4 sins; float4 coses; sincos(float4(t, 2 * t, 3 * t, 4 * t), sins, coses); float value = coefs1.r; // a0 value += coefs1.g * coses.r; // a1 value += coefs1.b * sins.r; // b1 value += coefs1.a * coses.g; // a2 value += coefs2.r * sins.g; // b2 value += coefs2.g * coses.b; // a3 value += coefs2.b * sins.b; // b3 value += coefs2.a * coses.a; // a4 return value;}方程給了我一個(gè)角度,這也是算法與編程結(jié)合的函數(shù)實(shí)現(xiàn),然后我可以比較水面上的反射光線的角度,以確認(rèn)我們是否應(yīng)該繪制天空或反射的地形,目前我只是使用黑色的反射地形,效果似乎滿足需求。如果我們想要更好的效果,還可以存儲(chǔ)地形的顏色,除了高度。當(dāng)然這將使所需的數(shù)據(jù)量增加四倍。
那它是如何工作的呢?您可以查看本文頂部的照片作為示例。這里有一個(gè)版本的頂點(diǎn)網(wǎng)格繪制。每個(gè)頂點(diǎn)存儲(chǔ)16字節(jié)的數(shù)據(jù)在我當(dāng)前的實(shí)現(xiàn)。上圖顯示了我使用的頂點(diǎn)分辨率效果。
在水面上使用的法線貼圖有助于實(shí)現(xiàn)這種假反射效果,實(shí)現(xiàn)的效果如下所示:
以上實(shí)現(xiàn)的效果在性能方面也給讀者分析一下,這也有助于讀者優(yōu)化Shader的渲染效果:上面給讀者實(shí)現(xiàn)了一種假反射,以避免渲染昂貴的反射貼圖,因此它需要具有高性能。不幸的是,這需要大量的著色器指令在我當(dāng)前的實(shí)現(xiàn)中評(píng)估。atan2約有20條指令。HLSL產(chǎn)生4個(gè)標(biāo)量sincos指令,其實(shí)際上每個(gè)占用8個(gè)指令槽??偣?#xff0c;它為像素著色器添加了約64個(gè)指令槽。針對(duì)上述問題,我們的下一步任務(wù)是找到一種減少指令數(shù)量的方法。可以使用atan,然后是正弦和余弦,我可以通過做一些三角取代來減少這一點(diǎn)?;蛘呶铱梢钥紤]使用e與虛數(shù)的冪的和來評(píng)估該系列。當(dāng)然我們還可以減少系數(shù)的數(shù)量。另外,我將看到我是否可以存儲(chǔ)每個(gè)系數(shù)在單個(gè)字節(jié)而不是16位浮點(diǎn)。最后總結(jié)一下,對(duì)于具有更多不同視圖的游戲,這可能不是一個(gè)很好的選擇。還有這個(gè)技術(shù)的一個(gè)問題是它只反射靜態(tài)對(duì)象,地形,以及你決定在你的射線檢測(cè)算法中包含的任何其他游戲元素。總結(jié)
以上是生活随笔為你收集整理的小程序[渲染层网络层错误] failed to load image_游戏中水的渲染技术的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle行列互换sql,解决Orac
- 下一篇: Nacos配置文件覆盖问题