Unity Light Shader

I. Introduction

Today we will implement a sweeping Shader

1.1 Ideas

Idea: We can use a texture as a sweeping light, and then sample its color and superimpose it on the original basis, so that there will be light, and then use _Time.y to make the sampled UV change with time, so that the sweeping light will able to move

1.2 Renderings

It can be seen that the sweeping light moves as we want, and we also added a _RotateAngel variable, so that the direction of the sweeping light can be adjusted
Please add a picture description

1.3 Preparations

1.3.1 Sweeping texture

We need a light-sweeping texture as a material, first attach the texture
Sweep map

1.3.2 Texture settings

Here we need to set WrapMode to Repeat, because uv in our algorithm or add the current time, let uv exceed the range of 0~1, set WrapMode to Repeat, so that we can sample the texture after exceeding 0~1![
In Insert picture description here](https://img-blog.csdnimg.cn/233a730a7f7c4edc92b9a5fa1110e843.pnginsert image description here

Two, Shader content

2.1 Initial Shader

Shader "Custom/MoveLight"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _LightTex("LightTex",2D) = "white" {}
        _LightColor("LightColor",Color) = (1,1,1,1)
        _LightStrength("LightStrength",Range(1,10)) = 1
        _Speed("Speed",Range(0,10)) = 1
        _RotateAngel("RotateAngel",Range(0,360)) = 0
    }
    SubShader
    {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha


        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

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

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

            sampler2D _MainTex;
            float4 _MainTex_ST;
           
            sampler2D _LightTex;
            float4 _LightTex_ST;

            float _Speed;
            float4 _LightColor;
            float _LightStrength;
            float _RotateAngel;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.lightUV = TRANSFORM_TEX(v.uv, _LightTex);
                // o.lightUV = v.uv;
                
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);

                //加上时间,让扫光动起来
                i.lightUV.x = i.lightUV.x + frac(_Speed * _Time.y);//_Time的4个分量 float4 Time (t/20, t, t*2, t*3), 
                
                fixed4 lightCol = tex2D(_LightTex, i.lightUV);
                
                float4 result = col;
                float alpha = step(1,lightCol.a);
                result = lerp(col,col + lightCol * _LightColor * _LightStrength,alpha);
                result.a = col.a;
                return result;     
            }
            ENDCG
        }
    }
}

2.2 Effect

Please add a picture description

2.3 Analysis

In this way, we use the original alpha as the final alpha, so as to ensure that it will not be added to the transparent place;
and we use the step and lerp functions to superimpose white light only on the opaque (that is, white light) part of the sweeping map;
and We used _Time.y to change the uv and make the sweep light move. Here remember the 4 components of _Time _Time (t/20, t, t 2, t 3),

However, the direction of sweeping light is fixed in this way, and more often, we hope that it can be adjusted. Next, let's optimize

2.4 Optimization

                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);

				//角度转弧度,因为正余弦采用弧度
                float angel = _RotateAngel * 3.14159265359 / 180;

                //旋转前,改变轴心。不减的话,是以左下角(0,0)为轴心,减去后以(0.5,0.5)为轴心,这才是我们要的旋转效果
                float2 lightUV = i.lightUV - float2(0.5,0.5);

                //这里,应用旋转函数,把UV进行旋转
                lightUV= float2(lightUV.x * cos(angel) - lightUV.y * sin(angel),lightUV.y * cos(angel) + lightUV.x * sin(angel));
                
                //加回偏移
                lightUV = lightUV + float2(0.5,0.5);

                //加上时间,让扫光动起来
                lightUV.x = lightUV.x + frac(_Speed * _Time.y);//_Time的4个分量 float4 Time (t/20, t, t*2, t*3), 
                
                fixed4 lightCol = tex2D(_LightTex, lightUV);

After adding the rotation, the effect is the same as the animation we posted earlier. RotateAngel can be adjusted to adjust the sweeping direction. Here is the derivation of the rotation function:

After the coordinate a(xa, ya) of any point is rotated by any angle θ, its new coordinate b(xb, yb), where xb
= xa * cosθ - ya * sinθ;
yb = ya * cosθ + xa * sinθ;

This is because we draw a circle with a radius of r, assuming the angle a between point a itself and the circle, then
xa = r * cos a, ya = r * sin a,
then xb = r * cos( a + θ ), yb = cos (b + θ)
into the cosine sum difference formula, and the above formula can be obtained by removing the parentheses:
xb = xa * cosθ - ya * sinθ;
yb = ya * cosθ + xa * sinθ;

There is also the following code

                //这里,应用旋转函数,把UV进行旋转
                lightUV= float2(lightUV.x * cos(angel) - lightUV.y * sin(angel),lightUV.y * cos(angel) + lightUV.x * sin(angel));

3. Complete code

At this point, our code is finished. Next attach the complete code

Shader "Custom/MoveLight"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _LightTex("LightTex",2D) = "white" {}
        _LightColor("LightColor",Color) = (1,1,1,1)
        _LightStrength("LightStrength",Range(1,10)) = 1
        _Speed("Speed",Range(0,10)) = 1
        _RotateAngel("RotateAngel",Range(0,360)) = 0
    }
    SubShader
    {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha


        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

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

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

            sampler2D _MainTex;
            float4 _MainTex_ST;
            
            sampler2D _LightTex;
            float4 _LightTex_ST;

            float _Speed;
            float4 _LightColor;
            float _LightStrength;
            float _RotateAngel;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.lightUV = TRANSFORM_TEX(v.uv, _LightTex);
                // o.lightUV = v.uv;
                
                return o;
            }



            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);

                float angel = _RotateAngel * 3.14159265359 / 180;//角度转弧度,因为正余弦采用弧度

                //旋转前,改变轴心。不减的话,是以左下角(0,0)为轴心,减去后以(0.5,0.5)为轴心,这才是我们要的旋转效果
                float2 lightUV = i.lightUV - float2(0.5,0.5);

                //这里,应用旋转函数,把UV进行旋转
                lightUV= float2(lightUV.x * cos(angel) - lightUV.y * sin(angel),lightUV.y * cos(angel) + lightUV.x * sin(angel));
                
                //加回偏移
                lightUV = lightUV + float2(0.5,0.5);

                //加上时间,让扫光动起来
                lightUV.x = lightUV.x + frac(_Speed * _Time.y);//_Time的4个分量 float4 Time (t/20, t, t*2, t*3), 
                
                fixed4 lightCol = tex2D(_LightTex, lightUV);
                
                float4 result = col;
                float alpha = step(1,lightCol.a);
                result = lerp(col,col + lightCol * _LightColor * _LightStrength,alpha);
                result.a = col.a;
                return result;

            }
            ENDCG
        }
    }
}


Guess you like

Origin blog.csdn.net/aaa27987/article/details/131259840