【问题标题】:OpenGL stencil (Clip Entity)OpenGL 模板(剪辑实体)
【发布时间】:2014-07-02 20:22:35
【问题描述】:

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

我正在尝试使用 OpenGL 模板功能来做到这一点。在我的模拟器上我让它工作了,但在我的安卓手机上却没有。我做错了什么?

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);

【问题讨论】:

  • 在设备上运行时是否检查过模板缓冲区存在?
  • 是的,请检查您的setEGLConfigChooser() 呼叫,并确保您请求了模板缓冲区。当您请求深度缓冲区时,某些设备会自动为您提供模板缓冲区,因为深度/模板通常组合在同一个缓冲区中。但并非所有设备都如此。
  • 非常感谢你们两位的快速回答!我真的很感谢你的帮助。我已经调用 view.setEGLConfigChooser(8, 8, 8, 8, 16, 0);在 onSetContentView 但遗憾的是没有成功。还有其他想法吗?顺便说一句:我应该基本上避免使用 OpenGL 模板还是这是一种稳定的方式来实现我想要的?
  • setEGLConfigChooser() 重载的最后一个参数是stencilSize。使用 8 作为最后一个参数的值。
  • 感谢您回复我!我现在调用 this.mRenderSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8);但它仍然不起作用?无论如何,使用模板是个好主意吗? - 他们在大多数设备上都能正常工作吗?感谢你的帮助。谢谢

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


【解决方案1】:

为您所描述的内容使用模板缓冲区听起来是个好方法。

您需要确保请求带有模板缓冲区的帧缓冲区配置。在 Android 上使用 GLSurfaceView 时,这是通过重载的 setEGLConfigChooser() 方法之一完成的。最简单的形式是对 Red、Green、Blue、Alpha、Depth 和 Stencil 采用位深度的形式。如果你还需要一个深度缓冲区,你可以尝试这样的组合来获得一个带有模板的配置:

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

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

【讨论】:

  • 嗨,Reto。非常感谢您的详细解答!十分有趣。我还认为 ES 2.0 的所有设备都支持模板,很高兴知道我错了。是的,你是对的,我不能使用剪刀,因为我还想旋转“剪辑矩形”。但是,似乎我必须找到另一种解决方法以避免在某些不支持模板的设备上出现不当行为。感谢您的时间和精力!祝你有美好的一天
猜你喜欢
  • 1970-01-01
  • 2013-09-23
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
  • 1970-01-01
  • 2014-06-09
  • 1970-01-01
相关资源
最近更新 更多