Artifacts in HDR Particle Shader

Hi, I tweaked the AddSmooth Particle Shader script a while ago, so that it also accepted a DiffuseMultiplier parameter to obtain shining particles when using glow postFXs.

I recently realised that if I push the parameter over 2-3 units, the colors start to act weird. Like there was some kind of overflow.

I also changed all color variables to float4.

All works fine in LDR,

but when I check HDR on the camera some artifacts show up.

It doesn’t depend on the bloomFX, I only used it to show the impact of the diffuse boost on the image. The artifacts appear also without any postFX applied on the camera.

The shader is pretty simple, but I can’t understand what I’m doing wrong.

Could you please help me?

Thanks for your time :slight_smile:

Here’s the shader. I didn’t change much from the builtin shader.
The double multiplication at the end of the alpha value has been done to recover the alpha value and give it a more subtle effect.

Shader "NeatWolf/Additive (Soft) HDR" {
Properties {
    _MainTex ("Particle Texture", 2D) = "white" {}
    _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
    _DiffuseBoost ("Diffuse Boost", Float) = 1.0
}

Category {
    Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    Blend One OneMinusSrcColor
    ColorMask RGB
    Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }

    SubShader {
        Pass {
    
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_particles

            #include "UnityCG.cginc"

            sampler2D _MainTex;
            fixed4 _TintColor;
            float _DiffuseBoost;
        
            struct appdata_t {
                float4 vertex : POSITION;
                float4 color : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 vertex : SV_POSITION;
                float4 color : COLOR;
                float2 texcoord : TEXCOORD0;
                #ifdef SOFTPARTICLES_ON
                float4 projPos : TEXCOORD1;
                #endif
            };

            float4 _MainTex_ST;
        
            v2f vert (appdata_t v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                #ifdef SOFTPARTICLES_ON
                o.projPos = ComputeScreenPos (o.vertex);
                COMPUTE_EYEDEPTH(o.projPos.z);
                #endif
                o.color = v.color;
                o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }

            sampler2D_float _CameraDepthTexture;
            float _InvFade;
        
            float4 frag (v2f i) : SV_Target
            {
                #ifdef SOFTPARTICLES_ON
                float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
                float partZ = i.projPos.z;
                float fade = saturate (_InvFade * (sceneZ-partZ));
                i.color.a *= fade;
                #endif
            
                float4 prev = i.color * tex2D(_MainTex, i.texcoord);
                prev.rgb *= prev.a * _DiffuseBoost * prev.a;
                return prev;
            }
            ENDCG
        }
    }
}
}

The blending is set to One OneMinusSrcColor, which is not very HDR ready. So, source being the pixel you render and destination the pixel already in the backbuffer, the blending operation is:

source + (1 - source) * destination

If the source (current output) color is above 1, it will place a negative multiplier on the original color in the backbuffer. I would either try Blend One One or Blend One OneMinusSrcAlpha. In the last case you can control the amount of background visible using the alpha.

1 Like

Yes! that was the problem!

Blend One One did the trick!

Thank you! :slight_smile: