Sign in to follow this  
EVIL_ENT

OpenGL GIMP Brush Blending

Recommended Posts

I've got a line texture with soft edges.
If I render two of these lines above each other using
[code]glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);[/code]
there's too much alpha where the lines are intersecting.

My blend function should do something like this:
[code]new color = old color or brush color//does not really matter because both are the same
if (old alpha > brush alpha) new alpha = old alpha
else new alpha = brush alpha[/code]
So I could render the single brush strokes on a framebuffer object.
Next I could blend all these layers with [code]glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);[/code].

In the end it should look like in this video:
[media]http://www.youtube.com/watch?v=9JfbnnloTNM[/media]

I've found several functions which work with alpha which are:
[code]glBlendEquation
glBlendEquationSeparate
glBlendFunc
glBlendFuncSeparate
glAlphaFunc[/code]
but I got none of these to do what I want.
Test environment:
http://pastebin.com/HVPxtNa6

If it is possible with shaders some code would be very nice because I didn't work much with them yet.
Of course I could do this with the CPU and without OpenGL but that would be slower and I need it to be fast.

Share this post


Link to post
Share on other sites
What do you mean by stack.
The blend operation is just a mathematical operation. If you want some different mathematical operation, then just type here what you want.

From your right pic, it looks like you don't want blending.

Share this post


Link to post
Share on other sites
Paint it to a seperate layer, if pixel is not coloured then colour it with the paint value, otherwise do nothing (unless your brush has some falloff). You can render this layer over the top with alpha blending. Once you release the mouse then you apply the layer to the layer your actually trying to draw on. Its sort of doing the "big array" thing you didn't want but slightly differently. Blending alone won't solve your problem as the effect you have is blending, the effect you want is not blending (its logical). Sounds like your doing render to texture, just get 2 render targets. One you render to while the brush is down, once its released you render it onto the "canvas" target and clear it ready for the next time you start painting.

Share this post


Link to post
Share on other sites
[quote name='Hodgman' timestamp='1310214244' post='4833073']
If you don't want to see one quad underneath the other, why are you using blending?
[/quote]

I still want the blending.
Imagine a brush which is not solid but fades out smoothly.
As long as I press the left mouse button I can go over the same pixel as often as I want but it won't get higher alpha values.
But if I release the left mouse button and do the same again it is supposed to blend as usual.

[quote name='Nanoha' timestamp='1310216527' post='4833076']
Paint it to a seperate layer, if pixel is not coloured then colour it with the paint value, otherwise do nothing (unless your brush has some falloff). You can render this layer over the top with alpha blending. Once you release the mouse then you apply the layer to the layer your actually trying to draw on. Its sort of doing the "big array" thing you didn't want but slightly differently. Blending alone won't solve your problem as the effect you have is blending, the effect you want is not blending (its logical). Sounds like your doing render to texture, just get 2 render targets. One you render to while the brush is down, once its released you render it onto the "canvas" target and clear it ready for the next time you start painting.
[/quote]

I've just found a function called "glBlendEquation".
If I do this:

[CODE]glBlendEquation(GL_FUNC_ADD);
glColor4f(red, green, blue, 1.0);
//render brush
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glColor4f(0.0, 0.0, 0.0, 1.0-alpha);
//render quad which covers the whole screen
[/CODE]

I can limit what I am drawing to alpha because it can't go beyond 1.0 and after that I subtract everything.

Unfortunately this will also affect what has been drawn before so I have to save that first, render the brush, save the brush, restore the old stuff and blend the brush on top of it.
I guess this will be too slow if I make a few brushes so I don't think that I'll do it like that.

I remember reading that it is possible to render directly to textures so I could make a bunch of quads which blend as usual and render on the quads by subtracting the alpha.
I have not done this before so I don't know if this works as intended.
Maybe rendering to many textures will consume the same amount of memory or have a big impact on performance.

What would be the fastest way to render the single brush strokes and blend them onto each other?

edit:
Seems to be called "Frame Buffer Object".
So I would:
1. Create one of these
2. Render a brush stroke on it
3. Blend content of it over the main rendering context
4. Clear it
and repeat 2. - 4. (up to lets say 1000 times) until everything is drawn?
Would that still be possible with a nice framerate?

Share this post


Link to post
Share on other sites
Apparently I can do this:
-render a triangle on the fbo
-render the fbo to a quad in the window context
-render another triangle to the fbo
-render the fbo on another quad in the window context
and get a quad with 1 and another quad with 2 triangles although having the same texture, render buffer object, etc.
So I can save lots of everything :)
Also it is pretty fast.
It only takes 0.00005 seconds to switch contexts, clear, render and switching back on my laptop.
And if I need more speed for some reason I'll just make another fbo to buffer it.
Thanks everyone

Share this post


Link to post
Share on other sites
*Bump*
Unfortunately the blending still does not work.

Updated first post, clarified question, added a video and more images.

Edit:
After lots of trial and error I finally found something which looks like I want.
FBO:
[code]glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);[/code]
Main window:
[code]glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);[/code]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this