Search code examples
opengltexturesalphaalphablendingblending

mix RGBA pixmap with texture


I have a RGBA pixmap (e.g. an antialiased circular 4x4 dot) that I want to draw over a texture in a way similar to a brush stroke. The obvious solution of using glTexSubImage2D just overwrites a rectangular area with no respect to alpha value. Is there a better solution than the obvious maintaining a mirrored version of the texture in local RAM, doing a blending there and then using glTexSubImage2D to upload it - preferrably OpenGL/GPU based one? Is FBO the way to go?

Also, is using FBO for this efficient both in terms of maintaining 1:1 graphics quality (no artifacts, interpolation etc) and in terms of speed? With 4x4 object in RAM doing a CPU blending is basically transforming 4x4 matrix with basic float arithmetics, totalling to 16 simple math iterations & 1 glTexSubImage2D call... is setting an FBO, switching rendering contexts & doing the rendering still faster?

Benchmarking data would be very appreciated, as well as MVCEs/pseudocode for proposed solutions.

Note: creating separate alpha-blended quads for each stroke is not an option, mainly due to very high amount of strokes used. Go science!


Solution

  • You can render to a texture with a framebuffer object (FBO).

    At the start of your program, create an FBO and attach the texture to it. Whenever you need to draw a stroke, bind the FBO and draw the stroke as if you were drawing it to the screen (with triangles). The stroke gets written to the attached texture.

    For your main draw loop, unbind the FBO, bind the attached texture, and draw a quad over the entire screen (from -1,-1 to 1,1 without using any matrices).


    Also, is using FBO for this efficient both in terms of maintaining 1:1 graphics quality (no artifacts, interpolation etc) and in terms of speed?

    Yes.

    • If the attached texture is as big as the window, then there are no artifacts.
    • You only need to switch to the FBO when adding a new stroke, after which you can forget about the stroke since it's already rendered to the texture.
    • The GPU does all of the sampling, interpolation, blending, etc., and it's much better at it than the CPU (after all, it's what the GPU is designed for)
    • Switching FBO's isn't that expensive. Modern games can switch FBOs for render-to-texture several times a frame while still pumping out thousands of triangles; One FBO switch per frame isn't going to kill a 2D app, even on a mobile platform.