在Deferred框架中輕鬆實現Decal

2022-05-17 16:34:15 字數 1677 閱讀 8909

現代3d遊戲經常會需要用到decal,子彈孔、腳印……傳統的decal渲染從quake 2時代開始就沒怎麼變過,通過畫乙個緊貼著物體的四邊形來實現。問題一直很多,比如光照的不一致,z-fighting造成的閃爍,渲染狀態的來回切換,等等。那麼到了deferred框架中,這種情況會有所好轉嗎?

有趣的是,deferred框架內實現decal不但非常容易:100行之內的**量,不到20分鐘就能完成,而且非常穩定,完全沒有上述各種缺點。更有趣的是,deferred的decal被至少三組不同的人都提出過完全相同的演算法,都在討論會出現的相同問題,只是被分別叫成了不同的名字。現在看看這三組:

既然這三種方法完全相同,我們其實只要討論一種即可,統稱為deferred decal。(順便吐槽一下第三個,screen space decals。作者不但是在看了前兩個後提出了個毫無新意的東西,並且起了個奇爛無比的名字——很顯然那東西不是screen space的。更噁心的是用了個ssd的縮寫,嫌縮寫混亂還不夠多嗎?他的ppt基本就是前兩篇的問題,只是換成自己的圖。遇到新問題直接就選擇了避開,或者胡搞乙個解法。)

deferred decal的基本思路就是,在g-buffer建立之後,把每乙個decal當作乙個立方體迭加到g-buffer上。對於g-buffer中被立方體覆蓋的畫素,用decal的color和normal來替換掉。在ps中,只要12

3456

78910

// 從eye座標系轉回decal立方體的座標系

float4 decal_pos = mul(float4(pos_es, 1), inv_mv);

// 忽略超過範圍的畫素

if (any(abs(decal_pos.xyz) > decal_pos.w))

// 計算畫素對應的decal紋理座標

decal_pos /= decal_pos.w;

texcoord = float2(decal_pos.x, -decal_pos.y) * 0.5f + 0.5f;

由於操作的物件是整個g-buffer,包括normal、diffuse、specular、shininess,所以這樣的decal可以修改掉其中任何乙個屬性,並且在光照階段不會增加任何開銷。這也是傳統的decal系統很難做到的。這裡我貼了乙個shininess很高的decal:

這種方法的最常見問題是,因為立方體的覆蓋面積遠遠大於decal,有時候會在不該貼的地方貼上了拉伸嚴重的。解決方法是把decal立方體的normal和g-buffer中的normal作比較,如果差別較大,就忽略掉。但因為寫入的目標是g-buffer,decal的ps就沒法讀取g-buffer。所以我的方法是在ps裡讀取相鄰點的depth,計算乙個screen space normal(就好像edge aa裡做的一樣),把它和decal立方體的normal比較。下面比較了沒加此處修正和加上後的區別:

修正前:

修正後:

另乙個常見問題就是視點進入decal立方體後,由於culling的關係,decal消失。解決方法是在那種情況下改成畫back face。

在deferred下實現decal就這麼簡單!

利用Exchange在Outlook中實現郵件提醒

通過exchange在outlook中實現郵件提醒,需要滿足如下幾個條件 1 於exchange server上建立郵件提醒賬戶 本案例採用projectreminder accado.com作為郵件提醒賬戶 操作步驟如下 登入exchange server管理控制台,然後在在 接受者管理 中新建郵...

syncbn在TensorFlow中的實現

在syncbn之前我們先簡單介紹一下bn層以及多卡機制 bn層介紹 bn層中有兩個可訓練引數 beta,gamma 以及兩個統計引數 moving mean,moving variance 訓練過程和測試過程,bn層計算方式是不同的。訓練過程,beta和gamma與卷積層中的weight是一樣參與訓...

SELCET TOP n在Oracle中的實現

聽說sql server和mysql中有top關鍵字,可以返回排序記錄的前n條記錄,如select top 10 from table name order by col name,我想oracle也必定有類似的功能,只是oracle沒有top關鍵字,而是使用rownum關鍵字。to retriev...