Search code examples
androidopengl-esandroid-camerashaderrender-to-texture

Render camera preview on a Texture with target GL_TEXTURE_2D


I'm trying to render the camera preview on an OpenGL Texture with target GL_TEXTURE_2D. I'm very well aware of SurfaceTexture but I cannot use it because it only works with GL_TEXTURE_EXTERNAL_OES. In the documentation of SurfaceTexture, it's written :

 Each time the texture is bound it must be bound to the GL_TEXTURE_EXTERNAL_OES target rather than the GL_TEXTURE_2D target

I cannot use GL_TEXTURE_EXTERNAL_OES because, I'll have to make a lot of changes in my existing code.

Is there a way to achieve this which is fast too ?


Solution

  • The only way I can come up with is to listen to the SurfaceTexture and when new frame comes you just redraw it on a GL_TEXTURE_2D target.

    When coming to the OpenGL ES field, things can get really complicated. Let me try to explain this to you with my limited experience. Some pseudocode below.

    1. If you want to render the camera data to a off-screen texture, you'll need a off-screen frame buffer. Some functions you may need.

      GLES20.glGenTextures(1, textures, 0);
      GLES20.glGenFramebuffers(1, frames, 0);
      GLES20.glGenRenderbuffers(1, frameRender, 0);
      GLES20.glActiveTexture(ActiveTexture);
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
      GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
                  width, height, 0, GLES20.GL_RGBA,
                  GLES20.GL_UNSIGNED_BYTE, directIntBuffer);
      GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER,
                  frameRender[0]);
      GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,
                  GLES20.GL_DEPTH_COMPONENT16, width, height);
      GLES20.glViewport(0, 0, width, height);
      GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frames[0]);
      GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
                  GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D,
                  textures[0], 0);
      GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER,
                  GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER,
                  frameRender[0]);
      
    2. Compile your vertex and fragment shaders and link your program.

    3. Prepare your vertex, textureCoordinates and drawList buffers.
    4. Bind your SurfaceTexture from camera to a certain GL_TEXTURE

      GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
      GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, cameraSurfaceTextureHandle);
      
    5. GLES20.glUseProgram(yourProgram), link all the above together, and GLES20.glDrawElements