3

I am displaying a video on a GLSurfaceView with a custom renderer that requires that multiple shaders be applied in succession. Currently, it is working successfully with one shader, though I am not sure how to extend the rendering pipeline to apply multiple shaders in succession.

I know that there are some examples concerning applying multiple shaders (using FrameBuffers and RenderBuffers), but I have not found any that deal with an image passed in through a SurfaceTexture.

There is a specific concern I would like to address:

A SurfaceTexture must be bound to a GL_TEXTURE_EXTERNAL_OES texture. On the other hand, a FrameBuffer cannot be bound to a GL_TEXTURE_EXTERNAL_OES texture (typically a GL_TEXTURE_2D is used), so is it even possible to use a FrameBuffer for a multi-pass render when the input texture is of a different format than the output? If not, what are the other options for performing a multi-pass render?

Below is some relevant code in the onSurfaceCreated function of the renderer I am trying to extend to perform multiple passes::

            GLES20.glGenTextures(1, this.textureID, 0);
            GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, this.textureID[0]);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
            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.glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
            this.surfaceTexture = new SurfaceTexture(this.textureID[0]);

Below is some relevant code in the onDrawFrame function of that renderer:

        synchronized (this) {
            if (this.updateSurface) {
                this.surfaceTexture.updateTexImage();
                this.surfaceTexture.getTransformMatrix(this.stMatrix);
                this.updateSurface = false;
            }
        }

        GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, this.textureID[0]);
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

  //apply shader here and call glDrawArrays() at end
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
M.S.
  • 1,091
  • 1
  • 11
  • 27
  • no single comment even?! it is funny that editors care more about making sure that u have not said thank you at the end or make a grammatical mistake in the question and don't care about such an important question. sof is becoming petty, soon it will die and stuff like chatgpt will take its place when they get a bit mature. Anyway, @M.S. if u found the solution to this problem please share it, thanks! – Mohammad Elsayed Feb 08 '23 at 12:29

1 Answers1

0

One way to approach this would be to use a SurfaceHolder rather than a SurfaceTexture.

From there, you can then get the Surface being held by the SurfaceHolder.

Then you can get the underlying Canvas being drawn to.

Note: Per this answer, you will need to use setBitmap(Bitmap canvas_bitmap) to specify the Bitmap being drawn into.

All the texture setup and parameter stuff will still need to be done basically the way you showed in you question.

GLES20.glGenTextures(1, this.textureID, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.textureID[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
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);

Then dump the bitmap into a texture using:

GLUtils.texImage2D( GLES20.GL_TEXTURE_2D, 0, canvas_bitmap, 0 );
G. Putnam
  • 1,262
  • 5
  • 10
  • it is not possible to do that in my case, I need to use the TextureView as my cameraview which means I have to use the surfaceTexture. what I need is to understand how to convert from GL_TEXTURE_EXTERNAL_OES to GL_TEXTURE_2D so that we can render external texture coming from the camera for example on a framebuffer @G. Putnam – Mohammad Elsayed Feb 09 '23 at 10:54
  • to help you with that, I found a way but I can't understand how to do it, it is done using EGLImage and glEGLImageTargetTexture2DOES and eglCreateImage. that is what I got so far maybe that helps u finding the solution – Mohammad Elsayed Feb 09 '23 at 10:55
  • Ok, I was just trying to answer the question of "what are the other options for performing a multi-pass render?" Another option that would support my answer would be [using a SurfaceView](https://tutorialwing.com/android-surfaceview-tutorial-with-example/) rather than a TextureView. [This question](https://stackoverflow.com/questions/39893367/how-to-show-the-camera-preview-on-a-surfaceview) also covers the topic. – G. Putnam Feb 09 '23 at 21:40
  • sorry if it was not so obvious, my project has to use textureview and I am interested in knowing how to make framebuffer accepts to bound to a texture that is OES and not TEXTURE_2D, please help me if u can, and if u think it is impossible please let me know. I will give the bounty anyway. – Mohammad Elsayed Feb 12 '23 at 21:04
  • If it must be TextureView and GL_TEXTURE_EXTERNAL_OES, then you could convert over to a GL_TEXTURE_2D using a method similar to [shown in this post](https://stackoverflow.com/questions/53388939/read-from-gl-texture-external-oes-to-gl-texture-2d-have-perfomance-issues-and-gl) where you use glReadPixels to read to a buffer and then write to a tex_2D. Note, from [this post](https://stackoverflow.com/questions/37258251/bind-gles-texture-to-gl-texture-2d-from-gl-texture-external-oes), it looks like if you use the GL_TEXTURE_EXTERNAL_OES even in the main draw you need to have `samplerExternalOES` – G. Putnam Feb 12 '23 at 21:34
  • Yeah regarding that one, glReadPixels is extremely inefficient and eats the whole gpu, keep in mind that I have 30 fps, so using glReadPixels, is not an option at all. – Mohammad Elsayed Feb 12 '23 at 21:37