Search Unity

Does anyone know how to take a multiply shadow and make it blend with shadows instead (projectors)?

Discussion in 'Shaders' started by astracat111, Sep 22, 2020.

  1. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    725
    At the moment this is what I've got:



    It's good but isn't there a way to have it blend with Unity shadows instead of it's current multiply effect? Here's what Unity's shader looks like that's packaged with the shadow projector:

    EDIT: full code in post below...

    I think what I might be looking for is an 'additive' shader, but I'm not sure.
     
    Last edited: Sep 22, 2020
  2. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    725
    So far this is what I've figured out from here:

    https://docs.unity3d.com/Manual/SL-...185.188095962.1600742175-764748103.1597092726

    To get an additive shader, you change this:

    Code (CSharp):
    1. Blend DstColor Zero
    To this:

    Code (CSharp):
    1. Blend One One
    But now it comes out all white:



    Which seems great for snow scenes but doesn't work here....here's the full code to Unity's shadow projector multiply shader:

    Code (CSharp):
    1. // Upgrade NOTE: replaced '_Projector' with 'unity_Projector'
    2. // Upgrade NOTE: replaced '_ProjectorClip' with 'unity_ProjectorClip'
    3.  
    4. Shader "Projector/Multiply" {
    5.     Properties {
    6.         _ShadowTex ("Cookie", 2D) = "gray" {}
    7.         _FalloffTex ("FallOff", 2D) = "white" {}
    8.     }
    9.     Subshader {
    10.         Tags {"Queue"="Transparent"}
    11.         Pass {
    12.             ZWrite Off
    13.             ColorMask RGB
    14.             Blend DstColor Zero
    15.             Offset -1, -1
    16.  
    17.             CGPROGRAM
    18.             #pragma vertex vert
    19.             #pragma fragment frag
    20.             #pragma multi_compile_fog
    21.             #include "UnityCG.cginc"
    22.            
    23.             struct v2f {
    24.                 float4 uvShadow : TEXCOORD0;
    25.                 float4 uvFalloff : TEXCOORD1;
    26.                 UNITY_FOG_COORDS(2)
    27.                 float4 pos : SV_POSITION;
    28.             };
    29.            
    30.             float4x4 unity_Projector;
    31.             float4x4 unity_ProjectorClip;
    32.            
    33.             v2f vert (float4 vertex : POSITION)
    34.             {
    35.                 v2f o;
    36.                 o.pos = UnityObjectToClipPos(vertex);
    37.                 o.uvShadow = mul (unity_Projector, vertex);
    38.                 o.uvFalloff = mul (unity_ProjectorClip, vertex);
    39.                 UNITY_TRANSFER_FOG(o,o.pos);
    40.                 return o;
    41.             }
    42.            
    43.             sampler2D _ShadowTex;
    44.             sampler2D _FalloffTex;
    45.            
    46.             fixed4 frag (v2f i) : SV_Target
    47.             {
    48.                 fixed4 texS     = tex2Dproj (_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));
    49.                 texS.a             = 1.0-texS.a;
    50.  
    51.                 fixed4 texF = tex2Dproj (_FalloffTex, UNITY_PROJ_COORD(i.uvFalloff));
    52.                 fixed4 res = lerp(fixed4(1,1,1,0), texS, texF.a);
    53.  
    54.                 UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(1,1,1,1));
    55.                 return res;
    56.             }
    57.             ENDCG
    58.         }
    59.     }
    60. }
    61.  
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    What do you mean blend with Unity’s shadows? Do you mean when a real Unity shadow and the projection overlap, they appear as the same color?

    No, that’s impossible. The closest you could get would be to fade out the projector when in the shadow, but even that’s not really possible without a lot of work. You’d need to copy a reference to the shadow map or screen space shadow texture using a command buffer, then sample that in the projector shader to hide it when intersecting the shadow. Won’t look the same as the shadow, but it at least won’t overlap.

    The better solution is to not use Unity’s projectors at all, and instead inject the “shadow blob” into the shadow maps themselves. If you’re targeting desktop, you can use something like deferred decals during the shadow collection pass. Otherwise you’re targeting mobile, or just want to do something simpler, you can place a shadow casting only circle mesh just above the ground using a ray cast.

    The last option is if you only need the projected blob shadow to cast onto the “ground”, and you only need one blob shadow, you can do it in a custom ground shader that you pass the blob texture and projection to and mix it with the shadow in there. If you need multiple shadows, you can render them into a render texture and have the custom ground shader sample that.

    Also, Projectors are terrible and you should never use them if you can avoid it.
     
    JmprDev likes this.
  4. astracat111

    astracat111

    Joined:
    Sep 21, 2016
    Posts:
    725
    @bgolus A 'deferred decal'...hmm...I'll definitely look that up, I've never even heard of it before.

    Would that be something like this:
    https://assetstore.unity.com/packages/vfx/shaders/standard-deferred-decals-115178
    ?

    The second solution is what I'm gonna use, I can't believe I didn't think of it sooner, just putting a sphere's Lighting setting in it's Mesh Renderer to Shadows Only:



    There aren't really many characters to render, so it's not gonna matter the whole performance hit if there is one.

    Better yet, a capsule like this works well because it mimics the main directional light that's always present in outside scenes:


    I'll just have to make like a scraggily object in probuilder to cast the shadow.



    To solve the problem I just made this strange modern artish thing combined with a capsule collider, and just set them both to Shadows Only with the mesh renderer. x__x Thanks for the help!



    And of course it looked like something suggestive, so I had to change it again. Well, thanks it really helps out.
     
    Last edited: Sep 22, 2020