OpenGL模板(剪辑实体)

时间:2014-07-02 20:22:35

标签: java android opengl-es opengl-es-2.0 andengine

我正在尝试使用精灵作为剪辑实体。这意味着我想要剪切它的所有子实体,以便只有与剪辑实体(父级)重叠的子项部分可见。

我试图使用OpenGL模板功能来做到这一点。在我的模拟器上我得到了它,但在我的Android手机上它没有。我做错了什么?

GLES20.glEnable(GLES20.GL_STENCIL_TEST);
GLES20.glClearStencil(0);
GLES20.glStencilMask(1);

GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT);

// pre draw
GLES20.glStencilFunc(GLES20.GL_NEVER, 1, 1);
GLES20.glStencilOp(GLES20.GL_REPLACE, GLES20.GL_KEEP, GLES20.GL_KEEP);

// draw clip-entity (this) (sprite)
this.draw();

// post draw
GLES20.glStencilFunc(GLES20.GL_LESS, 2, 1);
GLES20.glStencilOp(GLES20.GL_KEEP, GLES20.GL_KEEP, GLES20.GL_KEEP);

// draw children of clip-entity (this) which should now be clipped
this.drawChildren();

GLES20.glDisable(GLES20.GL_STENCIL_TEST);

enter image description here

1 个答案:

答案 0 :(得分:2)

使用模板缓冲区来处理您所描述的内容听起来像是一种很好的方法。

您需要确保使用模板缓冲区请求帧缓冲配置。在Android上使用GLSurfaceView时,可以使用其中一个重载的setEGLConfigChooser()方法完成此操作。最简单的形式是红色,绿色,蓝色,Alpha,深度和模板的深度。如果你还需要一个深度缓冲区,你可以尝试这样的组合来获得带有模板的配置:

setEGLConfigChooser(8, 8, 8, 8, 24, 8);
setEGLConfigChooser(8, 8, 8, 8, 16, 8);
setEGLConfigChooser(8, 8, 8, 0, 24, 8);
setEGLConfigChooser(8, 8, 8, 0, 16, 8);
setEGLConfigChooser(5, 6, 5, 0, 24, 8);
setEGLConfigChooser(5, 6, 5, 0, 16, 8);

为了更加彻底,您还可以使用setEGLConfigChooser()覆盖,以便您注册自己的EGLConfigChooser实施。使用它,您可以枚举配置,并实现自己的逻辑,以选择最符合您需求的逻辑。

要验证您确实有模板缓冲区,可以使用:

GLint stencilBits = 0;
glGetIntegerv(GL_STENCIL_BITS, &stencilBits);

我认为模板支持是标准的,但是我阅读ES 2.0规范的方式,并不是必需的:

  

此外,实现或上下文可能不提供深度或模板缓冲区。但是,OpenGL ES实现必须至少支持一个深度位深度的配置。

我相信至少相对较新的GPU支持模板。如果你必须在GPU上工作,在你尝试了以上所有内容之后确实没有提供模板,事情变得更加困难。对于您绘制的示例,您可以通过矩形剪切,这当然可以通过使用剪刀矩形来完成。但我确信你只是用它来说明。

根据您为实际渲染使用深度缓冲区的程度,您可以使用深度缓冲区来玩一些技巧。例如,它可能如下所示:

glClearDepthf(0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
// draw clip entity
glEnable(GL_DEPTH_TEST);
// draw children

这样做的缺点是你需要对部分绘图禁用深度测试,如果绘图需要深度测试才能正确渲染,这可能是完全不可接受的。