在OpenGL中隐藏片段

时间:2016-01-25 19:29:53

标签: android opengl-es blending depth-buffer

我在Android中使用OpenGL-ES 3.0。

为了简化我的问题,我将描述一个与我非常相似的场景。让我们说我有一个以原点为中心的球体。我们还说我有另一个以原点为中心的球体,半径更大。最后,让我们说我有一个圆柱体,圆柱顶面的中心位于原点上。圆柱体与两个球体相交。该场景的图片如下:

这是我的初始设置: Initial Setup

我想只绘制两个球体之间的部分,如下所示: Section in Between

然而,在我的应用中,两个球体中较小的一个是不可见的(虽然它存在)。它完全透明。因此,我希望最终的最终产品看起来像这样:

enter image description here

现在,还有一条信息:正如我之前提到的,这是我当前场景的简化。我有更复杂的对象(不是简单的原始形状),而不是球体。因此,从数学角度(例如,仅绘制圆柱体的大于小球体半径并且小于较大球体半径的部分)接近这一点是不可行的。我需要从编程的角度以某种方式处理这个问题(但鉴于我对OpenGL的了解有限,我只能将深度测试和混合视为可行的选项)

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分:0)

你所描述的是Constructive Solid Geometry,但是使用网格作为基本类型之一的复杂性增加了。

仅使用数学上简单的原语的事件,很难在OpenGL管道中纯粹实现CSG,因为您需要找到一种方式来以着色器可以理解和有效解析的方式表示场景图。一旦添加了网格,它基本上是不可能的,因为顶点和片段着色器将无法轻松访问网格几何体。

您可以通过对CGS图形中的每个项目执行绘制调用以及模板和深度缓冲区的巧妙操作来近似它,但您可能仍然会遇到许多无法正确渲染的边缘情况。