2013-01-04 97 views
6

我正在研究iOS上的手寫應用程序。我從OpenGL ES實現的iOS文檔中找到了示例項目「GLPaint」,並對其進行了修改。如何使用OpenGL避免透明度重疊?

我跟蹤觸摸點並計算點之間的曲線,並單獨繪製粒子圖像的曲線,使其看起來像手指經過的位置。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData); // burshData is from CGImage, it is 

// vertexBuffer is generated based on the calculated points, it's just a sequence of point where need to draw image. 
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer); 
glDrawArrays(GL_POINTS, 0, vertexCount); 

glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
[context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

我得到的是一條實線,看起來相當不錯。但現在我想繪製半透明的高光而不是實線。所以我用50%的透明度替換了粒子圖像而不更改代碼。

Result of 50% transparency particle image

Result of 50% transparency particle image

也有一些是錯誤的交融。

What I need

What I need

我繪製使用半透明度顆粒圖像的三個點,並且交叉區域應保持50%的透明度。

解決方案是什麼?

+1

問題是你需要消除透支,這對於一般情況來說是不可能的,只是「混合」。您可以使用深度緩衝區(使用alpha測試),但不能正確反鋸齒。如果你希望這樣做能夠得到正確的反對意見,那麼正確的做法並不是微不足道的,至少在一般情況下是這樣。您需要首先渲染到額外的幀緩衝區,然後在第二遍渲染。 – Damon

+0

感謝您的回覆。我是OpenGL的新手,但我仍然不清楚OpenGL中的大多數概念。我認爲antialias不是問題。您能否詳細說明代碼? –

回答

6

林也許兩年後,在回答這個問題,但我希望它可以幫助別人誰到這裏來尋找解決這個問題,就像發生在我身上。

您將需要爲每個cirle分配一個不同的z值。無論這種差異多麼大或小,無關緊要,我們只需要他們不會嚴格平等。

首先,您禁止在顏色緩衝區glColorMask(false,false,false,false)中寫入數據,然後正常繪製圓圈。 Z緩衝區將根據需要進行更新,但不會繪製圓。

然後,您啓用在顏色緩衝區(glColorMask(true,true,true,true))中寫入並將depthFunc設置爲LEQUAL(glDepthFunc(GL_LEQUAL))。只有最接近的圓像素才能通過深度測試(將其設置爲LEQUAL而不是EQUAL處理,但有一些罕見但可能的浮點逼近錯誤)。啓用混合並再次繪製它們會產生你想要的圖像,而不會有透明度重疊。

+0

真的非常感謝您的回答。還有一個問題。你是什​​麼意思「分配不同的z值」。這是座標或Z緩衝值的第三維?對不起,如果這個問題沒有意義,我是opengl的新手。 –

+0

兩者同時!在着色器內部,X和Y座標控制每個頂點(-1到1)的屏幕位置,Z座標控制深度(0到1,接近0)。 該深度是與Z緩衝區比較的深度 - 如果該像素中的Z緩衝區的值較小,則意味着已經有一個像素被拉近到相機,因此該片段將被丟棄。因此,如果每個圓都具有不同的Z座標,則每個像素只有一個片段不會被丟棄(距離相機最近),因此混合會成功。 – Ivelate

+0

您可能會感到困惑,因爲大部分時間我們都會使用變換矩陣在頂點着色器中應用座標變換。所以,對於一個頂點你有一個初始的X,Y,Z,並且它被變換到另一個位置來與攝影機或任何其他位置對齊,所以着色器使用的真實Z可能不是你頂點的原始Z.解釋你是否是OpenGL的新手有些複雜,所以我強烈建議你閱讀本教程(直到「Depth and stencil」部分),https://open.gl/,在我開始時它對我有很大的幫助。不要猶豫,如果你需要更多的問題! – Ivelate