GIMP Brush Blending

Started by
6 comments, last by EVIL_ENT 12 years, 9 months ago
I've got a line texture with soft edges.
If I render two of these lines above each other using
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
there's too much alpha where the lines are intersecting.

My blend function should do something like this:
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

So I could render the single brush strokes on a framebuffer object.
Next I could blend all these layers with glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);.

In the end it should look like in this video:
[media]
[/media]

I've found several functions which work with alpha which are:
glBlendEquation
glBlendEquationSeparate
glBlendFunc
glBlendFuncSeparate
glAlphaFunc

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.
Advertisement
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.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
If you don't want to see one quad underneath the other, why are you using blending?
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.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.


If you don't want to see one quad underneath the other, why are you using blending?


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.


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.


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

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


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?
Only one way to find out - try it. I can't see it being a problem, depends what hardware your targetting though.

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.

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
*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:
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);

Main window:
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

This topic is closed to new replies.

Advertisement