項目地址
本文基於兩篇文章來實現
渲染就是一個根據場景描述生成 2D 或 3D 畫面的過程
真實感渲染中,渲染軟體通常要求解渲染方程
對於光照,我們可以將其劃分成直接光照和間接光照兩部分
直接光照易於求解,但間接光照就比較難,比如反射、折射等。
所以根據實際需求,渲染的演算法分成兩大類
離線渲染傾向於實現各種各樣真實的效果,對時間不敏感
實時渲染要求計算快速,需要放棄很多精度,但也不斷地朝著真實感的方向努力
本文研究的是基於學習的實時透明材質渲染
這點內容可以參考我之前的文章
雙向散射分布函數可以用於描述透明材質
效果如下
考慮一個靜態場景,裡邊只有一個點光源,場景中的所有物體都是非透明的
那麼要渲染這個場景,就要求解反射方程
出射光可分為直接光照和間接光照,直接光照可以用渲染管線快速求解,而間接光照就比較困難,需要解一個複雜的積分。
我們求一個擬合函數——輻射度回歸函數,根據一些輸入(位置,視線方向,光源位置,法向,材質屬性)來得到間接光照。
前邊說到,輻射度回歸函數只能渲染非透明物體,而我們想用其渲染透明物體
那我們可以對其簡單擴展一下,將其中的 BRDF 改為 BSDF,此外為了簡化問題,我固定了光源位置。
本文所用的渲染器是我們構建的
支持實時渲染,離線渲染和場景編輯的功能。
我們用輻射度回歸函數來擬合間接光照,注意,這個函數是用於一個像素的,一個畫面里會有幾十萬到幾千萬個像素,也就是說,該函數每幀要計算很多次
因此,為了快速計算,我們只能使用呆萌的小神經網路,這裡明確一下我們所使用的網路模型
訓練神經網路需要數據,我們可以用渲染軟體生成大量的標註數據,採樣流程如下
一個如此萌的小網路,它沒法處理一個複雜場景
解決這個問題的方法:為每個物體訓練一個神經網路 KD-Tree
KD-Tree 適合於遞歸的劃分高維空間,即輸入向量空間。通過遞歸劃分,每個呆萌小網路只需要處理自己的小空間,學習壓力輕鬆了很多,表現就好了。
在實時渲染時,只需要根據輸入向量去搜索 KD-Tree,找到對應的神經網路,接著塞給它輸入向量,它就會給我們間接光照。
大家對於神經網路的訓練可能比較熟悉,但是,現在是神經網路 KD-Tree,訓練過程就不太一樣。關鍵是在於什麼時候劃分結點,什麼時候停止劃分。流程如下:
因為我們將問題分給了多個神經網路來解決,那麼在他們的邊界處,就會不連續
現象如下
視覺上非常明顯
我們可以通過遞歸插值的方法來解決這個問題
效果就好了很多
我對作者的流程進行了簡化:把KD-Tree搜索和神經網路的運算放進了 fragment shader 里
思路就是把 KD-Tree 和神經網路通過 codegen 的方式硬編碼寫到 shaders 中
? CPU: Intel(R) Core(TM) i5-8400 CPU @ 2.80 GHz 六核
? GPU: NVIDIA GeForce GTX 1050Ti 4G,驅動版本為 418.91
? 內存: 16 GB DDR4 2400MHz
? 圖形介面: Qt 5.12 框架上的 OpenGL 3.3
這裡我用了一個簡單的常量來測試
5個點光源,4前1後
中間為玻璃
六個物體(5牆1玻璃)對應六棵樹
左:直接光照
中:間接光照
右:全局光照
對於 512*512 的畫面,幀率達到 65 fps
感謝大家的閱讀
推薦閱讀: