Android, OpenGL ES 2.0, ndk - glCheckFramebufferStatus retur

Android, OpenGL ES 2.0, ndk - glCheckFramebufferStatus returning GL_FRAMEBUFFER_UNSUPPORTED

本文关键字:glCheckFramebufferStatus retur ndk OpenGL ES Android      更新时间:2023-10-16

我正在将一款用c++编写的游戏(带有SDL)移植到Android上。我之前在一个旧的项目上做过这个(在stackoverflow的帮助下!),尽管结果有点草率,但它在我扔给它的几乎所有Android设备上都能工作。

当时我太累了,无法重构和简化我所拥有的东西。这次我要创建一个引擎,理论上我不需要再碰,我把我的旧代码带来了。虽然我已经编译并运行了所有内容,但它没有呈现任何内容。

具体来说,OpenGL ES 2.0抛出了一个GL_FRAMEBUFFER_UNSUPPORTED消息。我将所有内容绘制为纹理(它 320x240 -最终会改变),然后绘制该纹理,使其覆盖屏幕。它拒绝画到那个纹理-我可以直接画到屏幕上(这至少让我希望着色器是好的),但这不是很有帮助。

我的framebuffer代码看起来像这样:
_superDuperFrameBuffer = 0;
_depthRenderBuffer = 0;
glGenFramebuffers(1, &_superDuperFrameBuffer);
//-----
glGenTextures(1, &_screenTexture);
glBindTexture(GL_TEXTURE_2D, _screenTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCREENWIDTH2, SCREENHEIGHT2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); //float?
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if(_currentWidth < SCREENWIDTH2*2 || _currentHeight < SCREENHEIGHT2*2) {
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else {
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glBindTexture(GL_TEXTURE_2D, 0);
//-----
glGenRenderbuffers(1, &_depthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, SCREENWIDTH2, SCREENHEIGHT2);
glGenRenderbuffers(1, &_stencilRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _stencilRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, SCREENWIDTH2, SCREENHEIGHT2);

glBindFramebuffer(GL_FRAMEBUFFER, _superDuperFrameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER,      GL_COLOR_ATTACHMENT0,   GL_TEXTURE_2D,      _screenTexture, 0); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER,   GL_DEPTH_ATTACHMENT,    GL_RENDERBUFFER,    _depthRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,   GL_STENCIL_ATTACHMENT,  GL_RENDERBUFFER,    _stencilRenderBuffer);

GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE) {
    __android_log_print(ANDROID_LOG_VERBOSE, "LOG", "FRAMEBUFFER BORK %x", status);
}

这里有什么明显的我做错了吗?这是一款简单的2D游戏——没有什么花哨的东西,而且之前似乎都行得通。我不知道Android的最佳设置是什么——没有任何东西来解释如何正确地做事情。

从我读到的,GL_FRAMEBUFFER_UNSUPPORTED应该在一个设置与另一个设置不一致时出现,或者如果设备不支持framebuffer(我知道它支持,因为我的上一款游戏运行得很好!)

同样关心的代码可能没有得到正确的清理-一两次早期版本已经显示出生命的迹象,但重新启动游戏后,他们没有。我没有排除有外部影响干扰的想法,但我想我应该先检查一下上面的代码是否正确。

在2013年Nexus 7上的测试。

提前感谢!

如注释所述,framebuffer可以在没有深度和模板渲染缓冲区绑定的情况下工作。这是GL[ES]的一个常见问题,因为没有查询支持的组合和/或格式的方法。你只需要尝试一下,看看它是否有效——如果不行,实际的问题并不总是很清楚。来自GLES 2.0规范:

4.1按分片操作所有OpenGL 2.0的每片段操作都是支持的,除了遮挡查询,逻辑操作,alpha测试和颜色指数相关的操作。支持深度和模板操作,但不支持选定的配置需要包含深度或模板缓冲区,但OpenGL ES 2.0实现必须包含深度或模板缓冲区至少支持一个配置,深度位深度为16及以上,模板位深度为8及以上。

但是,它不要求任何特定的深度和/或模板格式或其组合。glCheckFramebufferStatus管理页面说明:

GL_DEPTH_COMPONENT16是唯一可深度渲染的格式。GL_STENCIL_INDEX8是唯一可模板渲染的格式。

这个语句可以(并且是)被扩展修改。它也没有明确地说明两者的组合一定会形成一个有效的组合,从而导致glCheckFramebufferStatus报告成功,并且在某些驱动程序中,它们不会(肾上腺素320可能是其中之一)。

事实是,许多(大多数)Android gpu支持GL_OES_packed_depth_stencil扩展,它提供了DEPTH24_STENCIL8_OES格式,所以如果这个扩展是可用的,DEPTH24_STENCIL8_OES应该优先于GL_DEPTH_COMPONENT16GL_STENCIL_INDEX8的组合,因为它肯定支持该驱动程序。用这种格式创建的渲染缓冲区应该同时绑定到GL_DEPTH_ATTACHMENTGL_STENCIL_ATTACHMENT。这个扩展在GLES 3.0中成为标准,这意味着每个支持GLES 3.0的设备都应该有它。

当然,如果您不需要 depth/stencil附件,那么,它们只是浪费内存,您不应该使用它们。但是,如果您只是移植任意的呈现代码,那么将它们绑定起来可能更安全。
相关文章:
  • 没有找到相关文章