2017-01-31 60 views
0

想我需要呈現如下景象:每個對象後處理

  1. 兩個立方體,一個黃色,紅色彼此。
  2. 紅色立方體需要用紅光發光,黃色不會發光。
  3. 立方體圍繞共同的重心旋轉。
  4. 攝像機位於 這樣一種方式,當紅色發光立方體靠近攝像機時,它部分遮擋黃色立方體,當黃色立方體靠近攝像機時,它會部分遮擋紅色,發光一個。

如果不是輝光,場景渲染將變得微不足道。隨着光暈,我可以看到至少2種方式呈現它的:

WAY 1

  1. 渲染的黃色立方體到屏幕上。
  2. 計算紅色立方體最終在屏幕上的位置(容易,我們有頂點+模型視圖矩陣),因此將其渲染到足夠大的屏幕 FBO(留下發光的邊緣);請務必將深度保存爲紋理。
  3. 後處理FBO併發光。
  4. 現在很難的部分:將FBO與屏幕合併。我們需要考慮深度(我們已經存儲在紋理中),所以看起來像我們需要做的 :

    a)渲染一個帶有FBO顏色附件的紋理。
    b)中建立模型視圖矩陣適當地( ,我們需要通過一些矢量,因爲我們有意 呈現的紅色立方體移動紋理比屏幕FBO較小,在步驟2(用於 速度的原因!))
    c)中在「合併」片段着色器,我們需要寫 的gl_FragDepth從FBO的深度附着質地(而不是從 FragCoord.z)

WAY2

  1. 渲染兩個立方體到屏幕外FBO;設置模板,使紅色立方體的無障礙部分標記爲1。
  2. 後處理的FBO使帶標記的區域變得模糊和混合這使發光
  3. BLIT的FBO屏幕

WAY 1級的作品,但主要的問題是速度即步驟4c。在片段着色器中寫入gl_FragDepth將禁用早期的z-測試。

方式2也是一種工作,看起來應該快得多,但它不會給出100%正確的結果。 問題是當紅色立方體被黃色部分阻擋時,紅色立方體靠近黃色的像素在我們模糊時會變得「泛黃」,即更接近的黃色立方體'發出'閃爍。

我想我可以解決上述問題,當我模糊時,當我讀取的像素突然減少深度(意味着我們剛剛從另一個物體跳到更近的物體)時停止模糊,但那會意思是模糊時紋理訪問次數的兩倍(除了獲取COLOR紋理,我們需要繼續獲取深度紋理)和模糊片段着色器中的條件語句。我還沒有嘗試,但我不相信它會比方法1更快,甚至也不會給出100%正確的結果(靠近與黃色立方體的邊界的紅色像素只會受到可見光的影響紅色立方體的一部分,而不是整個(-blurRadius,+ blurRadius)區域,所以在這個區域發光不會100%相同)。

有人會有建議如何最好地實現這種「每對象後處理」?

編輯:

什麼我寫信是一種OpenGL ES的庫圖形效果的。客戶可以給它一系列的指示,比如'採用這個Mesh,用它來紋理,將下面的矩陣變換應用到它的ModelView矩陣中,將下面的變形應用到它的頂點,下面的一組碎片效果,渲染到下面幀緩衝區'。在我的庫中,我已經有了我稱之爲「矩陣效果」(修改模型視圖)的'頂點效果'(各種頂點失真)和'片段效果'(RGBA各片段的各種變化)。 現在我正在嘗試添加所謂的「後期處理」效果,這是其中的第一個「發光」。我定義了這個效果,我對它的理解與上面描述的完全相同。

該效果適用於整個網格;因此現在我需要我稱之爲「每對象後處理」。

該庫主要針對'2.5D'的用途,例如移動應用程序中的GPU加速UI,2-2.5D遊戲(認爲糖果粉碎)等。我懷疑人們會真的將它用於任何真正的3D,大型遊戲。因此,FPS雖然總是很重要,但通常並不那麼重要。

我非常努力地保持API'Mesh-local',即渲染管道只知道它正在渲染的當前Mesh。主要的抱怨是它必須意識到我們要呈現給定的Framebuffer的整個集合。這就是說,如果'mesh-locality'是不可能的或者不能用後處理效果來高效完成的話,那麼我想我必須放棄它(並且讓我的教程變得更加複雜)。

昨天我在想這個問題:

# 'Almost-Mesh-local' algorithm for rendering N different Meshes, some of them glowing 

Create FBO, attach texture the size of the screen to COLOR0, another texture 1/4 the size of the screen to COLOR1. 
Enable DEPTH test, clear COLOR/DEPTH 

FOREACH(glowing Mesh) 
    { 
    use MRT to render it to COLOR0 and COLOR1 in one go 
    } 

Detach COLOR1, attach STENCIL texture 
Set up STENCIL so that the test always passes and writes 1s when Depth test passes 
Switch off DEPTH/COLOR writes 

FOREACH(glowing Mesh) 
    { 
    enlarge it by N% (amount of GLOW needs to be modifiable!) 
    render to STENCIL // i.e. mark the future 'glow' regions with 1s in stencil 
    } 

Set up STENCIL so that test always passes and writes 0 when Depth test passes 
Switch on DEPTH/COLOR writes 

FOREACH(not glowing Mesh) 
    { 
    render to COLOR0/STENCIL/DEPTH // now COLOR0 contains everything rendered, except for the GLOW. STENCIL marks the unobstructed glowing areas with 1s 
    } 

Blur the COLOR1 texture with BLUR radius 'N' 
Merge COLOR0 and COLOR1 to the screen in the following way: 

IF (STENCIL==0) take pixel from COLOR0 
ELSE    blend COLOR0 and COLOR1 
END 

這不是網狀本地(我們仍然需要能夠處理所有的「發光」網格第一),但我把它叫做「幾乎網本地」因爲它只根據應用於它們的效果來區分網格,而不是哪一個是哪個或哪個阻礙哪個網格。

它也可以有兩個發光的網格彼此阻礙(混合不必按正確的順序完成)的問題,雖然GLOW是半透明的,但我希望最終的樣子或多或少會好。

看起來它甚至可以做一個巨人變成一個完全「網格局部」算法

FOREACH(Mesh) 
    { 
    if(glowing) 
    { 

    } 
    else 
    { 

    } 
    } 

雖然在有附加和從FBO分離的東西,並在每一個不同的設置模板的成本循環迭代。

回答

0

下意識的建議是做混合:

  1. 計算其中紅色立方體最終會在屏幕上,所以它渲染到離屏FBO剛剛夠大(或一個同樣大小作爲屏幕,因爲在蹄上創建FBO可能效率不高);不要擔心深度,它只是你以後的顏色;
  2. 將兩個立方體渲染到屏幕外的FBO;設置模板,使紅色立方體的無障礙部分標記爲1;
  3. 後處理到屏幕通過使用由式(2)的任何地方模版是0,或通過採樣計算的模糊像素(1)的任何地方模版是1
+0

問題是,輝光的原始像素大於立方體(通過在每個方向上的blurRadius延伸)並且步驟3將切斷輝光中所有'超出立方體'部分。 即使我們反轉這個算法並用stencil = 1標記YELLOW立方體,並且在stencil = 0時使用FBO與(2)混合的模糊像素進行後處理,而當stencil = 1時使用plain(2)仍然在相反的情況下切斷部分輝光:紅色立方體部分阻礙了黃色的一個... – Leszek

+2

沒錯。並且再次向模板緩衝區應用擴展消除了適當的硬邊緣。你是否考慮過假冒僞劣幾何 - 繪製一個展開的立方體來標記發光的外部區域,用深度讀取但不寫入,以獲得銳利的邊緣? – Tommy

+0

是的,通過在某個點渲染一個展開的(在X和Y中,但不是Z)紅色立方體(用COLOR和DEPTH註銷)來標記發光區域應該工作......讓我想一想。 當然,「紅色和黃色立方體」只是一個理想化的例子,真正的要求是「渲染N不同,比立方體更復雜,有紋理的網格,其中一些發光」。這應該是以一種獨立於順序的方式完成的,即當我們渲染一個發光的Mesh時,我們最好不知道是否會有其他部分覆蓋它(或部分覆蓋它)。 – Leszek