Unity Shader 进阶教程:透明效果、溶解效果、旗帜飘动与点云(附完整代码)

Unity Shader 进阶教程:透明效果、溶解效果、旗帜飘动与点云(附完整代码)

1. 透明与混合效果

1.1 透明度基础

Transparency

在 Shader 中,透明度通过 Alpha 通道控制。可以通过修改片段的 Alpha 值来实现透明效果。例如:

Shader "Custom/TransparentShader" {
    Properties{
        _MainTex("Texture", 2D) = "white" {}
        _Transparency("Transparency", Range(0,1)) = 0.5
    }
        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;
                    float4 pos : SV_POSITION;
                };
                sampler2D _MainTex;
                float4 _MainTex_ST;
                float _Transparency;
                v2f vert(appdata v) {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }
                fixed4 frag(v2f i) : SV_Target {
                    fixed4 col = tex2D(_MainTex, i.uv);
                    col.a *= _Transparency; // 应用透明度属性
                    return col;
                }
                ENDCG
            }
        }
            FallBack "Diffuse"
}

在 Unity 中,透明效果需要启用混合模式(Blend)。常见的混合模式包括:

  • Alpha 混合Blend SrcAlpha OneMinusSrcAlpha
  • 加法混合Blend One One
  • 乘法混合Blend DstColor Zero

1.2 实现溶解效果

溶解效果是一种常见的透明效果,通过噪声纹理控制物体的消失过程。以下是实现溶解效果的代码:

Shader "Custom/DissolveShaderWithTransparency"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}          // 主纹理
        _NoiseTex("Noise Texture", 2D) = "white" {}   // 噪声纹理
        _DissolveThreshold("Dissolve Threshold", Range(0, 1)) = 0.5  // 溶解阈值
        _EdgeColor("Edge Color", Color) = (1, 0, 0, 1)              // 边缘颜色
        _EdgeWidth("Edge Width", Range(0, 0.2)) = 0.1               // 边缘宽度
    }
        SubShader
        {
            Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }  // 透明渲染队列
            LOD 200

            Pass
            {
                Blend SrcAlpha OneMinusSrcAlpha  // 启用透明度混合
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"

                // 定义输入结构
                struct appdata
                {
                    float4 vertex : POSITION;  // 顶点位置
                    float2 uv : TEXCOORD0;     // 纹理坐标
                };

                // 定义输出结构
                struct v2f
                {
                    float2 uv : TEXCOORD0;     // 主纹理坐标
                    float2 uvNoise : TEXCOORD1; // 噪声纹理坐标
                    float4 vertex : SV_POSITION; // 裁剪空间顶点位置
                };

                // 属性变量
                sampler2D _MainTex;
                float4 _MainTex_ST;
                sampler2D _NoiseTex;
                float4 _NoiseTex_ST;
                float _DissolveThreshold;
                float4 _EdgeColor;
                float _EdgeWidth;

                // 顶点 Shader
                v2f vert(appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);  // 顶点变换到裁剪空间
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);       // 主纹理坐标变换
                    o.uvNoise = TRANSFORM_TEX(v.uv, _NoiseTex); // 噪声纹理坐标变换
                    return o;
                }

                // 片段 Shader
                fixed4 frag(v2f i) : SV_Target
                {
                    // 采样噪声纹理
                    float noise = tex2D(_NoiseTex, i.uvNoise).r;

                    // 溶解效果
                    if (noise < _DissolveThreshold)  // 如果噪声值小于阈值,丢弃像素
                        discard;

                    // 计算边缘透明度
                    float edgeAlpha = smoothstep(_DissolveThreshold, _DissolveThreshold + _EdgeWidth, noise);

                    // 采样主纹理
                    fixed4 texColor = tex2D(_MainTex, i.uv);

                    // 计算边缘颜色
                    fixed4 edgeColor = _EdgeColor * (1 - edgeAlpha);

                    // 最终颜色 = 主纹理颜色 + 边缘颜色
                    fixed4 col = texColor * edgeAlpha + edgeColor;
                    col.a = edgeAlpha;  // 设置透明度
                    return col;
                }
                ENDCG
            }
        }
            FallBack "Diffuse"
}

调整 _DissolveThreshold可以控制物体的溶解过程。

Dissolve


2. 顶点动画与几何 Shader

2.1 顶点动画基础

顶点动画通过修改顶点位置来实现动态效果。例如,我们可以实现一个简单的旗帜飘动效果:

Shader "Custom/FlagWaveShader"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}          // 主纹理
        _WindStrength("Wind Strength", Float) = 1.0   // 风强度
        _WindFrequency("Wind Frequency", Float) = 1.0  // 风频率
        _WindDirection("Wind Direction", Vector) = (1, 0, 0, 0)  // 风方向
    }
        SubShader
        {
            Tags { "RenderType" = "Opaque" }
            LOD 200

            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; // 裁剪空间顶点位置
        };

        // 属性变量
        sampler2D _MainTex;
        float4 _MainTex_ST;
        float _WindStrength;
        float _WindFrequency;
        float4 _WindDirection;

        // 顶点 Shader
        v2f vert(appdata v)
        {
            v2f o;

            // 计算顶点位移
            float wave = sin(v.uv.x * _WindFrequency + _Time.y) * _WindStrength;  // 波浪效果
            v.vertex.xyz += _WindDirection.xyz * wave;  // 根据风向和强度修改顶点位置

            // 顶点变换到裁剪空间
            o.vertex = UnityObjectToClipPos(v.vertex);

            // 传递纹理坐标
            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
            return o;
        }

        // 片段 Shader
        fixed4 frag(v2f i) : SV_Target
        {
            // 采样主纹理
            fixed4 col = tex2D(_MainTex, i.uv);
            return col;
        }
        ENDCG
    }
        }
            FallBack "Diffuse"
}

这段代码通过正弦函数模拟了旗帜的飘动效果。调整 _WaveFrequency_WaveAmplitude 来控制波浪的频率和幅度。
FlagWave

2.2 几何 Shader 简介

几何 Shader 是一种强大的工具,可以在渲染管线中生成新的几何图元。虽然 Unity 对几何 Shader 的支持有限,但我们仍然可以实现一些简单的效果。例如,生成一个简单的点云:

Shader "Custom/PointCloudShader"
{
    Properties
    {
        _PointSize("Point Size", Float) = 5.0  // 点的大小
        _PointColor("Point Color", Color) = (1, 1, 1, 1)  // 点的颜色
    }
        SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 200

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma geometry geom
            #pragma fragment frag

            #include "UnityCG.cginc"

            // 定义输入结构
            struct appdata
            {
                float4 vertex : POSITION;  // 顶点位置
            };

    // 定义几何 Shader 输入结构
    struct v2g
    {
        float4 vertex : POSITION;  // 顶点位置
    };

    // 定义几何 Shader 输出结构
    struct g2f
    {
        float4 vertex : SV_POSITION;  // 裁剪空间顶点位置
        float4 color : COLOR;         // 点颜色
        float size : PSIZE;           // 点大小
    };

    // 属性变量
    float _PointSize;
    float4 _PointColor;

    // 顶点 Shader
    v2g vert(appdata v)
    {
        v2g o;
        o.vertex = v.vertex;  // 直接传递顶点位置
        return o;
    }

    // 几何 Shader
    [maxvertexcount(3)]  // 每个输入顶点生成 3 个点
    void geom(point v2g input[1], inout PointStream<g2f> stream)
    {
        g2f o;

        // 生成随机偏移
        float3 randomOffset = float3(
            frac(sin(input[0].vertex.x * 123.456) * 43758.5453),
            frac(sin(input[0].vertex.y * 123.456) * 43758.5453),
            frac(sin(input[0].vertex.z * 123.456) * 43758.5453)
        );

        // 生成 3 个点
        for (int i = 0; i < 3; i++)
        {
            float3 offset = randomOffset * 0.1 * i;  // 随机偏移
            o.vertex = UnityObjectToClipPos(input[0].vertex + float4(offset, 0));  // 顶点变换到裁剪空间
            o.color = _PointColor;  // 设置点颜色
            o.size = _PointSize;    // 设置点大小
            stream.Append(o);       // 将点添加到输出流
        }
    }

    // 片段 Shader
    fixed4 frag(g2f i) : SV_Target
    {
        return i.color;  // 返回点颜色
    }
    ENDCG
}
    }
        FallBack "Diffuse"
}

PointCloud


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值