Android Opengl ES 2.0 FrameBuffer 不工作

Posted

技术标签:

【中文标题】Android Opengl ES 2.0 FrameBuffer 不工作【英文标题】:Android Opengl ES 2.0 FrameBuffer not working 【发布时间】:2014-06-04 03:06:01 【问题描述】:

我正在开发一个 2D android 项目,我希望使用 FBO 将内容绘制到空纹理,然后在屏幕上绘制该纹理。出于调试目的,FBO 附加的纹理应立即变为蓝色,因此我可以知道我可以编辑纹理,因为目前它甚至不会影响纹理。

帧缓冲区:

public static class FrameBuffer

    private final FaustEngine engine;
    private final int width;
    private final int height;
    private final int[] fboId = new int[1];
    private final int[] renId = new int[1];

    public FrameBuffer( FaustEngine Engine, int Width, int Height )
        engine = Engine;
        width = Width;
        height = Height;

        GLES20.glGenRenderbuffers( 1, renId, 0 );
        GLES20.glBindRenderbuffer( GLES20.GL_RENDERBUFFER, renId[0] );
        GLES20.glRenderbufferStorage( GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT, width, height );

        GLES20.glGenFramebuffers( 1, fboId, 0 );
        GLES20.glBindFramebuffer( GLES20.GL_FRAMEBUFFER, fboId[0] );
        GLES20.glFramebufferRenderbuffer( GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, renId[0] );

        GLES20.glBindRenderbuffer( GLES20.GL_RENDERBUFFER, 0);
        GLES20.glBindFramebuffer( GLES20.GL_FRAMEBUFFER, 0);
    

    public void bind( int texId, int texWidth, int texHeight )
        GLES20.glBindFramebuffer( GLES20.GL_FRAMEBUFFER, fboId[0] );
        GLES20.glFramebufferTexture2D( GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texId, 0 );
        GLES20.glViewport( 0, 0, texWidth, texHeight );
        GLES20.glClearColor(0f, 0f, 1f, 1f );
        GLES20.glClear( GLES20.GL_COLOR_BUFFER_BIT ); //Turn blue

        //Fix projection matrix
        Matrix.orthoM( engine.getOrthoMatrix() , 0, 0, texWidth, texHeight, 0, -1, 1 );
    

    public void unbind()
        GLES20.glBindFramebuffer( GLES20.GL_FRAMEBUFFER, 0 );
        GLES20.glViewport( 0, 0, engine.getScreenWidth(), engine.getScreenHeight() );

        //Reset projection matrix
        Matrix.orthoM( engine.getOrthoMatrix() , 0, 0, engine.getScreenWidth(), engine.getScreenHeight(), 0, -1, 1 );
    

渲染代码:

FrameBuffer fbo = new FrameBuffer( game.getEngine(), 1024, 1024 );
final int[] texIds = new int[1];
game.getEngine().createBlankTextures( texIds, 1024, 1024 );

fbo.bind( texIds[0], 1024, 1024 );
//texture should turn blue here since in the bind() function I placed a glClear with blue
fbo.unbind();

纹理创建:

public void createBlankTextures( int[] texIds, int width, int height )
    GLES20.glGenTextures( texIds.length, texIds, 0 );
    for( int i=0; i<texIds.length; i++ )
        GLES20.glBindTexture( GLES20.GL_TEXTURE_2D, texIds[i] );
        GLES20.glTexParameteri( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST );
        GLES20.glTexParameteri( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST );
        GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null );
        GLES20.glGenerateMipmap( GLES20.GL_TEXTURE_2D );
    

所以我有 2 个问题。

1.) 我需要带有帧缓冲区的渲染缓冲区吗?我不想跟踪深度。我只想编辑现有的纯 2D 纹理。

2.) 为什么这不起作用?

【问题讨论】:

【参考方案1】:

如果您的 FBO 渲染不需要深度缓冲区,则无需创建渲染缓冲区。

GL_DEPTH_COMPONENT 不是 ES 2.0 中 glRenderbufferStorage()internalformat 参数的有效值。如果您查看支持的值 (http://www.khronos.org/opengles/sdk/docs/man/xhtml/glRenderbufferStorage.xml),唯一的深度格式是 GL_DEPTH_COMPONENT16

一如既往,glGetError() 是您的朋友。它应该指示来自您的 glRenderbufferStorage() 调用的 GL_INVALID_ENUM 错误。

【讨论】:

做到了。非常感谢。我永远不会猜到这是一个专门针对 ES 2.0 的不兼容参数

以上是关于Android Opengl ES 2.0 FrameBuffer 不工作的主要内容,如果未能解决你的问题,请参考以下文章

Android OpenGL ES 2.0 模拟器

如何在Android上使用OpenGL ES 2.0绘制点

Android openGL ES 2.0里Surfaceview背景透明

Android:了解 OnDrawFrame、FPS 和 VSync (OpenGL ES 2.0)

Android设备上的OpenGL ES 2.0扩展[关闭]

Android Opengl ES 2.0 FrameBuffer 不工作