2016-01-25 73 views
0

我在Android中使用OpenGL-ES 3.0。在OpenGL中隱藏片段

爲了簡化我的問題,我將描述一個非常類似於我的場景。假設我有一個以原點爲中心的球體。我們還要說,我有另一個以原點爲中心的球體,半徑較大。最後,假設我有一個圓柱體,並且圓柱體頂面的中心位於原點上。圓柱體與兩個球體相交。場景的圖片下面:

這是我的初始設置: Initial Setup

我想只繪製了部分在這兩個領域之間,如下圖所示: Section in Between

然而,在我的應用程序中,兩個球體中較小的一個不可見(儘管它存在)。它是完全透明的。因此,最終的成品,我想會是這個樣子:現在

enter image description here

,多了一個資料片:正如我前面提到的,這是我目前的情況下的簡化。而不是球體,我有更復雜的對象(不是簡單的原始形狀)。因此,從數學的角度來看(比如只畫出大於小球體半徑且小於大球體半徑的圓柱體部分)是不可行的。我需要從編程的角度以某種方式來解決這個問題(但由於我對OpenGL知識有限,我只能將深度測試和混合看作可行的選項)

回答

1

您可以使用模板緩衝區來做到這一點。

我還沒有編譯的代碼,它會需要修改,但是這是總體思路:

glDisable(GL_STENCIL_TEST); 

<Render rest of scene (everything other than the spheres and cylinder)> 

// Render the larger sphere into the stencil buffer, setting stencil bits to 1 

glEnable(GL_STENCIL_TEST); 
glClear(GL_STENCIL_BUFFER_BIT); 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Don't render into the color buffer 
glDepthMask(GL_FALSE); // Don't render into the depth buffer 
glStencilMask(0xff); // Enable writing to stencil buffer 
glStencilFunc(GL_ALWAYS, 1, 0xff); // Write 1s into stencil buffer 
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // Overwrite for every fragment that passes depth test (and stencil <- GL_ALWAYS) 

<Render big sphere> 

// Render the smaller sphere into the stencil buffer, setting stencil bits to 0 (it carves out the big sphere) 

glStencilFunc(GL_ALWAYS, 0, 0xff); // Write 0s into stencil buffer 

<Render small sphere> 

// Render the cylinder into the color buffer, only where the stencil bits are 1 

glStencilMask(0); // Don't need to write to stencil buffer 
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Render into the color buffer 
glStencilFunc(GL_EQUAL, 1, 0xff); // Only render where there are 1s in the stencil buffer 

<Render cylinder> 

glDisable(GL_STENCIL_TEST); 

// Now render the translucent big sphere using alpha blending 

<Render big sphere> 
+0

我有一個問題:我認爲有些事情稍微偏離與您建議的代碼。讓我解釋一下我對代碼的理解,並讓我知道這是否是一種不正確的理解: – brohan322

+0

因此,您首先清除緩衝區並在任何地方寫入1。然後覆蓋通過深度測試的地方並替換這些值(順便說一句,用什麼替代?)。然後你爲第二個球體寫0。然後在任何有1秒的地方,圓柱體被拉出,對嗎? – brohan322

+0

我將您的代碼從GL_REPLACE更改爲GL_ZERO。這不是更有意義嗎?如果深度測試通過(在我的情況下,如果一個片段通過深度測試,它將位於大球體之外),並且模板測試通過(它總是這樣做),我不應該使這些值0在緩衝區中? – brohan322

0

你所描述的是Constructive Solid Geometry,但是增加了使用網格作爲原始類型之一。

只有數學上簡單的基元的事件很難在純OpenGL管線中實現CSG,因爲您需要找到一種方法來表示着色器可以理解和有效分析的場景圖形。一旦添加了網格物體,這基本上是不可能的,因爲頂點和片段着色器不容易訪問網格幾何體。

您可以通過對CGS圖形中的每個項目執行繪圖調用並對模板和深度緩衝區進行巧妙操作來逼近它,但是您可能仍然會遇到很多無法正確呈現的邊緣案例。