5
$\begingroup$

I am working on a 2D lighting system for my game. My approach has been to:

  1. Create a transparency quad representing 'darkness'.
  2. Create a stencil shader for light sources to clip from the darkness quad.
  3. Create a shader that blends alpha from 0 -> {darkness alpha} to soften the edges of the light source.

This looks like the following:

enter image description here

You can see the problem - the two light source shaders that soften the shadow edges are being blended like normal transparency layers should and causing the colour to intensify. Here is another image without the darkness quad, which might make things a bit clearer:

enter image description here

My question: Is there any sort of alpha blending I can do to make this intersection appear 'normal' i.e. it doesn't intensify the color? If not, is there another approach which could help with this?

Update:

Here is the shader code that generates the fade on the light source - note that the _Radius is set for each light source.

Properties
{
    _Color("Bottom Color", Color) = (1,1,1,1)
    _Radius("Radius", Float) = 1
}

SubShader
{
    Tags
    { 
        "RenderType" = "Transparent" 
        "IgnoreProjector" = "True"
        "Queue" = "Transparent" 
    }

    Cull Back
    Blend One OneMinusSrcAlpha

    Pass
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        #include "UnityCG.cginc"

        struct appdata
        {
            float4 vertex : POSITION;
        };

        struct v2f
        {
            float4 vertex : SV_POSITION;
            float distance : float2;
        };

        fixed4 _Color;
        float _Radius;

        v2f vert(appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.distance = distance(float3(0, 0, 0), v.vertex);
            return o;
        }

        fixed4 frag(v2f i) : SV_Target
        {               
            float distance = (i.distance / _Radius); // 0 -> 1 as progressing to outside
            float normalizedDistance = 1 - distance; // 1 -> 0 as progressing to outside 

            // 0 -> 0.43
            fixed colorOffset = lerp(0, _Color.a, distance);

            // return alpha 
            return fixed4(0, 0, 0, colorOffset);
        }

        ENDCG
    }
}
$\endgroup$
3
  • $\begingroup$ I deleted my answer as I think that a blending solution won't fix this problem. I think you probably need to utilize the stencil buffer somehow to avoid writing the darkness to the same area twice. $\endgroup$
    – default
    Commented Mar 6, 2017 at 15:26
  • $\begingroup$ Yes, I have thought the same. I will pursue that idea for the moment. Thanks for trying. $\endgroup$
    – Alex
    Commented Mar 6, 2017 at 15:28
  • 2
    $\begingroup$ You could try using Max blending : stackoverflow.com/questions/2143690/… $\endgroup$
    – PaulHK
    Commented Mar 8, 2017 at 6:41

1 Answer 1

1
$\begingroup$

image

I used Stencil Buffer to fixing your problem , you need a way for checking overlapping two or more shapes

 Shader "Custom/SemiTransparent"
{
    Properties
    {
        _Color("Color",Color) = (0,0,1,0.1)
    }
    SubShader
    {
Tags {"Queue"="Transparent" "IgnoreProjector"="true" "RenderType"="Transparent"}
ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off

        LOD 100

        Pass
        {
            Stencil {
                Ref 0
                Comp Equal
                Pass IncrSat 
                Fail IncrSat 
            }

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            fixed4 _Color;

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = _Color;
                return col;
            }
            ENDCG
        }
    }
}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.