Sombreador de luz de la unidad

I. Introducción

Hoy implementaremos un Shader de barrido

1.1 Ideas

Idea: Podemos usar una textura como una luz de barrido, y luego probar su color y superponerlo sobre la base original, para que haya luz, y luego usar _Time.y para hacer que el UV muestreado cambie con el tiempo, para que el la luz de barrido podrá moverse

1.2 Representaciones

Se puede ver que la luz de barrido se mueve como queremos, y también agregamos una variable _RotateAngel, para que la dirección de la luz de barrido se pueda ajustar
Por favor agregue una descripción de la imagen

1.3 Preparativos

1.3.1 Textura de barrido

Necesitamos una textura de barrido de luz como material, primero adjunte la textura
Barrido de mapa

1.3.2 Ajustes de textura


Aquí tenemos que establecer WrapMode en Repetir, porque uv en nuestro algoritmo o agregar el tiempo actual, dejar que uv exceda el rango de 0~1, establecer WrapMode en Repetir, para que podamos probar la textura después de exceder 0~1. Inserte la descripción de la imagen aquí](https://img-blog.csdnimg.cn/233a730a7f7c4edc92b9a5fa1110e843.pnginserte la descripción de la imagen aquí

Dos, contenido Shader

2.1 Sombreador inicial

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 Efecto

Por favor agregue una descripción de la imagen

2.3 Análisis

De esta manera, usamos el alfa original como el alfa final, para asegurarnos de que no se agregará al lugar transparente;
y usamos las funciones de paso y lerp para superponer luz blanca solo sobre el opaco (es decir, blanco luz) parte del mapa de barrido;
y Usamos _Time.y para cambiar el uv y hacer que la luz de barrido se mueva. Aquí recuerda los 4 componentes de _Tiempo _Tiempo (t/20, t, t 2, t 3),

Sin embargo, la dirección de la luz de barrido se fija de esta manera y, más a menudo, esperamos que se pueda ajustar. A continuación, vamos a optimizar

2.4 Optimización

                // 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);

Después de agregar la rotación, el efecto es el mismo que el de la animación que publicamos anteriormente. RotateAngel se puede ajustar para ajustar la dirección de barrido. Aquí está la derivación de la función de rotación:

Después de rotar la coordenada a(xa, ya) de cualquier punto en cualquier ángulo θ, su nueva coordenada b(xb, yb), donde xb =
xa * cosθ - ya * sinθ,
yb = ya * cosθ + xa * sinθ;

Esto se debe a que dibujamos un círculo con un radio de r, asumiendo el ángulo a entre el punto a y el círculo, entonces
xa = r * cos a, ya = r * sin a,
luego xb = r * cos( a + θ ), yb = cos (b + θ)
en la fórmula de diferencia de suma de coseno, y la fórmula anterior se puede obtener eliminando los paréntesis:
xb = xa * cosθ - ya * sinθ;
yb = ya * cosθ + xa * sinθ;

También existe el siguiente código

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

3. Código completo

En este punto, nuestro código está terminado. A continuación adjunta el código completo

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
        }
    }
}


Supongo que te gusta

Origin blog.csdn.net/aaa27987/article/details/131259840
Recomendado
Clasificación