[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Public WebGL] Premultiplied alpha blending and issues with color accuracy
- To: email@example.com
- Subject: [Public WebGL] Premultiplied alpha blending and issues with color accuracy
- From: Thor Harald Johansen <firstname.lastname@example.org>
- Date: Fri, 11 May 2012 09:18:43 +0200
- List-id: Public WebGL Mailing List <public_webgl.khronos.org>
- Sender: email@example.com
- User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20120428 Thunderbird/12.0.1
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
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.
You are currently subscribed to firstname.lastname@example.org.
To unsubscribe, send an email to email@example.com with
the following command in the body of your email: