Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How do I use shadows of a light as a mask for other lights in a shader?

Discussion in 'Shaders' started by Barti, Jul 10, 2015.

  1. Barti

    Barti

    Joined:
    Dec 8, 2012
    Posts:
    5
    Hello,

    I am trying to use the attenuation of a light as a mask for rendering.

    In my shader I can find the mask-light by comparing its position to a uniform which I set with an external script.
    Now I somehow need to "save" the attenuation of this light to mask out everything that is not effected by my mask-light.

    This is what I have got so far.

    Code (CSharp):
    1. Shader "Custom/MySurfaceShader" {
    2.  
    3.     Properties {
    4.         _Color("Tint color", Color) = (1.0, 1.0, 1.0, 1.0)
    5.         _MainTex("Main Texture", 2D) = "white" {}
    6.     }
    7.  
    8.     SubShader {
    9.  
    10.         Tags { "RenderType"="Opaque" }
    11.         LOD 200
    12.    
    13.         CGPROGRAM
    14.    
    15.         #pragma surface surf MaskLight fullforwardshadows
    16.         #pragma target 3.0
    17.    
    18.         uniform float4 _WorldPlayerPos;
    19.    
    20.         half4 LightingMaskLight(SurfaceOutput s, half3 lightDir, half atten) {
    21.             half4 c;
    22.    
    23.             fixed NdotL = dot(s.Normal, lightDir);
    24.        
    25.             // Test if the current light is the mask-light
    26.             // if(_WorldPlayerPos.x == _WorldSpaceLightPos0.x && _WorldPlayerPos.y == _WorldSpaceLightPos0.y && _WorldPlayerPos.z == _WorldSpaceLightPos0.z)
    27.          
    28.             // Use this when the attenuation of the mask-light is > 0
    29.             // c.rgb = s.Albedo * NdotL * atten * _LightColor0;
    30.  
    31.             // Use this when the attenuation of the mask-light is == 0
    32.             // c.rgb = half3(0, 0, 0);
    33.        
    34.             return c;
    35.         }
    36.    
    37.         uniform fixed4 _Color;
    38.         uniform sampler2D _MainTex;
    39.  
    40.         struct Input {
    41.             fixed2 uv_MainTex;
    42.         };
    43.  
    44.         void surf(Input IN, inout SurfaceOutput o) {
    45.             fixed4 c;
    46.        
    47.             c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    48.        
    49.             o.Albedo = c.rgb;
    50.             o.Alpha = c.a;
    51.         }
    52.    
    53.         ENDCG
    54.     }
    55.  
    56.     FallBack "Diffuse"
    57. }
    Greetings,
    Barti
     
    Last edited: Jul 11, 2015
  2. Sparrowfc

    Sparrowfc

    Joined:
    Jan 31, 2013
    Posts:
    100
    The attenuation is not a fixed value. It's different for each vertex with each light source. You can open 'generated surface shader' to see how the atten param is calculate.
    In your case, I think the practical solution is to write a custom vertex shader to calculate the mask-light's attenuation manually and use it in the Lighting function.
     
  3. Barti

    Barti

    Joined:
    Dec 8, 2012
    Posts:
    5
    Well, I already tried it and it worked totally fine except for the shadows. I am able to mask everything how I want it but this mask is just a circle without shadows.
    If you are able to provide me a solution on how I calculate the shadows, I will definitly take that. :)
     
  4. Sparrowfc

    Sparrowfc

    Joined:
    Jan 31, 2013
    Posts:
    100
  5. Barti

    Barti

    Joined:
    Dec 8, 2012
    Posts:
    5