2011-09-21 65 views
2

我正在渲染點精靈(在iOS上使用OpenGL ES 2.0)作爲用戶的繪畫筆觸。我將這些點存儲在頂點緩衝區對象中,以便我需要執行深度測試,以便在提交繪圖時讓精靈以正確的順序顯示。OpenGL點精靈與深度測試 - 一個混合問題?

呈現這些繪圖筆畫,當我看到一個奇怪的效果,如通過下面的截圖:

Point Sprite Blending Issue

注意背景色的「邊界」周圍藍色的行程,那裏的邊緣它被畫在綠地上。用戶在綠色描邊之後繪製藍色筆劃,但是當VBO重新繪製時,藍色筆劃首先被繪製。當談到繪製綠色中風時,深度測試開始,並且看到它應該落後於藍色中風,這樣做也是如此,一些成功。在我看來,這是一種混合問題,或者是不正確地計算片段着色器中的顏色?所有筆畫的邊緣應該是透明的,但是看起來片段着色器在處理這些片段時將其與背景紋理結合起來。

在我的應用程序中,我創建了一個深度渲染緩衝區,並使用glDepthFunc(GL_LEQUAL)調用glEnable(GL_DEPTH_TEST)。我試用glDepthMask()無濟於事。混合設置爲glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA),點精靈顏色使用預乘alpha值。繪圖程序非常簡單:

  • 綁定渲染到紋理的FBO。
  • 繪製背景紋理。
  • 畫點精靈(來自多個維也納國際中心)。
  • 將此FBO的紋理繪製到主幀緩衝區。
  • 呈現主要幀緩衝區。


編輯

下面是從繪製例程一些代碼。

設置狀態拉伸之前:

glDisable(GL_DITHER); 
glEnable(GL_BLEND); 
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 
glEnable(GL_DEPTH_TEST); 
glDepthFunc(GL_LEQUAL); 

繪製函數:

[drawingView setFramebuffer:drawingView.scratchFramebuffer andClear:YES]; 
glUseProgram(programs[PROGRAM_TEXTURE]); 
[self drawTexture:[self textureForBackgroundType:self.backgroundType]]; 

glUseProgram(programs[PROGRAM_POINT_SPRITE]); 

// ... 
// Draw all VBOs containing point sprite data 
// ... 

[drawingView setFramebuffer:drawingView.defaultFramebuffer andClear:YES]; 
glUseProgram(programs[PROGRAM_TEXTURE]); 
[self drawTexture:drawingView.scratchTexture]; 

[drawingView presentFramebuffer:drawingView.defaultFramebuffer]; 

感謝您的幫助。

回答

4

如果要繪製不透明的幾何圖形,則必須從後向前對它們進行z分類。這是多年來獲得適當混合的唯一途徑。現在有一些像雙深度剝離這樣的順序無關透明度的算法,但它們不適用於iOS。

+0

嘎,這就是我希望看不到的答案!儘管感謝您的回覆。由於筆畫使用不同的紋理(如屏幕截圖所示),Z-sort我的精靈可能會有點棘手。我想盡量減少維也納國際組織的數量,但是我會看到我能夠管理的事情,因爲他們需要保持正確的順序。 – Stuart

+0

我想象不同的筆畫在不同的VBO中。你所要做的就是排序VBO而不是點精靈......除非你想再次用綠色繪製,並將第一筆和第三筆結合起來,因爲它們要使用相同的紋理。這看起來像是大量的粒子。我不確定要做的最好的事情是每一幀畫出它們。如果您製作繪圖類型的應用程序,則應考慮繪製渲染目標中的舊圖層,並將最新的圖層繪製在最上面。然後,如果您已撤消操作類型,則必須從第一層重新繪製它們。 – Aleks

+0

是的,它們存儲在VBOs中,問題就像你描述的那樣 - 如果我將一個特定紋理的所有筆劃存儲在一個VBO中,然後繪製不同的紋理,當我畫出所有的VBO時,它們將失序。我已經修正了這個部分,並且每次用戶更改筆觸紋理時創建一個新的VBO,否則我會盡可能多地填充點。我不是每一幀都繪製VBOs--我使用渲染到紋理的方式進行繪製,這很容易達到60fps。我需要維也納各組織支持橡皮擦和撤銷/重做行動。 – Stuart