Shader(代码篇之特效)

这篇文章介绍了在Unity中创建自定义Shader的技巧,包括AlphaCutout实现透明剪切,以及BlendMode混合模式的使用,如AlphaBlend和AlphaAdditive。同时展示了如何实现UV流动和UV扭曲效果,增强了纹理的表现力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. AlphaCutout

Shader "Shader/Custom/AC"
{
    Properties
    {
        _MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}
        _Cutoff ("透切阈值", range(0.0, 1.0)) = 0.5
    }
    SubShader
    {
        Tags { 
            "RenderType"="TransparentCutout"    // 对应改为Cutout
            "ForceNoShadowCasting"="True"       // 关闭阴影投射
            "IgnoreProjector"="True"            // 不响应投射器
            }
        

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform half _Cutoff;

            // 输入结构
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;          // UV信息 采样贴图用
            };
            // 输出结构
            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;          // UV信息 采样贴图用
            };
            // 输入结构>>>顶点Shader>>>输出结构
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos( v.vertex);    // 顶点位置 OS>CS
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);       // UV信息 支持TilingOffset
                return o;
            }
            // 输出结构>>>像素
            fixed4 frag (v2f i) : SV_Target
            {
                half4 var_MainTex = tex2D(_MainTex, i.uv);      // 采样贴图 RGB颜色 A透贴
                clip(var_MainTex.a - _Cutoff);                  // 透明剪切
                return var_MainTex;                             // 返回值                          
            }
            ENDCG
        }
    }
}
  1. BlendMode

Shader "Shader/Custom/BlendMode"
{
    Properties
    {
        _MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}
        _Opacity ("透明度", range(0, 1)) = 0.5
        [Enum(UnityEngine.Rendering.BlendMode)]
        _BlendSrc ("混合源乘子", int) = 0
        [Enum(UnityEngine.Rendering.BlendMode)]
        _BlendDst ("混合目标乘子", int) = 0
        [Enum(UnityEngine.Rendering.BlendOp)]
        _BlendOp ("混合算符", int) = 0
    }
    SubShader
    {
        Tags { 
            "Queue"="Transparent"               // 调整渲染顺序
            "RenderType"="Transparent"          // 对应改为Cutout
            "ForceNoShadowCasting"="True"       // 关闭阴影投射
            "IgnoreProjector"="True"            // 不响应投射器
            }
        

        Pass
        {
            BlendOp [_BlendOp]                  // 可自定义混合算符
            Blend [_BlendSrc] [_BlendDst]       // 可自定义混合模式

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform half _Opacity;

            // 输入结构
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;          // UV信息 采样贴图用
            };
            // 输出结构
            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;          // UV信息 采样贴图用
            };
            // 输入结构>>>顶点Shader>>>输出结构
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos( v.vertex);    // 顶点位置 OS>CS
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);       // UV信息 支持TilingOffset
                return o;
            }
            // 输出结构>>>像素
            fixed4 frag (v2f i) : SV_Target
            {
                half4 var_MainTex = tex2D(_MainTex, i.uv);      // 采样贴图 RGB颜色 A透贴不必须
                half3 finalRGB = var_MainTex.rgb;
                half opacity = var_MainTex.a * _Opacity;
                return half4(finalRGB * opacity, opacity);                // 返回值                         
            }
            ENDCG
        }
    }
}

1.Blend One OneMinusSrcAlpha(AlphaBlend)

2.Blend One One(AlphaAdditive)

3.混合原理

Src*SrcFactor op Dst*DstFactor

• Src:源,当前Shader绘制的结果;

• Dst:目标,当前Shader绘制前的背景;

• SrcFactor:源乘子;

• DstFactor:目标乘子;

• Op:混合运算符;

  1. UV流动

Shader "Shader/Custom/UVFlow"
{
    Properties
    {
        _MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}
        _Opacity ("透明度", range(0, 1)) = 0.5
        _NoiseTex ("噪声图", 2d) = "gray"{}
        _NoiseInt ("噪声强度", range(0, 5)) = 1
        _FlowSpeed ("流动速度", range(-10, 10)) = 5
    }
    SubShader
    {
        Tags { 
            "Queue"="Transparent"               // 调整渲染顺序
            "RenderType"="Transparent"          // 对应改为Cutout
            "ForceNoShadowCasting"="True"       // 关闭阴影投射
            "IgnoreProjector"="True"            // 不响应投射器
            }
        

        Pass
        {
             Blend One OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            // 输入参数
            uniform sampler2D _MainTex;
            uniform half _Opacity;
            uniform sampler2D _NoiseTex;    uniform float4 _NoiseTex_ST;
            uniform half _NoiseInt;
            uniform half _FlowSpeed;

            // 输入结构
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;          // UV信息 采样贴图用
            };
            // 输出结构
            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;         // UV 采样MainTex用
                float2 uv1 : TEXCOORD1;         // UV 采样NoiseTex用
            };
            // 输入结构>>>顶点Shader>>>输出结构
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos( v.vertex);    // 顶点位置 OS>CS
                o.uv0 = v.uv;
                o.uv1 = TRANSFORM_TEX(v.uv, _NoiseTex);       // UV信息 支持TilingOffset
                o.uv1.y = o.uv1.y + frac(_Time.x * _FlowSpeed);
                return o;
            }
            // 输出结构>>>像素
            fixed4 frag (v2f i) : SV_Target
            {
                half4 var_MainTex = tex2D(_MainTex, i.uv0);      // 采样贴图 RGB颜色
                half4 var_NoiseTex = tex2D(_NoiseTex, i.uv1);
                half3 finalRGB = var_MainTex.rgb;
                half noise = lerp(1.0, var_NoiseTex.r * 2.0, _NoiseInt);
                noise = max(0.0, noise);
                half opacity = var_MainTex.a * _Opacity * noise;
                return half4(finalRGB * opacity, opacity);                // 返回值                         
            }
            ENDCG
        }
    }
}
  1. UV扰动

Shader "Shader/Custom/UVWrap"
{
    Properties
    {
        _MainTex ("RGB:颜色 A:透贴", 2d) = "gray"{}
        _Opacity ("透明度", range(0, 1)) = 0.5
        _WarpTex ("扭曲图", 2d) = "gray"{}
        _WarpInt ("扭曲强度", range(0, 1)) = 0.1
        _NoiseInt ("噪声强度", range(0, 5)) = 1
        _FlowSpeed ("流动速度", range(-10, 10)) = 5
    }
    SubShader
    {
        Tags { 
            "Queue"="Transparent"               // 调整渲染顺序
            "RenderType"="Transparent"          // 对应改为Cutout
            "ForceNoShadowCasting"="True"       // 关闭阴影投射
            "IgnoreProjector"="True"            // 不响应投射器
            }
        

        Pass
        {
             Blend One OneMinusSrcAlpha

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            // 输入参数
            uniform sampler2D _MainTex;
            uniform half _Opacity;
            uniform sampler2D _WarpTex;    uniform float4 _WarpTex_ST;
            uniform half _WarpInt;
            uniform half _NoiseInt;
            uniform half _FlowSpeed;

            // 输入结构
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;          // UV信息 采样贴图用
            };
            // 输出结构
            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;         // UV 采样MainTex用
                float2 uv1 : TEXCOORD1;         // UV 采样WrapTex用
            };
            // 输入结构>>>顶点Shader>>>输出结构
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos( v.vertex);    // 顶点位置 OS>CS
                o.uv0 = v.uv;
                o.uv1 = TRANSFORM_TEX(v.uv, _WarpTex);       // UV信息 支持TilingOffset
                o.uv1.y = o.uv1.y + frac(_Time.x * _FlowSpeed);
                return o;
            }
            // 输出结构>>>像素
            half4 frag (v2f i) : SV_Target
            {                
                half3 var_WarpTex = tex2D(_WarpTex, i.uv1).rgb;
                half2 uvBias = (var_WarpTex.rg - 0.5) * _WarpInt;
                half2 uv0 = i.uv0 + uvBias;
     
                half4 var_MainTex = tex2D(_MainTex, uv0);  
                half3 finalRGB = var_MainTex.rgb;
                half noise = lerp(1.0, var_WarpTex.b * 2.0, _NoiseInt);
                noise = max(0.0, noise);
                half opacity = var_MainTex.a * _Opacity * noise;
                return half4(finalRGB * opacity, opacity);                // 返回值                         
            }
            ENDCG
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧寒大大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值