0

I'm writing a application where a user is allowed to toggle between different shaders, and combinations of them. Thus i want to draw the exact same scene a multiple time.

In the end, all the passes should be combined into one single output. To combine all the passes i thought about using glblendfunc, but i dont get the result I want to have.

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//use first shader
draw();
if (secondShaderWished) {
    //use second shader
    draw()
}

In each draw call i draw a texture which does have alpha values, e.g. transparent regions. The Endresult i get is that I see mainly the effect of the last render pass, but on the boundary (where the alpha-values slightly drop off) I do see the first shader effects. What I do think is that i should use a second glBlendFunc which allows to blend the two passes, but I cant think of a way to not touch any of the alpha values, which would destroy the wished effect.

What should I do? Is there something else then alphablending?

Edit: My goal is to combine one or more passes. I want to mix the colors (most probably adding them together), wehereas the color in each path is calculated via the following blending function across different layers: glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)

EDIT: Hi again! I'm working on this problem but I get stuck. I dont understand how i can properly set the sampler2d in any shader... What am I doing wrong?

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _FBO)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _Tex);
glViewport(0, 0, viewportSize.x(), viewportSize.y());
draw();
GLuint texLocation = glGetUniformLocation(_shader->getProgramID(),"pass0");
glUniform1i(texLocation, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
Donny
  • 549
  • 2
  • 10
  • 24
  • So do you want the result to be just the average of both render passes? – Christian Rau Sep 06 '11 at 18:00
  • Try to work out the specific color mathematics of what exactly you want to have happen, then edit your post to include that. – Nicol Bolas Sep 06 '11 at 19:53
  • Yes I do want the result to be the average of both render passes! Further in each render pass I want to be able to draw as many layers as necessary until the user is confident with what he got. Thus I do have multiple passes with multiple layers. Therefore I need the alpha values as blend factor. At least in each pass! – Donny Sep 07 '11 at 06:26
  • i just created another question here on stackoverflow which may be better suited to be answered than the again edited question here, which does not have much to do with the original question anymore.... http://stackoverflow.com/questions/7357626/framebuffer-and-using-shaders-in-opengl – Donny Sep 09 '11 at 05:53

2 Answers2

1

Due to your comment, you could just render each pass indivually into a texture (best done using FBOs), using your needed blend function. Then you can blend the different passes together in a single pass by just drawing a screen-sized quad and averaging all the passes's textures together in the fragment shader.

EDIT: According to your comment. You render these passes individually directly into a texture (that is bound as an FBO attachment) each. Then you use a fragment shader like this one with a screen-sized quad, assuming you have three passes:

uniform sampler2D pass0;
uniform sampler2D pass1;
uniform sampler2D pass3;
uniform vec2 screenSize;

void main()
{
    vec2 texCoord = gl_FragCoord.xy / screenSize;
    gl_FragColor = (1.0/3.0) * (texture2d(pass0, texCoord) + 
                                texture2d(pass1, texCoord) + 
                                texture2d(pass2, texCoord));
}

EDIT: Alternatively you can use a simple 1-texture fragment shader (that just looks up a color from a single texture and puts it out) and draw multiple textured quads using Tobias's blending configuration. This may also scale better if the number of passes is not known a-priori.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
  • hi there, started to think about what your answer means I came up with the idea of using renderbuffers instead of textures. Thus meaning i set up a new framebufferobject and generate a renderbuffer for each pass. What I'm trying to do now is to draw into these renderbuffers? does this even work? Once i have done that, how would i average over all the renderbuffers/textures? do you have any examples/tutorials on how to use a fragment shader with multiple texture inputs? – Donny Sep 07 '11 at 17:43
  • @Donny Basically yes, but instead of renderbuffers as FBO attachments, use textures, like I said. So you can render directly into the texture and don't need to retrieve the image from the renderbuffer. Then in the final pass's fragment shader just use multiple `sampler2D` uniforms (to which the textures are bound, that you just have written to), access them by the same texture coordinate (probably the pixel's screen coordinate) and then average these values together to produce the final color. – Christian Rau Sep 07 '11 at 17:50
0

I think you don't want to use the alpha-values of the textures as a blend factor but rather a constant factor that gives you a 1:1 blending.

You have to distribute the blending factors on all texture layers. So a white pixel on all textures would add up to exactly 1.

float factor = 1.0f / numTextures;
glBlendColor(factor, factor, factor, factor);
glBlendFunc(GL_CONSTANT_COLOR, GL_ONE);

For 3 layers that would become:

             source        dest
1st pass: (tex1 * 1/3) + (0 * 1)
2nd pass: (tex2 * 1/3) + (tex1 * 1/3 * 1)
3rd pass: (tex3 * 1/3) + ((tex2 * 1/3 + tex1 * 1/3) * 1)

Also remember that alpha-blending is an order-dependent operation.

Tobias Schlegel
  • 3,970
  • 18
  • 22
  • See my comment from above, I do need the alpha-values as a blend factor. What I am trying to do right now is drawing in the same texture all the time. What would be the use of having multiple textures at hand, and use one for every pass? – Donny Sep 07 '11 at 06:30