对于某些纹理大小,glFramebufferTexture2D 在 iPhone 上失败
Posted
技术标签:
【中文标题】对于某些纹理大小,glFramebufferTexture2D 在 iPhone 上失败【英文标题】:glFramebufferTexture2D fails on iPhone for certain texture sizes 【发布时间】:2011-04-29 18:07:21 【问题描述】:当我尝试将纹理附加到帧缓冲区时,glCheckFramebufferStatus 会针对某些纹理大小报告 GL_FRAMEBUFFER_UNSUPPORTED。我已经在第 2 代和第 4 代 iPod Touch 上进行了测试。两个模型之间失败的纹理大小不相同。
以下是一些有趣的结果:
第二代 - 8x8 失败,16x8 失败,但 8x16 成功!
第 4 代 - 8x8 成功,8x16 成功,但 16x8 失败!
这是我用来测试附加不同大小纹理的一些代码:
void TestFBOTextureSize(int width, int height)
GLuint framebuffer, texture;
// Create framebuffer
glGenFramebuffersOES(1, &framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
// Create texture
glGenTextures(1,&texture);
glBindTexture(GL_TEXTURE_2D,texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D,0);
// Attach texture to framebuffer
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture, 0);
GLenum error = glGetError();
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status==GL_FRAMEBUFFER_COMPLETE_OES)
NSLog(@"%dx%d Succeeded!",width,height,status);
else
NSLog(@"%dx%d Failed: %x %x %d %d",width,height,status,error,texture,framebuffer);
// Cleanup
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, 0, 0);
glDeleteTextures(1, &texture);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glDeleteFramebuffersOES(1, &framebuffer);
void TestFBOTextureSizes()
int width,height;
for (width=1; width<=1024; width<<=1)
for (height=1; height<=1024; height<<=1)
TestFBOTextureSize(width,height);
似乎只要两个尺寸都至少为 16 像素,那么在两个设备上一切正常。不过,困扰我的是,我还没有看到任何关于附加到帧缓冲区对象的纹理大小要求的文章。目前,一种解决方案是将我的纹理大小限制为至少 16 像素,但这可能会在未来中断或已经在我未尝试过的某些设备上中断?我也可以在启动时执行此测试代码,以便动态确定允许哪些纹理大小,但这似乎有点做作。
【问题讨论】:
【参考方案1】:当我尝试在 iPod touch 4 上渲染大小为 480x320(无分辨率比例的全屏)的纹理时,我遇到了类似的问题。当我调用 glCheckFramebufferStatus()
时,它返回 GL_FRAMEBUFFER_UNSUPPORTED
。我的代码:
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 480, 320, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
// report error
调查这个问题我发现GL_TEXTURE_2D
必须是一个有效的 OpenGL ES 对象,如果我们希望它用于渲染到纹理机制。这意味着纹理应该准备好绑定和使用。所以要修复一个错误,我必须设置一些纹理参数。因为我使用非 POT 纹理,所以我必须将 GL_TEXTURE_WRAP_
设置为 GL_CLAMP_TO_EDGE
(默认值为 GL_REPEAT
)和 GL_TEXTURE_MIN_FILTER
设置为 GL_NEAREST
或 GL_LINEAR
(默认值为 GL_NEAREST_MIPMAP_LINEAR
)才能使用此纹理.
我找不到 16x8 有什么问题,但是如果设置了这个参数,16x9 和 17x8 可以正常工作。我希望这些信息对您有所帮助。
【讨论】:
即使我将环绕模式设置为 GL_CLAMP_TO_EDGE 并将最小过滤器设置为最近,我仍然会收到错误消息。当您说您对 16x8 纹理没有问题时,您的意思是我的示例代码在您的设备上适用于 16x8 纹理吗?或者你的意思是它可以在你自己的代码中工作?也许您可以发布一个类似于我的适用于 16x8 纹理的示例的小示例。谢谢! 我也有纹理 16x8 的问题。它对我也不起作用。但是 16x9 和 17x8 就可以了!这很奇怪。我刚刚注意到如果要将纹理对象附加到帧缓冲区,它应该具有有效的参数。 很奇怪!我认为我的解决方案是不要尝试从我的纹理中读取数据。我使用附加到帧缓冲区的纹理结合 glReadPixels 将纹理数据恢复到内存中。这对我所做的事情并不重要,所以我可以解决它。以上是关于对于某些纹理大小,glFramebufferTexture2D 在 iPhone 上失败的主要内容,如果未能解决你的问题,请参考以下文章