0
\$\begingroup\$

I use Unity, and I need a shader a bit special. Unfortunatly my skills about shaders are very limited and I need this shader quickly.

So I want a shader to display a unlit texture on a plane, and when a light affect the plane, instead of make the lighting on the plane, I want that the light change the alpha to make the "lighted" surface transparent.

I think that it's not very hard for someone who know how to make shaders, so if you can help me to do this, it can be very useful for me!


Edit:

Ok, maybe it's not very clear.

I speak about a light, but it's not necessary a light, it can be with an other type of object, or just a position.

What I want is to have an unlit image, with a movable circle zone on this texture which make the zone transparent, like the white circle on this picture (imagine that the with is just the transparency).

The border shouldn't be necessarily with smooth border, it will be also fine with an hard border.

enter image description here

I have thought about a spotlight, because it's like move a spotlight on the picture, but instead of doing the lighting, I want to set the "lighted" pixel transparent (but it's not lighted, it's just to explain what I want), a,d it's not necessary with a light

And yes, the unlit shader can't do this I think, I probably need a custom shader but I don't know how to this (I have thinked about take a basic lighting shader, and use the computed intensity of the light on the pixels to set the alpha instead of use it to set the intensity of the pixel, but I don't know exactly how to do this)

\$\endgroup\$
3
  • \$\begingroup\$ But Unlit shaders never get affected by light \$\endgroup\$ Jan 4, 2016 at 8:41
  • \$\begingroup\$ @HamzaHasan that's not a problem, because the OP has not asked for an "unlit shader". They've asked for a shader which displays an "unlit texture" - ie. the texture's rgb values are not tinted or darkened by light & shadow. That doesn't preclude us from using a lit shader and overriding the colour output (see answer below) although it looks like simpler options are available. \$\endgroup\$
    – DMGregory
    Jan 4, 2016 at 13:17
  • \$\begingroup\$ @DMGregory What so ever, but I love your answer man :) \$\endgroup\$ Jan 4, 2016 at 13:30

1 Answer 1

3
\$\begingroup\$

This looks like an XY problem.

What you've asked for is a material which changes opacity based on lighting. This is doable, but somewhat needlessly complex to get working well:

Wood plane being made transparent where a spotlight hits it

This hacked example is accomplished with this surface shader:

Shader "Custom/LightToAlpha" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _ALightThreshold("Light Threshold", float) = 0.0
        _ALightContrast("Light Contrast", float) = 1.0
    }
    SubShader {
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows finalcolor:alphaLight alpha:fade

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        half _ALightThreshold;
        half _ALightContrast;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = (fixed4)1.0f;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }

        void alphaLight(Input IN, SurfaceOutputStandard o, inout fixed4 color)
        {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
            color.a = 1.0f - saturate(c.a * saturate(dot(color.rgb, fixed3(1.0f, 1.0f, 1.0f) / 3.0f) - _ALightThreshold) * _ALightContrast);            
            color.rgb = c.rgb;
        }

        ENDCG
    }
    FallBack "Diffuse"
}

But from your clarification, what it seems like you really want is to be able to make a movable circular hole in an image. This doesn't require all the complexities of lighting at all, and can be accomplished much more simply & robustly:

Textured image with a circular hole faded into it.

This shader exposes a vector parameter whose x, y, z correspond to the worldspace position of the hole, and whose w is the worldspace size of the hole. You can rig up a script to set these parameters from the transform of a hole object for ease of editing/animating.

Shader "Unlit/TextureHole"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _HolePos ("Hole Position & Size", vector) = (0, 0, 0, 1)

    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue"="Transparent" }
        LOD 100

        Blend srcAlpha oneMinusSrcAlpha
        ZWrite Off
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldPos : TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float4 _HolePos;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.worldPos = mul(_Object2World, v.vertex).xyz;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                float3 offset = _HolePos.xyz - i.worldPos;
                float range = dot(offset, offset) / (_HolePos.w * _HolePos.w);
                range = 1.0f - saturate(range);
                range *= range * 5.0f; // this multiplier controls the sharpness of the fade around the hole.               
                col.a *= saturate(1.0f - range);
                return col;
            }
            ENDCG
        }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ I have tested the second shader, it's exctaly what I need ! Thanks ! \$\endgroup\$
    – jb14
    Jan 4, 2016 at 16:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .