OpenGL ES渲染到纹理,然后绘制纹理。

7
我正在尝试使用iPhone上的OpenGL ES将内容渲染到纹理中,然后将该纹理绘制到屏幕上。我以这个问题为起点,在Apple演示EAGLView的子类中进行绘图。
实例变量:
GLuint textureFrameBuffer;
Texture2D * texture;

为了初始化帧缓冲区和纹理,我正在进行以下操作:

GLint oldFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);

// initWithData results in a white image on the device (works fine in the simulator)
texture = [[Texture2D alloc] initWithImage:[UIImage imageNamed:@"blank320.png"]];

// create framebuffer
glGenFramebuffersOES(1, &textureFrameBuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);

// attach renderbuffer
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture.name, 0);

if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
    NSLog(@"incomplete");

glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);

现在,如果我像往常一样将场景绘制到屏幕上,那么它就能正常工作:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw some triangles, complete with vertex normals
[contentDelegate draw];
[self swapBuffers];

但是,如果我将渲染结果放在'textureFrameBuffer'中,然后将'texture'绘制到屏幕上,得到的图像会颠倒并且“里外颠倒”。也就是说,看起来好像3D对象的法线指向内部而不是外部 -- 每个对象的最前面的面是透明的,我可以看到背面的内部。以下是代码:

GLint oldFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);

glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// draw some polygons
[contentDelegate draw];

glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glColor4f(1, 1, 1, 1);
[texture drawInRect:CGRectMake(0, 0, 320, 480)];    
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);

[self swapBuffers];

我可以通过重新排列(在Texture2D的drawInRect方法中)(glTexCoordPointer)坐标来轻松地将图像上下翻转,但这并不能解决“里外颠倒”的问题。
我尝试用手动创建的OpenGL纹理替换Texture2D纹理,结果相同。从PNG图像加载的Texture2D绘制正常。
至于绘制对象,每个顶点都有一个单位法线指定,并启用了GL_NORMALIZE。
glVertexPointer(3, GL_FLOAT, 0, myVerts);
glNormalPointer(GL_FLOAT, 0, myNormals);
glDrawArrays(GL_TRIANGLES, 0, numVerts);

当渲染到屏幕上时,所有东西都可以正常绘制;启用了GL_DEPTH_TEST并且工作得很好。

有什么建议可以解决这个问题吗?谢谢!


关于“内外”问题:如果您的前向基元被剔除,那么您就有了一个顶点排序问题,这会用于确定面法线。这不是纹理问题,除非我理解错了。您启用了GL_CULL_FACE吗? - prideout
GL_CULL_FACE未启用。启用它肯定会改善整体外观。物体法线现在似乎是正确的,但很多本应该隐藏的正面面孔现在可见,不管它们是否(或者更确切地说,应该)被另一个面遮挡。这是否表明我的三角形的绕序存在问题?我正在使用脚本从Blender导出顶点;我将确保在导出时绕序是统一的。请注意,当我直接绘制到屏幕上时,一切看起来都完美(GL_CULL_FACE开启或关闭都没有任何区别)。 - sb.
1个回答

3
这个有趣的部分是,当直接绘制到背景缓冲时,你会看到不同的结果。由于你在iPhone平台上,即使你绘制到背景缓冲区,你实际上也是在绘制到一个FBO上。
确保你的离屏FBO上附有深度缓冲区。在初始化代码中,你可能想在glBindFramebufferOES(...)后添加以下代码片段。
// attach depth buffer
GLuint depthRenderbuffer;
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, width, height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

你可能有所发现,但它还没有完全起作用... 在执行此操作并附加纹理(如之前所述)后,glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) 返回GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES。frameBuffer是否也需要附加颜色渲染缓冲区?(我已经尝试过了,但还没有成功,不过我会继续努力。)顺便说一句,非常感谢你的帮助。 - sb.
哦,我是想将渲染添加到后备缓冲区,然后使用glCopyTexSubImage2D将其复制到我的图像中,然后显示该图像(一切都绘制得很好),只是速度非常慢。现在回去找出我的缓冲区有什么问题... - sb.
有趣。是的,您确实需要附加一个颜色渲染缓冲区。顺便说一下,这与此无关,但您可能需要确保您的纹理对象具有2的幂大小,以便它可以在旧版iPhone上使用。祝你好运! - prideout
好的,我已经不再从事这个项目了,并且没有设置所有必要的缓冲区。我将其标记为正确,因为它很可能是正确的。如果我回来了,我会在这里发布我的工作代码。 - sb.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接