RGB values seem to be wrong when alpha less than 1.0?

For questions about using Classic.

Post » Tue Aug 24, 2010 2:30 pm

RGB values seem to be wrong when alpha less than 1.0?
===============================
I first noticed this when building a shader that would allow you to view channels in various ways. I was going to post this in the "Construct engineering" forum, but after closer inspection it seems that this odd issue originates from Construct itself rather than the effects system, so I figured I'd ask here.

I may be doing something wrong, but it really looks like the alpha channel somehow corrupts the image data in the R, G, and B channels.

Specifically it's as if, for each pixel, the alpha value is being multiplied into the R, G, and B values. If that's really what's going on, it means that image data is being destroyed, as the color depth resolution in the R, G, and B channels is discarded in the presence of non-1.0 alpha values.

To see an example of what I mean, using the Construct image editor, try loading and saving an image with 0 to 1 alpha gradient. You should see all the R, G, and B channel values clamped to black as alpha approaches 0, irrespective of what data was originally in the R, G, and B channels.

At any rate, if the alpha is really being multiplied into the data, the R, G, and B channel information can't be recovered. For example, dividing the RGB values by alpha will approximate the original colors, but with lots of ugly banding, quantizing, and aliasing as you near low alpha areas. The original data is definitely not recoverable from that.



This may also explain another kind of glitchy behavior I've seen in the image editor, namely, that the soft edged brushes paint a kind of dirty aliased range of colors rather than just the color you selected.

To see this effect for yourself, in the image editor, pick a gray-green color (or any other desaturated color) and fill the whole frame, now get a large soft edged brush and draw the same color in the center of the frame. Obviously you should not see anything change, because the whole frame is already the color you're trying to draw with. Instead however, you will get a grungy mess of various colors loosely similar to the selected color. I think this may be because of the alpha glitch I mentioned above, causing waves upon waves of compounding rounding errors. That's sure what it looks like anyway.



So, my question is, is this weird RGB behavior really what it looks like, and if so is there a work around that would allow the RGB values to remain in tack while at the same time using alpha?
Please let me know if this appears to be a real issue, or if I just overlooked something simple, or am missing a setting somewhere that resolves the odd alpha behavior mentioned above.
B
21
S
13
G
8
Posts: 306
Reputation: 5,458

Post » Tue Aug 24, 2010 5:22 pm

The method is called "premultiplied alpha" and is a standard in 3D (remember, Construct is based on DirectX). With this method the alpha is stored in the color channels when using rgb and stored in the color channels and the alpha channel with rgba.

There are advantages and disadvantages to both methods, but the most important advantage is the speed factor. Calculations are less complex and speed up the process and that is essential in 3D-environments.

You don't really lose precision, because you're working with relative values 0 to 1 in 32-bit-precision (The smallest representable number without losing precision is 1.401298464e-45). It's the picture model that may lose precision (e.g. 8-bit-colors).

The way you work with the colors in an effect is simple:
1) Calculate the alpha out of the rgb-channels before working on the color
[code:2apdu4tj]color.rgb /= color.a;[/code:2apdu4tj]
2) Work on the color

3) Calculate the alpha back in
[code:2apdu4tj]color.rgb *= color.a;[/code:2apdu4tj]

Here is a very good summary of premultiplied alpha
Image
B
23
S
8
G
10
Posts: 1,820
Reputation: 8,242

Post » Wed Aug 25, 2010 2:54 am

Okay, cool. I'm just glad I'm not going crazy. :)

I figured it might be a means of sidestepping the weighting calculations to get a performance gain. I ran into premultiplied alpha a while back using Maya. Granted, you can get away with disabling premultiplication for Maya, because Maya is by no means a real-time application.

It makes sense that Construct uses it to speed up compositing, since the name-of-the-game is flooding the screen with sprites, and 99.9% of those sprites will get drawn onto a fully opaque backdrop. Though actually what about transparent layers? Do they just force z-ordering, unless you tell them to render themselves as an intermediate texture?

Sadly though, it seems then that you can't store arbitrary alpha maps without irreparably degrading the image information in the RGB maps.

For example, the divide by alpha method you describe, is the same method I described in the 5th paragraph of my first post, and it's not capable of retrieving the original RGB values, because they have already been degraded by premultiplication, followed by quantization into the 8-bit color model. The best you can get is a quantized/depth-aliased approximation that gets less and less accurate as transparency increases. (Unless I'm thinking about this the wrong way, but I've already tried a number of different methods and it would appear that the original data really just isn't there to be retrieved.)

One of the reasons I was interested in getting at the original RGB image data is that I wanted to make a small painting application that could do gamma accurate color blending. For that I would need to have access to the unaltered RGB and alpha maps.

I can't really complain though, a lot of the cool things you can do with separated channels aren't really what Construct is designed for, so like everything it's a tradeoff. And I agree that in Construct's case premultiplied alpha is the way to go.

If there was a way to disable premultiplication for certain objects though, that might be nice, but understandably that probably won't be a priority any time soon. Even so, it might be worth looking into the problem with the Construct image editor (see 6th paragraph of first post).

That said, is there a way to use effects to apply a grayscale texture to an object as an alpha map? I know there's a "Mask" effect, but I'm not sure if you can set it up to punch through only the object one z-index behind it. It's seems like you couldn't, because any object one z-index lower would have already been flattened into the scene. Then again, I'm not that familiar with DirectX.
B
21
S
13
G
8
Posts: 306
Reputation: 5,458

Post » Sun Aug 29, 2010 3:34 am

I'm sorry, I totally forgot about this thread :oops:

Yes, you assume right. Within Construct's implementation of effects you have access to these four stages:
1) the original unaltered texture of the object the effect is applied to (=source)
2) the texture with all previous alterations from other effects in the object's effect chain (= foreground)
3) the texture of all graphical content that was already processed before the current object (= background)
4) the texture of the previous effect in the object's effect chain (=previous)

I never used 4), can't tell you exactly the difference to 2)
Image
B
23
S
8
G
10
Posts: 1,820
Reputation: 8,242


Return to Help & Support using Construct Classic

Who is online

Users browsing this forum: No registered users and 3 guests