2012-03-23 98 views
0

如何讓我自己的z緩衝區正確混合alpha通道?我正在使用glsl。 我只有一個想法。這是使用2「緩衝區」,其中一個存儲深度組件和另一種顏色(與alpha通道)。我不需要訪問我的程序中的緩衝區。我不能使用統一數組,因爲glsl對統一變量的數量有限制。我不能使用FBO,因爲有時寫入和讀取Frame Buffer的行爲沒有定義(並且不在任何卡上工作)。我自己的z緩衝區

我該如何解決這個問題?

或者如何從glsl讀取實際的實時z-buffer? (我的意思是每個片段着色器調用z-buffer必須更新)

+3

「正確混合alpha通道」是什麼意思?你想解決什麼問題?你是否想要做一些與訂單無關的事情? – 2012-03-23 20:27:11

+1

除了Nicol Bolas所說的內容:對於與訂單無關的透明度,一些額外的深度緩衝區是不夠的。什麼可以分層分解場景,這就是所謂的深度剝離。但是,這不是微不足道的。 – datenwolf 2012-03-23 20:36:20

+0

@NicolBolas,是的。如果我可以從glsl讀取Z-Buffer,那麼我有一個簡單的方法來做到這一點! – 2012-03-24 07:27:17

回答

2

如果它是與順序無關的透明膠片,那麼基本問題是深度緩衝區存儲每個像素的深度,但如果您正在編寫部分透明幾何的視圖,那麼不止一個片段對每個像素都有貢獻。

如果您要穩健地解決問題,則需要每個像素有序的深度列表,然後回到最近的不透明片段。然後你會按照相反的順序走這個列表。在實踐中,OpenGL不會像可變大小的數組那樣做事情,所以人們通過按照先後順序繪製它們的幾何圖形來達到非常好的效果。

GL_SAMPLE_ALPHA_TO_COVERAGE的一個替代方案是切換到屏幕門透明度,無論是以非常高的分辨率還是採用多重採樣,都無法區分真正的透明度。理想情況下,你會這樣做,但這會使OpenGL重複性規則失效。儘管如此,因爲你在GLSL,你可以自己做。您的採樣器只需輸入alpha,並將其用作輸出最終像素的概率。因此,從某個地方抓住一個範圍在0.0到1.0之間的隨機值,如果它大於alpha,則丟棄該像素。始終以1.0的alpha值輸出,並使用正常的深度緩衝區。 Answers like this對你可以做些什麼來獲得GLSL中的隨機數字有了更多的瞭解,顯然你想盡可能多地進行多重採樣。

Eric Enderton寫了a decent paper(其中有slide version)關於隨機順序無關的透明度,並附帶一個值得檢查的DirectX實現。

2

如何讓我自己的z緩衝區正確混合alpha通道?

這是不可能的。對於完美的與順序無關的透明度,您必須擺脫z緩衝區並將其替換爲隱藏表面移除的另一種機制。

使用z緩衝區有兩種可能的方法來解決這個問題。

  1. 多層z緩衝區(硬件加速不切實際) - 基本上它會存儲幾層「深度」值,並將用它來混合透明表面。會佔用很多內存,並且會有最大數量的透明覆蓋表面,一旦超過極限,就會出現僞像。
  2. 深度去皮(谷歌它)。訂購獨立的透明度,但每個像素的「覆蓋」透明多邊形的最大數量是有限制的。實際上可以在硬件上實現。

兩種方法都會有一個限制(每個像素的重疊透明多邊形的最大數量),一旦超過極限,場景將不再正確渲染。這意味着整個事情都變得毫無用處。你可以做的(獲得完美的解決方案)是完全移除zbuffer,並製作一個圖形渲染管道,它將收集所有要渲染的多邊形,剪切它們,拆分它們(當兩個多邊形相交時),排序然後按照正確的順序在屏幕上繪製它們,以確保您獲得正確的結果。但是,這很難,而用硬件加速來完成則更困難。我認爲(我並不完全肯定它發生了)6年前的某些ATI GPU相關文檔提到,它們的某些卡可以通過啓用某種擴展來禁用Z-Buffer來渲染正確的場景。但是,他們沒有提到α混合的事情。自那以後,我還沒有聽說過這個功能。也許它沒有變得流行,並分享了TruForm的命運(被遺忘)。此外,這樣的渲染管道將無法在z緩衝區上實現某些功能