Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: How to use the GlFrameBuffer? #25

Open
kihaki opened this issue Jul 14, 2020 · 5 comments
Open

Documentation: How to use the GlFrameBuffer? #25

kihaki opened this issue Jul 14, 2020 · 5 comments

Comments

@kihaki
Copy link

kihaki commented Jul 14, 2020

Hey, I am trying to render to a texture using a framebuffer, but I can't seem to make it work, could you help me out here?

So I am setting up a SurfaceView and tried a simple rendering, which works just fine:

        val core = EglCore(flags = EglCore.FLAG_TRY_GLES3)
        val window = EglWindowSurface(core, surface)
        window.makeCurrent()

        val simpleProgram = GlFlatProgram()
        simpleProgram.setColor(Color.GREEN)
        val circle = GlCircle()
        circle.radius = 0.15F
        simpleProgram.draw(circle)

        // Publish
        window.swapBuffers()

But when I am trying to render to a FBO it crashes:

        val core = EglCore(flags = EglCore.FLAG_TRY_GLES3)
        val window = EglWindowSurface(core, surface)
        window.makeCurrent()

        val simpleProgram = GlFlatProgram()
        simpleProgram.setColor(Color.GREEN)
        val circle = GlCircle()
        circle.radius = 0.15F

        val fbTexture = GlTexture()
        val fbo = GlFramebuffer()
        fbo.attach(fbTexture, GLES20.GL_COLOR_ATTACHMENT0)
        fbo.bind()

        simpleProgram.draw(circle)

        // Publish
        window.swapBuffers()

java.lang.RuntimeException: Error during draw start: glError 0x502: invalid operation

Could you help me out with a working sample or a pinpoint in what's wrong? I couldn't glean much more from the docs.

@natario1
Copy link
Owner

natario1 commented Jul 14, 2020

There are many things going on:

  • If you want to render into a framebuffer, you don't need a window, so you can remove it.
  • Instead of creating the window, you should probably make the context current (core.makeCurrent() I think)
  • The GlTexture defaults to target = GL_TEXTURE_EXTERNAL_OES, but this only works with android surfaces, so with windows, not FBOs. You have to use target = GL_TEXTURE_2D and assign a proper width and height.
  • Don't forget to unbind() the FBO after drawing (or you can use fbo.use { /* draw */ } )

A good exercise to learn how to use the lib could be render the circle in the FBO as you're trying to do here, then render the FBO texture into a window (with another draw pass and GlTextureProgram).

@kihaki
Copy link
Author

kihaki commented Jul 14, 2020

Hey, first of all, thanks for you super quick response! I wouldn't have believed that you would answer in just 5 minutes.
I only read it just now but in the meantime I have made some progress on my own:

  • Updated to the latest version (0.5.2)
  • Figured the texture size out, also discovered fbo.use { ... }, which is very handy. Starting to love this library :)

Right now my code looks like this:

        val scene = GlScene()
        val core = EglCore(flags = EglCore.FLAG_TRY_GLES3)
        val window = EglWindowSurface(core, surface /* Surface from a SurfaceView so something becomes visible on screen */)
        window.makeCurrent()

        val simpleProgram = GlFlatProgram()
        simpleProgram.setColor(Color.GREEN)
        val quad = GlRect()

        val textureProgram = GlTextureProgram()
        val fbTexture = GlTexture(GL_TEXTURE0, GL_TEXTURE_2D, 100, 100)
        textureProgram.texture = fbTexture
        val fbo = GlFramebuffer()
        fbo.attach(fbTexture, GLES20.GL_COLOR_ATTACHMENT0)
        fbo.use {
            scene.draw(simpleProgram, quad)
        }
        scene.draw(textureProgram, quad)

        // Publish
        window.swapBuffers()

Which does not crash (so far so good). But the contents of the fbo are not visible on screen (its just black).
Skipping the fbo part will result in the correct image on screen, so I am pretty sure the simpleProgram renders correctly.
Skipping the EglWindowSurface as you mentioned, while not necessary for a fbo, is still required, because I want to render the final output to a surface, right?

I can't quite figure out if either 1) the content of the fbo is not updated or 2) the rendering of the textureProgram is somehow faulty.

Any ideas?

@natario1
Copy link
Owner

I think it's the same issue of EOS vs. regular textures. In GlTextureProgram constructor, the fragment shader defaults to SIMPLE_FRAGMENT_SHADER (which reads from external, android textures). Since you are using a regular 2D texture, you should replace samplerExternalOES with sampler2D.

Something like SIMPLE_FRAGMENT_SHADER.replace("samplerExternalOES", "sampler2D") might work

@kihaki
Copy link
Author

kihaki commented Jul 14, 2020

This fixes it, it's rendering correctly. Many thanks, this would probably have taken me a lot longer to find out on my own. I would like to write some small samples for your docs which could help out other people when starting out if that is okay for you? :)

This is just a simple example for now but I have it working and can build on it. Once again, thank you, also great work on the library!

@natario1
Copy link
Owner

Sure, feel free to open a PR :-) there's also a button on each webpage to edit that specific markdown doc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants