Android, OpenGL ES 2.0, ndk - glCheckFramebufferStatus retur
Android, OpenGL ES 2.0, ndk - glCheckFramebufferStatus returning GL_FRAMEBUFFER_UNSUPPORTED
我正在将一款用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_COMPONENT16
和GL_STENCIL_INDEX8
的组合,因为它肯定支持该驱动程序。用这种格式创建的渲染缓冲区应该同时绑定到GL_DEPTH_ATTACHMENT
和GL_STENCIL_ATTACHMENT
。这个扩展在GLES 3.0中成为标准,这意味着每个支持GLES 3.0的设备都应该有它。
- 没有找到相关文章