Shader每日一练(2)护盾

Lua 复制代码
Shader "Custom/Shield"
{
    Properties
    {
        _Size("Size", Range(0 , 10)) = 1 // 控制噪声纹理缩放大小的参数
        _colorPow("colorPow", Float) = 1 // 控制颜色强度的指数
        _colorMul("colorMul", Float) = 1 // 控制颜色乘法因子
        _mainColor("mainColor", Color) = (1,1,1,0) // 主颜色
        _Noise1Tex("Noise1Tex", 2D) = "white" {} // 噪声纹理
        _dir1("dir1", Vector) = (0,0,0,0) // 流动方向1
        _dir2("dir2", Vector) = (1,1,0,0) // 流动方向2
        _alphaSpeed("alphaSpeed", Float) = 1 // 控制透明度变化速度的参数
        _colorAdd("colorAdd", Float) = 1 // 控制颜色添加因子
        _flowSpeed("flowSpeed", Float) = 1 // 控制流动速度的参数
        _flowStrength("flowStrength", Vector) = (1,1,0,0) // 控制流动强度的参数
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Blend SrcAlpha OneMinusSrcAlpha, SrcAlpha OneMinusSrcAlpha // 混合模式:源颜色的 alpha 与目标颜色的反 alpha 进行混合
        ZWrite Off // 关闭深度写入
        LOD 100 // 设置 LOD 等级

        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; // 传递给片段着色器的裁剪空间顶点位置
            };

            // Uniform 变量
            uniform float4 _mainColor;
            uniform sampler2D _Noise1Tex;
            uniform float4 _Noise1Tex_ST;
            uniform float _Size;
            uniform float3 _dir1;
            uniform float2 _flowStrength;
            uniform float _flowSpeed;    
            uniform float _colorMul;
            uniform float _colorPow;
            uniform float3 _dir2;
            uniform float _colorAdd;
            uniform float _alphaSpeed;

            // Flow 函数:生成流动效果
            float3 Flow(sampler2D tex, float2 uv, float2 dir, float2 strength, float speed)
            {
                float2 dirx = dir + 0.5f; // 调整方向
                float timeSpeed = _Time.y * speed; // 根据时间和速度计算流动的时间因子
                float2 uv1 = uv + (dirx * strength * frac(timeSpeed)); // 计算第一组纹理坐标
                float2 uv2 = uv + (dirx * strength * (frac(timeSpeed + 0.5f))); // 计算第二组纹理坐标
                float3 result = lerp(
                    UnpackNormal(tex2D(tex, uv1)), 
                    UnpackNormal(tex2D(tex, uv2)), 
                    (abs((frac(timeSpeed) - 0.5)) / 0.5)
                ); // 线性插值计算最终的流动效果
                return result;
            }

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex); // 转换顶点位置到裁剪空间
                o.uv = TRANSFORM_TEX(v.uv, _Noise1Tex) / +_Size; // 计算纹理坐标并进行缩放
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                float3 col1 = Flow(_Noise1Tex, i.uv, _dir1, _flowStrength, _flowSpeed); // 计算第一个流动效果
                float3 col2 = Flow(_Noise1Tex, i.uv, _dir2, _flowStrength, _flowSpeed); // 计算第二个流动效果
                float val1 = 1.0 - saturate(pow(col1.r * _colorMul, _colorPow)); // 根据流动颜色计算第一个颜色值
                float val2 = 1.0 - saturate(pow(col2.r * _colorMul, _colorPow)); // 根据流动颜色计算第二个颜色值
                float4 noiseCol = tex2D(_Noise1Tex, float2(frac(_Time.y * _alphaSpeed), 0)); // 采样噪声纹理计算透明度
                float alpha = val1 * val2 * noiseCol.r * noiseCol.r; // 计算最终透明度
                float3 rgb = _mainColor.rgb * val1 * val2 * _colorAdd; // 计算最终颜色
                return half4(rgb, alpha); // 返回颜色和透明度
            }
            ENDCG
        }
    }
}

效果:

简化版: