Search Unity

Revealing a texture when you shine a spotlight on it

Discussion in 'Shaders' started by Yocal, Jun 26, 2017.

  1. Yocal

    Yocal

    Joined:
    Feb 10, 2014
    Posts:
    22
    Hello,

    I have a hidden message on a wall in a dim lit room, and I would like it to remain completely hidden until you shine a special spotlight on it. I am not quite sure how to achieve this, but I found this thread:

    https://forum.unity3d.com/threads/reveal-texture-only-when-light-falls-on-it.26639/

    Unfortunately I am not sure if this for some reason doesn't work anymore or I'm doing it completely wrong.

    I have made a quad, a new material and added my sprite to the material using that shader. But nothing happens when I turn a spotlight to it.

    I'm completely new to shaders, so I'm not even 10% sure what's actually going on... Any good hints?

    Thanks.
     
  2. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    The reason why it doesnt work is because it uses per vertex lighting. If you shine the light on one of the vertices, the hidden message will appear, but obviously with a quad there is a very limited amount of vertices to be hit by light. I worked on the same problem just the other week and here is what I've got:
    Code (CSharp):
    1.  Shader "Custom/UltravioletLight" {
    2.     Properties {
    3.       _MainTex ("Texture", 2D) = "white" {}
    4.     }
    5.     SubShader {
    6.       Tags {"Queue" = "Transparent" "RenderType"="Transparent" }
    7.       CGPROGRAM
    8.       #pragma surface surf Standard alpha:fade
    9.       struct Input {
    10.           float2 uv_MainTex;
    11.       };
    12.  
    13.       sampler2D _MainTex;
    14.       void surf (Input IN, inout SurfaceOutputStandard o) {
    15.           fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * fixed4(1,1,1,1);
    16.           o.Albedo = c.rgb;
    17.           o.Alpha = c.a * (1 - _LightColor0.a);
    18.       }
    19.       ENDCG
    20.     }
    21. }
    This isn't perfect, but hopefully it will help you get going. The way you use it is as follows:
    1. make a shader file and paste this code there
    2. make a material that uses this shader
    3. attach this material to a wall/quad you want
    4. select the texture on the material, adjust tiling if needed
    5. set the desired light to emit light colour with maximum alpha channel(by default light has 0 alpha)
    Note that this solution relies on all other light sources being alpha 0, otherwise the hidden message will always show.

    Also if anyone else here has any improvement ideas to this shader, I'd appreciate.
     
    Last edited: Jun 28, 2017
    Alverik and Yocal like this.
  3. Yocal

    Yocal

    Joined:
    Feb 10, 2014
    Posts:
    22
    Thank you for assisting, BakeMyCake... That kinda worked for me to some extend, but my issue seems to be that the sprite turns black in alpha=0 light. I would have expected it to disappear instead. Try to see this little clip:

    - http://imgur.com/0chMNPt

    Left and right light is alpha=100 and the center one is alpha=0. No other lights in the scene.

    What could I be doing wrong?
     
  4. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    Here is a demo scene. I think it's the easiest way to rule out any mistakes.

    EDIT: Upon further inspection it appears that without the main directional light this shader does produce black shapes. Like I said it's far from perfect. I haven't noticed that because in my project I always used a directional light.
     

    Attached Files:

    Last edited: Jun 28, 2017
  5. Yocal

    Yocal

    Joined:
    Feb 10, 2014
    Posts:
    22
    Wow, you are amazing - thanks a ton!
     
  6. Yocal

    Yocal

    Joined:
    Feb 10, 2014
    Posts:
    22
    Just a follow up question - i played around with your spotlight just to figure out what went wrong in my other scene... When i turn the alpha to max (255) it shows the circle as green instead of invisible. Looks like the 'sweetspot' where it disappears is at alpha 50. What is it I don't understand here? Wouldn't 255 be 100%? Why does it work with 50?

    Edit: Just tried another texture, that seem to disappear around alpha set to 90... I'm deeply confused! :)
     
  7. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    Can you provide a test case so I can debug it?
     
  8. Yocal

    Yocal

    Joined:
    Feb 10, 2014
    Posts:
    22
    I must have fiddled with something I shouldn't... I loaded it into an empty project and tried setting up a demoscene for you - and it works flawlessly! :)

    Only odd thing is the black effect without directional light. It'll pose a bit of a problem as my room will be dark, and lowering the intensity to less than 1 will make the shapes start to appear which kinda defeats the purpose.

    Any hints on what could be done? I tried a few things inspired from the original link i refered to, but that doesn't seem to do anything...

     
  9. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    Maybe this one helps? Since I don't know what your scene setup is, I'm pretty much doing guesswork. In any case the whole trick revolves around the o.Aplha parameter of the shader. 0 will give you a completely transparent pixel, 1 gives you a fully opaque pixel. _LightColor0.a is the colour alpha part of the main lights that shine on this pixel. c.a is the alpha part of this textures' pixel.

    From there it's a matter of coming up with an equation that takes the alpha of both the image and the lights, and gives you 0 where you want it to be invisible, and 1 where you want it visible. Hope it helps.
     

    Attached Files:

  10. Yocal

    Yocal

    Joined:
    Feb 10, 2014
    Posts:
    22
    Ah, yes, I think that did the trick! These two examples are great to compare to understand what's going on. Thank you so much, I think you solved it :)