简体   繁体   中英

glBlendFunc and alpha blending

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, eg 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);

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM