1

我从 Android NDK 和 OpenGL 开始。我知道我在这里做错了一些事情(可能是一些事情),因为我在测试时一直出现黑屏,所以我知道渲染没有被发送到屏幕上。

在 Java 中,我有一个调用这两个本机方法的 GLSurfaceView.Renderer。它们被正确调用,但未绘制到设备屏幕。

有人能指出我正确的方向吗?

以下是本机方法实现:

int init()
{
    sendMessage("init()");

    glGenFramebuffersOES(1, &framebuffer);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);

    glGenRenderbuffersOES(1, &colorRenderbuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, 854, 480);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);

    GLuint depthRenderbuffer;
    glGenRenderbuffersOES(1, &depthRenderbuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
    glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, 854, 480);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

    GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
    if(status != GL_FRAMEBUFFER_COMPLETE_OES)
        sendMessage("Failed to make complete framebuffer object");

    return 0;
}

void draw()
{
    sendMessage("draw()");

    GLfloat vertices[] = {1,0,0, 0,1,0, -1,0,0};
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, vertices);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDisableClientState(GL_VERTEX_ARRAY);

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

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
}

日志输出为:

init() draw() draw() draw() 等等。

4

3 回答 3

4

我认为这根本不是一个真正的解决方案。

我在这里遇到了同样的问题,在本机代码中使用帧缓冲区对象,并通过

framebuffer = (GLuint) 0;

您只使用默认的帧缓冲区,该缓冲区始终存在并保留为 0。从技术上讲,您可以擦除与帧缓冲区相关的所有代码,并且您的应用程序应该可以正常工作,因为始终生成帧缓冲区 0 并且是由默认值绑定的.

但是,您应该能够生成多个帧缓冲区并根据需要使用绑定函数(glBindFramebuffer)在它们之间进行交换。但这似乎对我不起作用,我还没有找到真正的解决方案。关于 android 部分的文档并不多,我开始怀疑本机代码是否真的支持 fbo。虽然它们在 java 代码中确实可以正常工作,但我已经成功对其进行了测试!

哦 !而且我刚刚注意到您的缓冲区尺寸不是 2 的幂......通常应该是所有纹理/缓冲区(如 Opengl 中的结构)的情况。


更新 :

现在我相当确定你不能将 FBO 与 android(2.2 或更低)和 ndk(r5b 或更低版本)一起使用。如果您使用新的 3.1 版本,这是一个完全不同的游戏,您可以使用本机代码编写所有应用程序(不再需要 jni 包装器),但我还没有测试它!

另一方面,我已经设法使 Stencil 缓冲区和纹理完美地工作!因此,解决方法是将这些用于我的渲染逻辑,而忘记 FBO 屏幕外渲染。

于 2011-05-12T20:53:35.400 回答
1

经过大量修补后,我终于找到了问题。

事实证明,因为我是从 Java 中的 GLSurfaceView.Renderer 调用代码,所以帧缓冲区已经存在,因此通过调用:

glGenFramebuffersOES(1, &framebuffer);

我无意中分配了一个未附加到目标显示器的新缓冲区。通过删除此行并将其替换为:

framebuffer = (GLuint) 0;

它现在呈现到正确的缓冲区并正确显示在屏幕上。请注意,即使我并没有真正使用此代码段中的缓冲区,更改它也会破坏正确的显示。

于 2011-01-21T03:13:05.647 回答
0

从 iOS 迁移到 Android NDK 时,我遇到了类似的问题,这也是我的完整解决方案。

OpenGLES 1.1 with FrameBuffer / ColorBuffer / DepthBuffer for Android with NDK r7b

于 2012-05-19T09:08:19.593 回答