<p>You seem to be using additive blending against its purpose. Additive blending is supposed to represent light from multiple sources being combined. It is not physically possible for one source of light to eclipse another.</p>

<p>Furthermore, even if you hack an alpha of exactly 1 to mean "opaque", you will get a strange circumstance where an alpha of 0.99 is quite far from "nearly opaque". So if you're animating "opacity", then you're going to get a sudden jump from appearing to be transparent to completely opaque.</p>

<p>Lastly, opacity with blending can <em>only</em> be achieved if you render the objects in the correct <em>order</em>. So even if you use this hack on the pink square, it will only eclipse the sphere if the sphere is rendered before the square. Using this hack will lose you the order-independency of additive blending.</p>

<p>That last part makes what you want essentially impossible.</p>

<p>However, if you wish to persist in this, there is a way to do what you've asked for. You need to use <a href="https://www.khronos.org/opengl/wiki/Dual_Source_Blending" rel="nofollow noreferrer">dual-source blending</a> (which means you can only be rendering to a single render target). This is a technique whereby you output two values from the FS to the same render target:</p>

<pre><code>layout(location = 0, index = 0) out vec4 outputColor0;
layout(location = 0, index = 1) out vec4 outputColor1;
</code></pre>

<p>Both values can be used in the blending equation. This means there are two source colors. The <code>index</code> zero source color is the source color used directly in the additive blending equation. The <code>index</code> one source color is how you turn off the destination color and achieve opacity:</p>

<pre><code>glBlendFunci(0, GL_ONE,  GL_SRC1_ALPHA);
</code></pre>

<p>With this blend function, if you want a fragment shader's output to be opaque, you set <code>outputColor1.a</code> to 0. Otherwise you set it to 1. The other components are irrelevant.</p>

<p>Of course, you must still suffer the limitations of dual-source blending. Namely, that you can only render to a single render target on most hardware.</p>

CC BY-SA 3.0
2018-02-19T11:34:11.413Z
That is correct, plus the additive blending blends (RGB * A, A) * Weight. I don't know how dual source blending works I'll investigate it, it seems interesting! But on the other hand I need to two different render targets: accumulation (vec4: RGBA16F) and revelage (float)
recp
CC BY-SA 3.0
2018-02-19T11:41:48.593Z
Maybe I can use three render targets (the first two for dual-source blending and last one for revelage), in the first pass dual-source is disabled and in other pass it is enabled (full screen quad), then compositing all passes? This would add extra pass only for dual-source blending but if it will fix the artifact I will implement it
recp
CC BY-SA 3.0
2018-02-18T23:16:46.410Z
2018-02-18T23:16:46.410Z
Nicol Bolas
<p>I'm rendering transparent objects in separate framebuffer then compositing it with opaque one to get final image. </p>

<p>The transparent pass has additive blending:</p>

<pre><code>glBlendFunci(0, GL_ONE,  GL_ONE);
</code></pre>

<p>so transpareny seems work perfect (I used weighted, blended OIT). Now I have problem if I set all surfaces' alpha to <strong>1</strong>. Transparency works if alpha is between 0 and &lt; 1 but not work as expected if alpha = 1. In this case (alpha=1) transparency surface seems opaque on opaque surface[s], but it also appears as semi-transparent on transparent surface[s].</p>

<p>I think additive blending causes this issue/artifact, how can I fix this? I want to transparent surfaces appear opaque if alpha is set to 1 in fragment shader. I can't disable blending because it will disable whole transparency process. </p>

<p>What I want to do is control blending in fragment shader or per-fragment blending; is this possible? Overriding old values of some fragments in framebuff e.g. to zero (0,0,0,0) could also help to fix/control blending, because I can put some values in blend equation to get what I want. </p>

<p>I'm asking this because maybe there is a way to simulate this which I don't know yet. Maybe I can fix this with another rendering passes/targets, I will give a try, any help would be appreciated  </p>

<p>EDIT:</p>

<p>The first image is rendered with alpha = 0.5 and the second one is rendered with alpha = 1.0. As you can see transparency is still active among transparent objects. The pink plane overrides Suzanne mesh and bottom plane but not sphere :( Both sphere and pink plane are rendered in transparency pass.</p>

<p><a href="https://i.sstatic.net/c2uGw.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/c2uGw.png" alt="Alpha = 0.5"></a>
<a href="https://i.sstatic.net/Wa8Kq.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Wa8Kq.png" alt="Alpha = 1.0"></a></p>

CC BY-SA 3.0
2018-02-18T18:52:39.997Z
Can you post an image showing what you mean?
user1118321
CC BY-SA 3.0
2018-02-18T19:18:35.753Z
@user1118321 sure, I updated question and added images
recp
CC BY-SA 3.0
2018-02-18T20:42:37.693Z
@recp: Additive blending is not transparency. The math simply doesn't work out that way.
Nicol Bolas
CC BY-SA 3.0
2018-02-18T20:47:36.217Z
@NicolBolas thanks for your comments; yep additive blending itself is not transparency but weighted, blended OIT algorithm requires additive blending ONE, ONE. I'm using GL_ONE_MINUS_SRC_ALPHA/GL_SRC_ALPHA in compositing pass
recp
CC BY-SA 3.0
2018-02-18T20:50:31.607Z
I want to disable additive blending ( or additive blending LOOK ) in shader if alpha is 1. I want to do this for specific fragments/pixels, this is why I want to do it in shader ( or with helper framebuffs / buffs ... )
recp
CC BY-SA 3.0
2018-02-18T23:07:44.283Z
@recp: My overall point is that you're doing the wrong thing. It's as wrong as taking 2 seconds and multiplying it by 3 seconds and saying that you have a velocity of 6 m/s. You're not getting the right look because you're using the math incorrectly. Additive blending has a meaning, and if it's not doing what you want, then you're not using it correctly. Simply having an alpha of 1 mean "opaque" won't help you. After all, an alpha of 0.99 won't be "nearly opaque", so it's going to look wrong if it suddenly jumps to "opaque".
Nicol Bolas
<opengl><transparency><fragment-shader><blending>
Is it possible to override or disable blending per pixel
recp
# Is it possible to override or disable blending per pixel

(Asked by: username_0 on 2018-02-18)

I'm rendering transparent objects in separate framebuffer then compositing it with opaque one to get final image.

The transparent pass has additive blending:

```
glBlendFunci(0, GL_ONE,  GL_ONE);

```

so transpareny seems work perfect (I used weighted, blended OIT). Now I have problem if I set all surfaces' alpha to **1**. Transparency works if alpha is between 0 and < 1 but not work as expected if alpha = 1. In this case (alpha=1) transparency surface seems opaque on opaque surface[s], but it also appears as semi-transparent on transparent surface[s].

I think additive blending causes this issue/artifact, how can I fix this? I want to transparent surfaces appear opaque if alpha is set to 1 in fragment shader. I can't disable blending because it will disable whole transparency process.

What I want to do is control blending in fragment shader or per-fragment blending; is this possible? Overriding old values of some fragments in framebuff e.g. to zero (0,0,0,0) could also help to fix/control blending, because I can put some values in blend equation to get what I want.

I'm asking this because maybe there is a way to simulate this which I don't know yet. Maybe I can fix this with another rendering passes/targets, I will give a try, any help would be appreciated

EDIT:

The first image is rendered with alpha = 0.5 and the second one is rendered with alpha = 1.0. As you can see transparency is still active among transparent objects. The pink plane overrides Suzanne mesh and bottom plane but not sphere :( Both sphere and pink plane are rendered in transparency pass.

[![Alpha = 0.5](https://i.sstatic.net/c2uGw.png)](https://i.sstatic.net/c2uGw.png)
[![Alpha = 1.0](https://i.sstatic.net/Wa8Kq.png)](https://i.sstatic.net/Wa8Kq.png)

**Tags:** opengl, transparency, fragment-shader, blending

> **Comments:**
> **username_1**: Can you post an image showing what you mean?  
> **username_0**: @username_1 sure, I updated question and added images  
> **username_2**: @username_0: Additive blending is not transparency. The math simply doesn't work out that way.  
> **username_0**: @username_2 thanks for your comments; yep additive blending itself is not transparency but weighted, blended OIT algorithm requires additive blending ONE, ONE. I'm using GL_ONE_MINUS_SRC_ALPHA/GL_SRC_ALPHA in compositing pass  
> **username_0**: I want to disable additive blending ( or additive blending LOOK ) in shader if alpha is 1. I want to do this for specific fragments/pixels, this is why I want to do it in shader ( or with helper framebuffs / buffs ... )  
> **username_2**: @username_0: My overall point is that you're doing the wrong thing. It's as wrong as taking 2 seconds and multiplying it by 3 seconds and saying that you have a velocity of 6 m/s. You're not getting the right look because you're using the math incorrectly. Additive blending has a meaning, and if it's not doing what you want, then you're not using it correctly. Simply having an alpha of 1 mean "opaque" won't help you. After all, an alpha of 0.99 won't be "nearly opaque", so it's going to look wrong if it suddenly jumps to "opaque".  

---

## 1 answers

### Answer by username_2 on 2018-02-18. Score: 2

You seem to be using additive blending against its purpose. Additive blending is supposed to represent light from multiple sources being combined. It is not physically possible for one source of light to eclipse another.

Furthermore, even if you hack an alpha of exactly 1 to mean "opaque", you will get a strange circumstance where an alpha of 0.99 is quite far from "nearly opaque". So if you're animating "opacity", then you're going to get a sudden jump from appearing to be transparent to completely opaque.

Lastly, opacity with blending can *only* be achieved if you render the objects in the correct *order*. So even if you use this hack on the pink square, it will only eclipse the sphere if the sphere is rendered before the square. Using this hack will lose you the order-independency of additive blending.

That last part makes what you want essentially impossible.

However, if you wish to persist in this, there is a way to do what you've asked for. You need to use [dual-source blending](https://www.khronos.org/opengl/wiki/Dual_Source_Blending) (which means you can only be rendering to a single render target). This is a technique whereby you output two values from the FS to the same render target:

```
layout(location = 0, index = 0) out vec4 outputColor0;
layout(location = 0, index = 1) out vec4 outputColor1;

```

Both values can be used in the blending equation. This means there are two source colors. The `index` zero source color is the source color used directly in the additive blending equation. The `index` one source color is how you turn off the destination color and achieve opacity:

```
glBlendFunci(0, GL_ONE,  GL_SRC1_ALPHA);

```

With this blend function, if you want a fragment shader's output to be opaque, you set `outputColor1.a` to 0. Otherwise you set it to 1. The other components are irrelevant.

Of course, you must still suffer the limitations of dual-source blending. Namely, that you can only render to a single render target on most hardware.

> **Comments:**
> **username_0**: That is correct, plus the additive blending blends (RGB * A, A) * Weight. I don't know how dual source blending works I'll investigate it, it seems interesting! But on the other hand I need to two different render targets: accumulation (vec4: RGBA16F) and revelage (float)  
> **username_0**: Maybe I can use three render targets (the first two for dual-source blending and last one for revelage), in the first pass dual-source is disabled and in other pass it is enabled (full screen quad), then compositing all passes? This would add extra pass only for dual-source blending but if it will fix the artifact I will implement it  

---

