Alpha and scene clear color while taking a screenshot

Hello, I’m trying to create a screenshot of my scene which contains alpha blended materials. Normally my Babylon scene has a clear color of Color4(1,1,1,1). But I need to have my object separate in the image so I can overlay it later on top of other images.

Now when I take a screenshot the objects with alpha below 1, it gets faded when I set the clear color to a transparent Color4(1,1,1,0). Even though my default clear color is white normally and it visually looks the same. when I overlay this screenshot with the transparent clear color on top of for example a white background it doesn’t obtain the same color either as the opaque clear color screenshot.

Is it possible to get a screenshot with the same “opacity” as a scene with an opaque clear color?

A scene to demonstrate what I mean (change the indicated lines):

EDIT:
Setting it to Color4(0,0,0,0) seems to fix it. This makes little sense to me however, can someone explain this behaviour?

@Evgeni_Popov

(0,0,0,0) is the right color because of the alpha mode used, which is ALPHA_COMBINED (note that your code is doing mat.alphaMode = BABYLON.PBRMaterial.MATERIAL_ALPHABLEND, which is wrong, it should be mat.alphaMode = BABYLON.Constants.ALPHA_COMBINE, but it happens that MATERIAL_ALPHABLEND==ALPHA_COMBINE==2!).

ALPHA_COMBINE is computing the final color as SRC_ALPHA * SRC_COLOR + (1 - SRC_ALPHA) * DEST_COLOR

So, if you clear with (0,0,0,0), DEST_COLOR = (0,0,0) and the final color will only depend on SRC_COLOR. If you clear with (1,1,1,0), the final color will be a mix (depending on source alpha) of the source color and white.

2 Likes

I’ve noticed that if I use a clear color of (0,0,0,0), there tends to be a dark outline around my main model.
I can’t share the model but my scene is a model with a shadow.

If I do (1,1,1,0), the shadow is faded.
If I do (0,0,0,0), the shadow is correct but there is a dark outline around the main model (the transparent edges are very dark)

a scene to somewhat test it:
https://playground.babylonjs.com/#AMTLDQ#10

Is there any way to prevent this from happening, specifically around edges?

@Evgeni_Popov

You would need to turn antialiasing off on the engine but the drawback is that you will not have antialiasing at all in this case.

1 Like

I don’t really see much difference switching the antialiasing on or off.

I’ve made a better playground to show my results:
https://playground.babylonjs.com/#AMTLDQ#15

(0,0,0,0) → shadow visible, but an outline:
image

(1,1,1,0) → shadow faded away, no outline:
image

(1,1,1,1) → shadow visible, no outline, no transparency (I need transparency)
image

These example are made by putting the downloaded pngs in-front of a white background in photoshop btw. Maybe having the playground might help in finding a possible solution for this?

There would not be any “fade off” if you turn antialiasing of.

For the screenshot the samples should be 0 to turn it off: https://playground.babylonjs.com/#AMTLDQ#18

1 Like

This makes it look very jagged sadly enough, which won’t do either. Is there really no way to get a result like in my 3rd image, but then still having opacity instead of pure white?

AA works by Blending the background color and what you draw fading from one to the other so you need to clear with the correct background unfortunately.

Or you disable it and super sample (render 4 * bigger for intstance)

Is there a possibility to set a different color for the color blending of the anti-aliasing somehow?
Without messing up the regular color blending of the transparent textures, in this case the shadow.

only through the scene clearColor.

I ran into a generally different but probably very related issue.
I can’t get a screenshot of a babylonjs scene that contains transparency, but so that it looks the same when a white background is put behind it.

To demonstrate what I mean:
5Z2T9PV1

The screenshot that uses a white transparent clear color doesn’t look the same as a screenshot with an opaque white clear color, even when I put an opaque white background behind it. Is there any way to fix this so that I can get a png that would look the same at the first picture when put in front of a white background, while maintaining the transparency?

My playground:
https://playground.babylonjs.com/#AMTLDQ#19

This would be really hard to build.

Basically you want to only chose the final alpha without blending within babylon.

This could work by forcing an opaque mesh to render with an alpha value. but you would lose anything behing the mesh in your render.

Also aliasing might be pretty strong in this case.

1 Like

I don’t think this would work for my use case sadly enough. I’m really trying to recreate the current scene but as a picture, so if the objects behind other transparent objects aren’t seen through them it wouldn’t look the same anymore. Is there really no way to export the scene as an image before it blends with the clear color or something along that line?

Actually, I have nearly the same colors in both cases in Paint.net:

Circle (not shadow):

image

image

Middle of shadow:

image

image

Yeah it’s very similar, but still different. I also use this circle just as an example. I think in more complex scenes the color difference might be stronger, although that’s just an assumption. If there was a consistent way to “unblend” the colors in post, like with photoshop or imagemagick that might also fix the issue. I wouldn’t be against it, if that could solve my issue but that feels a bit backwards personally.

The difference between (255,116,116) and (255,117,117) is imperceptible, and has nothing to do with the difference shown in the screenshot you posted above:

The color in the middle of the left sphere is (255,128,128) and the color in the middle of the right sphere is (255,192,192). So, if you’ve generated the image of the right sphere from the PG, there’s something going on with the DCC tool you used to create the image above.

I’ve generated that image by creating screenshots with the PG I’ve provided. Then throwing those screenshots into Photoshop and putting a second, fully white layer behind them respectively. Then I took screenshot of the results and put them side by side.

Just to be sure I’ve just done the same in gimp and I got the same result.

Gimp

For comparison, these are the 2 files I generated through the playground (1 with opaque clear color(1,1,1,1), and 1 with transparent white clear color(1,1,1,0):

Opaque

Transparent

You can clearly see they’re quite different, so I’m not sure what I’m doing wrong then?

I tried with GIMP and I get the same results than with Paint.NET, the color is (255,129,129) in one case, and (255,128,128) in the other case.

However, I think the problem is with the value in the alpha channel. In the opaque case, the value is 255, whereas it is 127 in the other case. That’s because you set mat.alpha = 0.5. In the opaque case, the final alpha value is 255 because the source and destination alpha value is 255. In the (1,1,1,0) clear value case, the final alpha value is 127 because the source alpha is 255 and the destination alpha is 0.

So, at pixel level, everything seems to be ok to me (at least if you want to retain the alpha values in the alpha channel), it’s only that the DCC tools apply the alpha value over the existing (r,g,b) values, effectively applying it twice (because the rgb values generated in the file already take alpha into account). I think the DCC tools are right in that matter, because .png files don’t support pre-multiplied alpha, so they apply the alpha multiplication on the rgb values.

One way to make it work in your particular example is to use the ALPHA_ONEONE_ONEONE mode for alpha blend. In this mode, the final color is computed as color_src+color_dest and the final alpha as alpha_src+alpha_dest. So, by using a clear color of (0,0,0,0) you will get what you want:

However, it may not work in more complex scenes (you could try a different alpha blend mode and see if one works for you).