Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 5 of 5

Thread: Issues with translucency (blending)

  1. #1
    Junior Member Newbie
    Join Date
    Feb 2013
    Posts
    28

    Issues with translucency (blending)

    Hi.

    I've followed the advice from:

    https://home.comcast.net/~tom_forsyth/blog.wiki.html#[[Premultiplied%20alpha]]

    edit: sorry, forum software breaks link - it really does have square brackets in the URI

    I've developed a renderer that uses premultiplied alpha throughout (all textures are
    premultiplied, and the output of the renderer itself is a premultiplied alpha image in
    a framebuffer). The renderer works by first clearing the framebuffer to (0, 0, 0, 0), then
    rendering all opaque objects in any order (using the depth buffer to prevent overdraw),
    and then rendering all translucent objects from furthest to nearest. I don't think there's
    anything controversial there other than maybe that it produces an image that has
    translucent regions, because the result is intended for use in further compositing down
    the line, whereas I imagine most renderers produce a completely opaque image (and
    so typically clear to (0,0,0,1) or some other opaque background color).

    I'm having issues when it comes to rendering translucent objects.

    The renderer uses standard and unsurprising multipass lighting. Here's an image of
    an opaque object rendered with five lights (one large white light is offscreen):



    This is rendered in the usual style: The square in the middle is rendered five times,
    once with each light, with the contributions from each light being summed with additive blending.
    Basically:

    Code :
    glBlendFunc(GL_ONE, GL_ONE);
     
    for (o : objects) {
      for (l : lights) {
        render(o, l);
      }
    }

    However, and this is taken directly from the blog post above, for translucent
    lighting, one needs to set a different blending mode for the first light, but then
    switch back to additive blending for the rest. So, essentially:

    Code :
    for (o : objects) {
     
      boolean first = true;
      for (l : lights) {
        if (first) {
          glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        } else {
          glBlendFunc(GL_ONE, GL_ONE);
        }
     
        render(o, l);
        first = false;
      }
    }

    This does appear to give roughly the right results, except that for some
    reason, I have to perform premultiplication on the actual resulting
    fragment color produced by the shader. That is, I have to do:

    Code :
      out_rgba = vec4(lit.xyz * albedo.w, albedo.w);

    ... where out_rgba is my fragment shader's output, lit is the
    final color of the surface with lighting applied, and albedo is the
    surface albedo (either sampled from a premultipled texture, or specified
    as a premultiplied color via a uniform, etc). Otherwise, the shaders used
    for translucent objects are character-for-character identical to their opaque
    equivalents (the shaders are generated, and differ only in the final line that
    performs the premultiplication).

    Here's what happens when rendering the above object as a translucent without
    performing the premultiplication in the shader (note the excessive brightness):



    ... and here's what happens when I do perform the premultiplication
    in the shader:



    ... which is more like what I'd expect to see and seems almost pixel identical
    other than the fact that the object is (deliberately) slightly translucent.

    My question is: Why do I have to perform this extra step? It seems silly to have to
    have "translucent" variants of all of the existing shaders when they're otherwise
    identical except for the final line. Is it possible to get the blending hardware to do
    this step for me?

  2. #2
    Junior Member Newbie
    Join Date
    Feb 2013
    Posts
    28
    To clarify a little, the current opaque shaders produce a fragment color with:

    Code :
      out_rgba = vec4(lit.xyz, 1.0);

    ... and the translucent shaders do exactly the same for the rest of the code
    except they produce a final fragment color with:

    Code :
      out_rgba = vec4(lit.xyz * albedo.w, albedo.w);

    In an ideal world, I'd run the same shader in both the opaque and translucent
    cases and produce a fragment color with:

    Code :
      out_rgba = vec4 (lit.xyz, albedo.w);

    ... and the blending hardware would be configured such that:

    1. I get simple
      additive blending in the opaque case, with the value in the alpha channel
      of the fragment set to 1.0 so that light contributions are summed and
      objects are fully opaque.
    2. I get the result that I already get by manually premultiplying in the translucent
      case, but without having to do that multiplication myself.


    ... Is this even possible?

  3. #3
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Posts
    788
    Maybe I'm not understanding the issue correctly, but it seems to me that you want GL_SRC_ALPHA as source blend factor, i.e glBlendFunc(GL_SRC_ALPHA, GL_ONE); or perhaps make use of glBlendFuncSeparate/glBlendEquationSeparate to have the alpha channel treated specially (since you want the image to be blended itself).

  4. #4
    Junior Member Newbie
    Join Date
    Feb 2013
    Posts
    28
    Quote Originally Posted by carsten neumann View Post
    it seems to me that you want GL_SRC_ALPHA as source blend factor, i.e glBlendFunc(GL_SRC_ALPHA, GL_ONE)
    For the first light pass when rendering a translucent object?

    I'll give it a go.

  5. #5
    Junior Member Newbie
    Join Date
    Feb 2013
    Posts
    28
    Hm, no... That seems to make the resulting image light-order dependent (if you render lights A B C, you get a different result than if you'd rendered C B A). Because the renderer doesn't (and can't) guarantee the order of lights, it results in flickering.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •