简体   繁体   中英

Alpha blending of black visibly goes through white color

I'm trying to fade out an object of the scene, but I noticed it fades first gaining value nearly to white, before disappearing due to alpha channel being 0.

For a test, I set a square that's entirely black (0, 0, 0) and then linearly interpolate alpha channel from 1 to 0.

[1]:https://i.stack.imgur.com/fujcZ.png

This is the rectangle.

在此处输入图像描述

Same rectangle but when alpha value is 0.1 that is vec4(0, 0, 0, 0.1) . It's brighter than the background itself.

Blending mode used: gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

As far as I understand this mode should just lerp between the background pixel and the newly created source pixel. I just don't see any angle where the output pixel becomes brighter, when mixing anything with (0,0,0).


EDIT: After doing some testing I feel I need to clarify a few more things.

This is WebGL, and I'm drawing into a canvas on a website. I don't know how it works but it looks as if every draw call gl.drawElements() was drawn to a separate buffer and possibly later on composited into a single image. When debugging I can see my square drawn into an entirely white buffer, this is where the colour might come from.

But this means that blending doesn't happen with the backbuffer, but some buffer I didn't know existed. How do I blend into the back buffer? Do I have to avoid browser composition by rendering to a texture and only then drawing it to the canvas?


EDIT 2: I managed to get the expected result by setting separate blending for alpha and colour as follows: gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE);

But I'd rather leave this question open hoping that someone could clarify why it didn't work in the first place.

Issue is very well described here: https://stackoverflow.com/a/35459524/9956631

My color was blended with Canvas background. As I understand, it overwrites alpha, so you leave a seethrough part of canvas where your mesh is. So why my blendFuncSeparate() fixed the issue is because I was leaving DST alpha intact.

To turn it off, you can disable alpha when fetching the glContext. To get OpenGL-like rendering you should also disable premultipliedAlpha:

canvas.getContext('webgl', 
{
    premultipliedAlpha: false,
    alpha: false
})!;

Edit: To make sure my assumption is right, I set a test. behind the canvas I've placed a label. Then, on top of that I draw my canvas, with my (0, 0, 0, 0.5) color square on top. Just like this:

<label style="
    position: absolute;
    width: 400px;
    height: 400px;
    top:445px;
    left:500px;
    z-index: -1; // Behind...
    font-size: 80px;">LMAO</label>
<canvas id="glCanvas" style="z-index: 2;" width="1200" height="1200"></canvas>

As you can see, label is visible where the square is rendered. So this means, it is being blended with what's behind the canvas instead of current contents of the canvas (as one might assume). 在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM