Luke AP
Luke AP

Reputation: 95

OpenGL ES can't make LUMINANCE FBO work in Android

I'm using framebuffers to do some post processing shaders on a video renderer. One of the shaders is quite look-up intensive so I would like to change to a luminance only frame buffer to speed things up. I've tried changing the glTexImage2D call from RGBA to LUMINANCE in the initialisation but I then get an error when I attempt to attach the buffer in "onDrawFrame".

The trouble is I have hacked the code together from examples and don't quite understand everything it is doing. For one thing I am also creating a depth attachment, since I am rendering video I don't need any depth information but I don't know whether I can just disable that. Anyway here is my initialisation for the FBO in onSurfaceCreated:

        GLES20.glGenTextures(1, renTex, 0);

        // generate
        GLES20.glGenFramebuffers(1, fb2, 0);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE4);

        // generate color texture
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renTex[0]);

        // parameters
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);

        // create it 
        // create an empty intbuffer first?
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, texW, texH, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, texBuffer);
        //**THIS WORKS AS IS, CHANGING FROM RGBA TO LUMINANCE BREAKS IT**

        // create render buffer and bind 16-bit depth buffer
        GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[0]);
        GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, texW, texH);

And here is the code to attach the buffer in onDrawFrame:

    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[0]);
    // specify texture as color attachment
    GLES20.glViewport(0, 0, w, h);
    Matrix.frustumM(mProjMatrix, 0, -.30f, .30f, -.30f, .30f, 3, 7);


    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renTex[0], 0);
    // attach render buffer as depth buffer


    GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRb[0]);
    int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
    if (status != GLES20.GL_FRAMEBUFFER_COMPLETE)
        System.out.println("Frame buffer not obtained :(");
//This works for RGBA but returns an error for LUMINANCE

Anyone got any suggestions? Also can I ditch the depth buffer component or is it mandatory

Upvotes: 1

Views: 1535

Answers (2)

sergyt
sergyt

Reputation: 11

Use two textures as frame buffer targets one with GL_RED_EXT format for Y plane and other with GL_RG_EXT for UV plane. Second texture will have a half dimensions of first, so you can't assign them in one time to different COLOR_ATTACHMENTS and need to do your rendering twice, with different viewports as well.

 #include "gl2ext.h" 

...
    glGenTextures(1, &mYTextureId);
    glBindTexture(GL_TEXTURE_2D, mYTextureId);
...
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED_EXT, mCameraFrameWidth, mCameraFrameHeight, 0, GL_RED_EXT, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mYTextureId, 0);
    glViewport(0, 0, mCameraFrameWidth, mCameraFrameHeight);
...

    glGenTextures(1, &mUVTextureId);
    glBindTexture(GL_TEXTURE_2D, mUVTextureId);
...
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RG_EXT, mCameraFrameWidth/2, mCameraFrameHeight/2, 0, GL_RG_EXT, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mUVTextureId, 0);
    glViewport(0, 0, mCameraFrameWidth/2, mCameraFrameHeight/2);
...

This works on most iPhone and Android phones with arm7+

Upvotes: 0

Mika Haarahiltunen
Mika Haarahiltunen

Reputation: 471

GL_LUMINANCE is not a color-renderable format. From OpenGL ES 2.0 specification section 4.4.5:

Formats not listed in table 4.5, including compressed internal formats. are not color-, depth-, or stencil-renderable, no matter which components they contain.

The color-renderable formats listed in the table are: RGBA4, RGB5_A1 and RGB565.

Even RGB8 and RGBA8 are not listed in the table but since you can use RGBA8, your device probably supports OES_rgb8_rgba8 and/or ARM_rgba8 extension.

Upvotes: 1

Related Questions