<p>I managed to solve the problem by putting a saturate on the color input.</p>
<pre><code>float4 _BloomThreshold;
float _BloomIntensity;
float _BloomScattering;

float3 ApplyBloomThreshold(float3 color) {
    float brightness = Max3(color.r, color.g, color.b);
    float soft = brightness + _BloomThreshold.y;
    soft = clamp(soft, 0.0, _BloomThreshold.z);
    soft = soft * soft * _BloomThreshold.w;
    float contribution = max(soft, brightness - _BloomThreshold.x);
    contribution /= max(brightness, 0.00001);
    return color * contribution;
}

float4 PreFilter(Varyings i) : SV_TARGET{
    float3 color = pow(ApplyBloomThreshold(GetSource(i.fxUV).rgb),2);
    return float4(saturate(color), 1.0);
}
</code></pre>

CC BY-SA 4.0
2021-12-15T00:43:31.243Z
2021-12-15T00:43:31.243Z
Matheus Markies
<p>Good Morning!
I'm having trouble rendering an on-screen bloom shader by post processing.
Basically the shader works like this:</p>
<p>Camera image before rendering the effect:
<a href="https://i.sstatic.net/92lGr.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/92lGr.png" alt="enter image description here" /></a></p>
<p>First a filter is passed on the camera image to leave only one highlights.</p>
<p><a href="https://i.sstatic.net/10ED8.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/10ED8.png" alt="[ATTACH=full]964042[/ATTACH]" /></a></p>
<pre><code>float4 _BloomThreshold;
float _BloomIntensity;
float _BloomScattering;

float3 ApplyBloomThreshold(float3 color) {
    float brightness = Max3(color.r, color.g, color.b);
    float soft = brightness + _BloomThreshold.y;
    soft = clamp(soft, 0.0, _BloomThreshold.z);
    soft = soft * soft * _BloomThreshold.w;
    float contribution = max(soft, brightness - _BloomThreshold.x);
    contribution /= max(brightness, 0.00001);
    return color * contribution;
}

float4 PreFilter(Varyings i) : SV_TARGET{
    float3 color = pow(ApplyBloomThreshold(GetSource(i.fxUV).rgb),2);
    return float4(color, 1.0);
}
</code></pre>
<p>After that, the image goes through a downsample:</p>
<pre><code>float4 FragBox(Varyings i) : SV_Target
{
    return float4(SampleBox(i.fxUV),1);
}

static const float gaussian[14] = {
    0.00598,    0.060626,    0.241843,    0.383103,    0.241843,    0.060626,    0.00598,
    0.02400,    0.0160125,    0.741843,    0.455653,    0.296803,    0.189060,    0.18406
};

float4 FragHBlur(Varyings i) : SV_Target
{
    float4 color;
    float2 o = float2(GetSourceTexelSize().x, 0);
    for (int idx = -3; idx &lt;= 3; idx++) {
        float4 tColor = GetSource(i.fxUV + idx * o);
        color += tColor * gaussian[idx + 3];
    }
    return float4(color.rgb, 1 / _Levels);
}

float4 FragVBlur(Varyings i) : SV_Target
{
    float4 color;
    float2 o = float2(0, GetSourceTexelSize().y);
    for (int idx = -3; idx &lt;= 3; idx++) {
        float4 tColor = GetSource(i.fxUV + idx * o);
        color += tColor * gaussian[idx + 3];
    }
    return float4(color.rgb, 1 / _Levels);
}
</code></pre>
<p>This step occurs several times in the effect's rendering, with each of the images used from source having its dimensions shrunk.</p>
<p>After the image is blurred, it will be merged with the image from the previous frame, which was also blurred but has larger dimensions.
<a href="https://i.sstatic.net/i1HEm.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/i1HEm.png" alt="enter image description here" /></a></p>
<p>After merging all bloomed images, the final image is merged with the camera image before rendering the effect:</p>
<p><a href="https://youtu.be/upFOgWgLqXc" rel="nofollow noreferrer">https://youtu.be/upFOgWgLqXc</a></p>
<p>So far so good.</p>
<p><a href="https://youtu.be/2rJ7lS8DM5I" rel="nofollow noreferrer">https://youtu.be/2rJ7lS8DM5I</a></p>
<p>The problem is these black squares that sometimes appear when I move the camera.
Why are they there???</p>
<p><a href="https://i.sstatic.net/P6Qel.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/P6Qel.png" alt="enter image description here" /></a>
<a href="https://youtu.be/ralRa_-nqiU" rel="nofollow noreferrer">https://youtu.be/ralRa_-nqiU</a></p>
<p>The same problem happens in the lens flare shader, which uses the same downsample method:</p>
<p><a href="https://i.sstatic.net/D649n.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/D649n.png" alt="enter image description here" /></a></p>

CC BY-SA 4.0
2021-12-04T12:08:26.097Z
If your framebuffer contains incorrect float values like nans or infs, these are blurred (blur kernel is square) and this is the result.
mdkdy
CC BY-SA 4.0
2021-12-06T01:00:23.803Z
Thanks!
Fixed adding a saturate in the input.
Matheus Markies
<hlsl><unity>
Black squares in bloom effect
Matheus Markies
# Black squares in bloom effect

(Asked by: username_0 on 2021-12-01)

Good Morning!
I'm having trouble rendering an on-screen bloom shader by post processing.
Basically the shader works like this:

Camera image before rendering the effect:
[![enter image description here](https://i.sstatic.net/92lGr.png)](https://i.sstatic.net/92lGr.png)

First a filter is passed on the camera image to leave only one highlights.

[![[ATTACH=full]964042[/ATTACH]](https://i.sstatic.net/10ED8.png)](https://i.sstatic.net/10ED8.png)

```
float4 _BloomThreshold;
float _BloomIntensity;
float _BloomScattering;

float3 ApplyBloomThreshold(float3 color) {
    float brightness = Max3(color.r, color.g, color.b);
    float soft = brightness + _BloomThreshold.y;
    soft = clamp(soft, 0.0, _BloomThreshold.z);
    soft = soft * soft * _BloomThreshold.w;
    float contribution = max(soft, brightness - _BloomThreshold.x);
    contribution /= max(brightness, 0.00001);
    return color * contribution;
}

float4 PreFilter(Varyings i) : SV_TARGET{
    float3 color = pow(ApplyBloomThreshold(GetSource(i.fxUV).rgb),2);
    return float4(color, 1.0);
}

```

After that, the image goes through a downsample:

```
float4 FragBox(Varyings i) : SV_Target
{
    return float4(SampleBox(i.fxUV),1);
}

static const float gaussian[14] = {
    0.00598,    0.060626,    0.241843,    0.383103,    0.241843,    0.060626,    0.00598,
    0.02400,    0.0160125,    0.741843,    0.455653,    0.296803,    0.189060,    0.18406
};

float4 FragHBlur(Varyings i) : SV_Target
{
    float4 color;
    float2 o = float2(GetSourceTexelSize().x, 0);
    for (int idx = -3; idx <= 3; idx++) {
        float4 tColor = GetSource(i.fxUV + idx * o);
        color += tColor * gaussian[idx + 3];
    }
    return float4(color.rgb, 1 / _Levels);
}

float4 FragVBlur(Varyings i) : SV_Target
{
    float4 color;
    float2 o = float2(0, GetSourceTexelSize().y);
    for (int idx = -3; idx <= 3; idx++) {
        float4 tColor = GetSource(i.fxUV + idx * o);
        color += tColor * gaussian[idx + 3];
    }
    return float4(color.rgb, 1 / _Levels);
}

```

This step occurs several times in the effect's rendering, with each of the images used from source having its dimensions shrunk.

After the image is blurred, it will be merged with the image from the previous frame, which was also blurred but has larger dimensions.
[![enter image description here](https://i.sstatic.net/i1HEm.png)](https://i.sstatic.net/i1HEm.png)

After merging all bloomed images, the final image is merged with the camera image before rendering the effect:

<https://youtu.be/upFOgWgLqXc>

So far so good.

<https://youtu.be/2rJ7lS8DM5I>

The problem is these black squares that sometimes appear when I move the camera.
Why are they there???

[![enter image description here](https://i.sstatic.net/P6Qel.png)](https://i.sstatic.net/P6Qel.png)
<https://youtu.be/ralRa_-nqiU>

The same problem happens in the lens flare shader, which uses the same downsample method:

[![enter image description here](https://i.sstatic.net/D649n.png)](https://i.sstatic.net/D649n.png)

**Tags:** hlsl, unity

> **Comments:**
> **username_1**: If your framebuffer contains incorrect float values like nans or infs, these are blurred (blur kernel is square) and this is the result.  
> **username_0**: Thanks! Fixed adding a saturate in the input.  

---

## 1 answers

### Answer by username_0 on 2021-12-15. Score: 1 | Accepted answer

I managed to solve the problem by putting a saturate on the color input.

```
float4 _BloomThreshold;
float _BloomIntensity;
float _BloomScattering;

float3 ApplyBloomThreshold(float3 color) {
    float brightness = Max3(color.r, color.g, color.b);
    float soft = brightness + _BloomThreshold.y;
    soft = clamp(soft, 0.0, _BloomThreshold.z);
    soft = soft * soft * _BloomThreshold.w;
    float contribution = max(soft, brightness - _BloomThreshold.x);
    contribution /= max(brightness, 0.00001);
    return color * contribution;
}

float4 PreFilter(Varyings i) : SV_TARGET{
    float3 color = pow(ApplyBloomThreshold(GetSource(i.fxUV).rgb),2);
    return float4(saturate(color), 1.0);
}

```


---

