java - OpenGL 模板(剪辑实体)

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

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

我正在尝试使用 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

最佳答案

针对您所描述的内容使用模板缓冲区听起来是一个不错的方法。

您需要确保请求带有模板缓冲区的帧缓冲区配置。在 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 规范的方式,它不是必需的:

Further, an implementation or context may not provide depth or stencil buffers. However, an OpenGL ES implementation must support at least one config with a depth bit depth.

我相信至少最近的 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

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

关于java - OpenGL 模板(剪辑实体),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24540373/

相关文章:

android - 使布局的最小宽度与内部 View 的宽度匹配

Android中的android.permission.READ_PROFILE,它有什么作用?

java - 遍历列表后得到一个总和

iphone - 如何使用 glDrawTex*

java - 使用 OpenGL ES 绘制纹理最简单的方法是什么?

java - 按降序对 Firebase 数据进行排序

java - 当 Activity 处于后台时,在 AsyncTask.onPostExecute 上显示 DialogFragment;

ios - 在iPhone4上使用OpenGL ES加载大纹理时出现glError 0x0501

java - 告诉任意 SSLSocketFactories 信任所有证书?

java - 根据格式比较日期