[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Premultiplied alpha blending and issues with color accuracy



You can use any number of texture units you like (up to MAX_TEXTURE_IMAGE_UNITS).

I've been doing image manipulation and have had to do the blending myself in most cases for the same reasons you've described. It's annoying, as it often requires excessive ping-ponging of render-targets (you cannot read from/write to the same texture) and can slow things down considerably if your pipeline is long. But unfortunately it's the way things are -- unless you write an on-the-fly shader compiler (and deal with all the performance issues that has).

Unless someone else proves you and me wrong ;)

On Fri, May 11, 2012 at 4:18 PM, Thor Harald Johansen <thj@thj.no> wrote:

So I'm working on a prototype of Sketcher, as mentioned in previous posts, and I think I might've run up against a major roadblock when it comes to alpha blending.

I'm superimposing many brush images onto a texture. The images are generated by a fragment shader. I had my pipeline set up for premultiplied alpha earlier, since this was easy to work with, but with only 8 bits per channel to work with, color accuracy was visibly suffering, so I switched to unpremultiplied alpha, and saw immediate improvement.

I now run into a problem, and it's a classic one: I cannot find a way of making blendFuncSeparate() take both source and destination alpha into account for the color. This is a problem because the color underneath the alpha matte on my destination layer is bleeding through the soft edges of the brush.

Some Googling reveals that there is an extension, OES_texture_float, which would provide enough accuracy for premultiplied alpha, but there are some problems with this approach:

- not supported on every OpenGL ES implementation
- support for float texture FBOs is optional
- increased texture footprint

Something tells me that it would typically be mobile devices that would not support the extension, and of those that do, most would not support writing to the texture, and I'm guessing that support is not universal even on desktop computers.

In the Java version of Sketcher, I did alpha blending as follows:

       dA = dA + sA * (1 - dA)
       dC = dC + (sC - dC) * sA / dA

These are serial calculations, so dA in the 2nd equation refers to the final destination alpha, i.e. result of the 1st equation.

The 1st equation is a sort of cumulative alpha blend which interpolates between the destination and 1.0 using the source, so that compositing 0.5 over 0.5 gets you 0.75.

This was easily implemented in WebGL using:

       glBlendFuncSeparate(?, ?, gl.ONE_MINUS_DST_ALPHA, gl.ONE);

The 2nd equation interpolates between the destination and source color using the source alpha, but with the twist of dividing the source alpha by the final destination alpha first.

It's been too long since I worked these equations out, so I don't really understand why the 2nd equation works, except that the result never overflows, granted that I use fixed point arithmetic and a special case for divide by 0.

It's not critical that the WebGL version of Sketcher mixes colors in the same way, but if I'm going to do this with unpremultiplied alpha, the equation will need to take both source and destination alpha into account to avoid the color bleeding.

I tried to look into using multi-textures and a shader to do my own blending, but it would seem that I'm only allowed to use a single texture unit at any given point, and I need 2 to do blending.

It would seem that my problem is impossible to solve with the available tools. I hope that someone can prove me wrong.

Thor

-----------------------------------------------------------
You are currently subscribed to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email:
unsubscribe public_webgl
-----------------------------------------------------------