Elysia Tools

在一个清晰的工作台里浏览工具、案例、可视化和主题指南。

热门分类

专题

语言
ZHESPTRUFRDEEN

Elysia Tools

导航

游戏开发

Unity Shader 示例

Unity HLSL着色器示例,包括表面着色器、顶点/片段着色器和后期处理效果

案例

这个案例集合中的条目

代码glsl简单

基础 Unity 着色器

Unity着色器编程入门,包含表面着色器和基础效果

难度

4/10

预计时间

25 min

标签

unity, shader, hlsl, graphics

前置条件

Shader programming basics, Unity Editor

glsl
// Unity Basic Shaders - HLSL/Cg

// 1. Basic Diffuse Shader
Shader "Custom/BasicDiffuse"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        fixed4 _Color;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    Fallback "Diffuse"
}

// 2. Lambert Lighting with Custom Properties
Shader "Custom/CustomLambert"
{
    Properties
    {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _Emission ("Emission", Color) = (0,0,0,1)
        _Glossiness ("Glossiness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0

        sampler2D _MainTex;
        fixed4 _Color;
        half _Glossiness;
        half _Metallic;
        fixed4 _Emission;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Normal = fixed3(0,0,1);
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Emission = _Emission.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    Fallback "Standard"
}

// 3. Transparent Shader with Alpha
Shader "Custom/Transparent"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _Alpha ("Alpha", Range(0,1)) = 1.0
    }

    SubShader
    {
        Tags {
            "Queue"="Transparent"
            "RenderType"="Transparent"
        }

        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite Off
        Cull Off

        CGPROGRAM
        #pragma surface surf Lambert alpha:fade

        sampler2D _MainTex;
        fixed4 _Color;
        float _Alpha;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a * _Alpha;
        }
        ENDCG
    }
}

// 4. Rim Lighting Shader
Shader "Custom/RimLighting"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _RimColor ("Rim Color", Color) = (0,0.5,1,1)
        _RimPower ("Rim Power", Range(0,8)) = 3.0
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        fixed4 _Color;
        fixed4 _RimColor;
        float _RimPower;

        struct Input
        {
            float2 uv_MainTex;
            float3 viewDir;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;

            // Rim lighting
            half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
            o.Emission = _RimColor.rgb * pow (rim, _RimPower);
            o.Alpha = c.a;
        }
        ENDCG
    }
    Fallback "Diffuse"
}

// 5. Toon/Cel Shading Shader
Shader "Custom/ToonShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _Ramp ("Toon Ramp", 2D) = "gray" {}
        _OutlineColor ("Outline Color", Color) = (0,0,0,1)
        _Outline ("Outline Width", Range(0,0.1)) = 0.02
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        UsePass "Toon/OUTLINE"

        CGPROGRAM
        #pragma surface surf Toon

        sampler2D _MainTex;
        sampler2D _Ramp;
        fixed4 _Color;

        struct Input
        {
            float2 uv_MainTex;
        };

        inline fixed4 LightingToon (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
        {
            half d = dot (s.Normal, lightDir) * 0.5 + 0.5;
            fixed3 ramp = tex2D (_Ramp, fixed2(d,d)).rgb;
            fixed4 c;
            c.rgb = s.Albedo * _LightColor0.rgb * ramp * atten;
            c.a = s.Alpha;
            return c;
        }

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }

    Fallback "Diffuse"
}

// 6. Scrolling Texture Shader
Shader "Custom/ScrollingTexture"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _ScrollX ("Scroll X Speed", float) = 0.1
        _ScrollY ("Scroll Y Speed", float) = 0.0
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        fixed4 _Color;
        float _ScrollX;
        float _ScrollY;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            float2 scrolledUV = IN.uv_MainTex;
            scrolledUV.x += _Time.y * _ScrollX;
            scrolledUV.y += _Time.y * _ScrollY;

            fixed4 c = tex2D (_MainTex, scrolledUV) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    Fallback "Diffuse"
}

// 7. Dissolve Shader
Shader "Custom/Dissolve"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _DissolveTex ("Dissolve Texture", 2D) = "white" {}
        _DissolveAmount ("Dissolve Amount", Range(0,1)) = 0.0
        _EdgeColor ("Edge Color", Color) = (1,0,0,1)
        _EdgeWidth ("Edge Width", Range(0,0.1)) = 0.01
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        sampler2D _DissolveTex;
        fixed4 _Color;
        float _DissolveAmount;
        fixed4 _EdgeColor;
        float _EdgeWidth;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_DissolveTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            float dissolve = tex2D (_DissolveTex, IN.uv_DissolveTex).r;

            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

            if (dissolve < _DissolveAmount)
            {
                clip (-1);
            }

            // Edge effect
            if (dissolve < _DissolveAmount + _EdgeWidth)
            {
                c = _EdgeColor;
            }

            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    Fallback "Diffuse"
}

// 8. Glass/Refraction Shader
Shader "Custom/Glass"
{
    Properties
    {
        _MainTex ("Main Texture", 2D) = "white" {}
        _BumpMap ("Normal Map", 2D) = "bump" {}
        _Color ("Color", Color) = (1,1,1,1)
        _RefractAmount ("Refraction Amount", Range(0,1)) = 0.5
        _Glossiness ("Glossiness", Range(0,1)) = 0.8
    }

    SubShader
    {
        Tags {
            "Queue"="Transparent"
            "RenderType"="Opaque"
        }

        GrabPass {}

        CGPROGRAM
        #pragma surface surf Standard alpha
        #pragma target 3.0

        sampler2D _MainTex;
        sampler2D _BumpMap;
        sampler2D _GrabTexture;
        fixed4 _Color;
        float _RefractAmount;
        half _Glossiness;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpMap;
            float4 screenPos;
        };

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

            // Refraction
            float3 normal = UnpackNormal(tex2D (_BumpMap, IN.uv_BumpMap));
            float2 offset = normal.xy * _RefractAmount;
            IN.screenPos.xy += offset;

            half3 grabColor = tex2Dproj(_GrabTexture, IN.screenPos).rgb;

            o.Albedo = c.rgb;
            o.Emission = grabColor * _RefractAmount;
            o.Smoothness = _Glossiness;
            o.Normal = normal;
            o.Alpha = c.a * 0.8;
        }
        ENDCG
    }
    Fallback "Transparent/Cutout/VertexLit"
}

// 9. Vertex/Fragment Shader - Basic Unlit
Shader "Custom/BasicUnlit"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        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;
            fixed4 _Color;

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

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv) * _Color;
                return col;
            }
            ENDCG
        }
    }
}

// 10. Vertex Color Shader
Shader "Custom/VertexColor"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.color = v.color;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return i.color;
            }
            ENDCG
        }
    }
}
代码glsl中等

高级 Unity 着色器

复杂着色器效果,包括视差映射、曲面细分和高级光照模型

难度

7/10

预计时间

35 min

标签

unity, shader, advanced, parallax, tessellation

前置条件

Advanced shader programming, Mathematics, Graphics pipeline

glsl
// Advanced Unity Shaders - HLSL/Cg

// 1. Parallax Occlusion Mapping Shader
Shader "Custom/ParallaxOcclusion"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _BumpMap ("Normal Map", 2D) = "bump" {}
        _ParallaxMap ("Height Map", 2D) = "black" {}
        _Parallax ("Height Scale", Range(0.005, 0.08)) = 0.02
        _ParallaxMaxSteps ("Max Steps", Range(1, 50)) = 20
        _ParallaxRefractionSteps ("Refraction Steps", Range(1, 20)) = 10
        _Color ("Color", Color) = (1,1,1,1)
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _Glossiness ("Glossiness", Range(0,1)) = 0.5
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 300

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0
        #pragma shader_feature _PARALLAX_MAP

        sampler2D _MainTex;
        sampler2D _BumpMap;
        sampler2D _ParallaxMap;
        fixed4 _Color;
        half _Metallic;
        half _Glossiness;
        float _Parallax;
        int _ParallaxMaxSteps;
        int _ParallaxRefractionSteps;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpMap;
            float2 uv_ParallaxMap;
            float3 viewDir;
        };

        #if defined(_PARALLAX_MAP)
            float2 ParallaxOffset(float2 uv, float3 viewDir)
            {
                float h = tex2D(_ParallaxMap, uv).r;
                float height = h * _Parallax;
                float2 offset = viewDir.xy / (viewDir.z + 0.42);
                return uv - offset * height;
            }

            float2 RaymarchParallax(float2 uv, float3 viewDir)
            {
                float2 offset = 0;
                float stepSize = 1.0 / _ParallaxMaxSteps;

                for(int i = 0; i < _ParallaxMaxSteps; i++)
                {
                    float h = tex2D(_ParallaxMap, uv + offset).r;
                    float height = h * _Parallax;

                    if(height > (float)i / _ParallaxMaxSteps)
                    {
                        offset -= viewDir.xy / viewDir.z * stepSize * _Parallax;
                    }
                    else
                    {
                        break;
                    }
                }

                return uv + offset;
            }
        #endif

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            #if defined(_PARALLAX_MAP)
                float2 uv = RaymarchParallax(IN.uv_ParallaxMap, IN.viewDir);
            #else
                float2 uv = IN.uv_MainTex;
            #endif

            fixed4 c = tex2D (_MainTex, uv) * _Color;
            o.Albedo = c.rgb;
            o.Normal = UnpackNormal(tex2D (_BumpMap, uv));
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    Fallback "Standard"
}

// 2. Tessellation Shader
Shader "Custom/Tessellation"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _Tessellation ("Tessellation", Range(1,32)) = 4
        _MinDistance ("Min Distance", Range(1,20)) = 10
        _MaxDistance ("Max Distance", Range(20,100)) = 50
        _EdgeLength ("Edge Length", Range(2,50)) = 15
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows vertex:disp tessellate:tessEdge nolightmap
        #pragma hull hull_shader
        #pragma domain domain_shader
        #pragma target 4.6

        sampler2D _MainTex;
        fixed4 _Color;
        float _Tessellation;
        float _MinDistance;
        float _MaxDistance;
        float _EdgeLength;

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

        struct v2f
        {
            float4 vertex : SV_POSITION;
            float3 normal : NORMAL;
            float2 uv : TEXCOORD0;
        };

        float4 disp (appdata v)
        {
            return v.vertex;
        }

        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.normal = v.normal;
            o.uv = v.uv;
            return o;
        }

        #ifdef UNITY_CAN_COMPILE_TESSELLATION
            struct TessellationFactors
            {
                float edge[3] : SV_TessFactor;
                float inside : SV_InsideTessFactor;
            };

            struct HS_CONSTANT_OUTPUT
            {
                float edges[3] : SV_TessFactor;
                float inside : SV_InsideTessFactor;
            };

            HS_CONSTANT_OUTPUT hsConstant (InputPatch<appdata,3> v)
            {
                HS_CONSTANT_OUTPUT o;

                float4 p0 = UnityObjectToViewPos(v[0].vertex);
                float4 p1 = UnityObjectToViewPos(v[1].vertex);
                float4 p2 = UnityObjectToViewPos(v[2].vertex);

                float d0 = length(p0.xyz);
                float d1 = length(p1.xyz);
                float d2 = length(p2.xyz);

                float minDist = min(min(d0, d1), d2);
                float maxDist = max(max(d0, d1), d2);

                float dist = saturate((minDist - _MinDistance) / (_MaxDistance - _MinDistance));
                float factor = lerp(_Tessellation, 1, dist);

                o.edges[0] = factor;
                o.edges[1] = factor;
                o.edges[2] = factor;
                o.inside = factor;

                return o;
            }

            [domain("tri")]
            [partitioning("fractional_odd")]
            [outputtopology("triangle_cw")]
            [outputcontrolpoints(3)]
            [patchconstantfunc("hsConstant")]
            TessellationFactors hs (InputPatch<appdata,3> i, uint patchID : SV_PrimitiveID)
            {
                TessellationFactors o;
                o.edge[0] = 4;
                o.edge[1] = 4;
                o.edge[2] = 4;
                o.inside = 4;
                return o;
            }

            struct HS_OUTPUT
            {
                float4 vertex : SV_POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };

            [domain("tri")]
            DS_OUTPUT ds (TessellationFactors factors, OutputPatch<HS_OUTPUT,3> patch, float3 bary : SV_DomainLocation)
            {
                DS_OUTPUT o;

                float3 vertex =
                    patch[0].vertex * bary.x +
                    patch[1].vertex * bary.y +
                    patch[2].vertex * bary.z;

                float3 normal =
                    patch[0].normal * bary.x +
                    patch[1].normal * bary.y +
                    patch[2].normal * bary.z;

                float2 uv =
                    patch[0].uv * bary.x +
                    patch[1].uv * bary.y +
                    patch[2].uv * bary.z;

                o.vertex = vertex;
                o.normal = normal;
                o.uv = uv;

                return o;
            }
        #endif

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv) * _Color;
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    Fallback "Standard"
}

// 3. Fur Shader
Shader "Custom/Fur"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _FurLength ("Fur Length", Range(0.1, 1)) = 0.5
        _FurDensity ("Fur Density", Range(0.01, 1)) = 0.3
        _FurTiling ("Fur Tiling", float) = 1.0
        _FurGravity ("Gravity Force", Range(0,1)) = 0.5
        _FurColor ("Fur Color", Color) = (1,1,1,1)
        _Layers ("Layer Count", Range(1, 100)) = 20
    }

    SubShader
    {
        Tags { "RenderType"="TransparentCutout" }
        LOD 200
        Cull Off

        CGPROGRAM
        #pragma surface surf Lambert vertex:vert alpha:fade
        #pragma shader_feature _FURSHADER_ON

        sampler2D _MainTex;
        fixed4 _Color;
        float _FurLength;
        float _FurDensity;
        float _FurTiling;
        float _FurGravity;
        fixed4 _FurColor;
        int _Layers;

        struct Input
        {
            float2 uv_MainTex;
            float furLayer;
        };

        void vert(inout appdata_full v, out Input o)
        {
            UNITY_INITIALIZE_OUTPUT(Input);
            o.uv_MainTex = v.texcoord;
            o.furLayer = v.color.r; // Pass layer from vertex color
        }

        void surf (Input IN, inout SurfaceOutput o)
        {
            float2 uv = IN.uv_MainTex * _FurTiling + float2(IN.furLayer * 0.2, IN.furLayer * 0.3);
            float4 fur = tex2D(_MainTex, uv);

            // Alpha based on fur density and layer
            float alpha = fur.r;
            alpha = smoothstep(_FurDensity * (1.0 - IN.furLayer), 1.0, alpha);

            // Fur color variation
            fixed4 furColor = lerp(_Color, _FurColor, IN.furLayer * 0.5);

            o.Albedo = furColor.rgb;
            o.Alpha = alpha * (1.0 - IN.furLayer);
        }
        ENDCG

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma shader_feature _FURSHADER_ON

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
            };

            sampler2D _MainTex;
            float _FurLength;
            float _FurGravity;
            int _Layers;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float fur = tex2D(_MainTex, i.uv).r;
                float alpha = smoothstep(0.5, 1.0, fur);
                return fixed4(1, 1, 1, alpha);
            }
            ENDCG
        }
    }
}

// 4. Holographic Shader
Shader "Custom/Holographic"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _ScanLineSize ("Scan Line Size", Range(0.1, 10)) = 2.0
        _ScanLineSpeed ("Scan Line Speed", Range(-10, 10)) = 2.0
        _FlickerIntensity ("Flicker Intensity", Range(0, 1)) = 0.1
        _FlickerSpeed ("Flicker Speed", Range(1, 100)) = 50.0
        _GlowIntensity ("Glow Intensity", Range(0, 5)) = 2.0
    }

    SubShader
    {
        Tags {
            "Queue"="Transparent"
            "RenderType"="Transparent"
        }

        LOD 200
        Cull Off

        CGPROGRAM
        #pragma surface surf Lambert alpha:fade
        #pragma shader_feature _HOLOGRAM_SHADER_ON

        sampler2D _MainTex;
        fixed4 _Color;
        float _ScanLineSize;
        float _ScanLineSpeed;
        float _FlickerIntensity;
        float _FlickerSpeed;
        float _GlowIntensity;

        struct Input
        {
            float2 uv_MainTex;
            float3 worldPos;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            // Base texture
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

            // Scan lines
            float scanline = sin(IN.worldPos.y * _ScanLineSize + _Time.y * _ScanLineSpeed) * 0.5 + 0.5;
            scanline = pow(scanline, 2.0);

            // Flicker effect
            float flicker = sin(_Time.y * _FlickerSpeed) * 0.5 + 0.5;
            flicker = lerp(1.0, flicker, _FlickerIntensity);

            // Edge glow
            float edge = 1.0 - saturate(dot(IN.worldPos - _WorldSpaceCameraPos, IN.worldPos - _WorldSpaceCameraPos));

            // Combine effects
            c.rgb = c.rgb * scanline * flicker + c.rgb * _GlowIntensity * edge;

            o.Albedo = c.rgb;
            o.Alpha = c.a * scanline * flicker;
            o.Emission = c.rgb * _GlowIntensity * edge;
        }
        ENDCG
    }
    Fallback "Transparent/VertexLit"
}

// 5. Particle Shader with Soft Particles
Shader "Custom/SoftParticles"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
        _Softness ("Softness", Range(0,1)) = 0.5
    }

    SubShader
    {
        Tags {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
        }

        Blend SrcAlpha OneMinusSrcAlpha
        ColorMask RGB
        Cull Off Lighting Off ZWrite Off

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_particles

            #include "UnityCG.cginc"

            sampler2D _MainTex;
            fixed4 _Color;
            float _InvFade;
            float _Softness;

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                fixed4 color : COLOR;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                #ifdef SOFTPARTICLES_ON
                    float4 projPos : TEXCOORD2;
                #endif
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.color = v.color;

                #ifdef SOFTPARTICLES_ON
                    o.projPos = ComputeScreenPos(o.vertex);
                    COMPUTE_EYEDEPTH(o.projPos);
                #endif

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                #ifdef SOFTPARTICLES_ON
                    float sceneZ = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, i.projPos));
                    float partZ = i.projPos.z;
                    float fade = saturate(_InvFade * (sceneZ - partZ));
                    fade = pow(fade, 1.0 + _Softness);
                    i.color.a *= fade;
                #endif

                fixed4 c = tex2D(_MainTex, i.uv) * i.color * _Color;
                return c;
            }
            ENDCG
        }
    }
}
代码glsl复杂

后期处理着色器

屏幕空间效果,包括辉光、景深、运动模糊和屏幕过渡

难度

8/10

预计时间

45 min

标签

unity, shader, post processing, screen effects

前置条件

Expert shader programming, Render pipeline, Graphics math

glsl
// Unity Post-Processing Shaders

// 1. Bloom Effect Shader
Shader "Hidden/PostProcessing/Bloom"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Threshold ("Bloom Threshold", Range(0, 1)) = 0.5
        _Intensity ("Bloom Intensity", Range(0, 10)) = 1.0
        _BlurSize ("Blur Size", Range(1, 10)) = 3.0
        _Tint ("Bloom Tint", Color) = (1,1,1,1)
    }

    SubShader
    {
        Cull Off ZWrite Off ZTest Always

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

            sampler2D _MainTex;
            float4 _MainTex_TexelSize;
            float _Threshold;
            float _Intensity;
            int _BlurSize;
            fixed4 _Tint;

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

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 original = tex2D(_MainTex, i.uv);

                // Apply threshold
                fixed luminance = dot(original.rgb, fixed3(0.2126, 0.7152, 0.0722);
                fixed4 bloom = luminance > _Threshold ? original : fixed4(0,0,0,1);

                // Apply intensity and tint
                bloom *= _Intensity * _Tint;

                return bloom;
            }
            ENDCG
        }

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

            sampler2D _MainTex;
            float4 _MainTex_TexelSize;

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

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float2 texelSize = _MainTex_TexelSize.xy;
                float2 offset = texelSize * 2.0;

                fixed4 color = tex2D(_MainTex, i.uv);

                // Box blur
                for(int x = -2; x <= 2; x++)
                {
                    for(int y = -2; y <= 2; y++)
                    {
                        float2 offset = float2(x, y) * texelSize;
                        color += tex2D(_MainTex, i.uv + offset);
                    }
                }

                color /= 25.0; // Normalize by the number of samples

                return color;
            }
            ENDCG
        }

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

            sampler2D _MainTex;
            sampler2D _BloomTex;

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

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 original = tex2D(_MainTex, i.uv);
                fixed4 bloom = tex2D(_BloomTex, i.uv);

                return original + bloom;
            }
            ENDCG
        }
    }
}

// 2. Depth of Field Shader
Shader "Hidden/PostProcessing/DepthOfField"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _FocalDepth ("Focal Depth", Range(0, 1)) = 0.5
        _FocalRange ("Focal Range", Range(0, 1)) = 0.1
        _MaxBlurSize ("Max Blur Size", Range(0, 10)) = 5.0
        _Aperture ("Aperture", Range(0.1, 10)) = 2.8
    }

    SubShader
    {
        Cull Off ZWrite Off ZTest Always

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

            sampler2D _MainTex;
            sampler2D _CameraDepthTexture;
            float4 _MainTex_TexelSize;
            float _FocalDepth;
            float _FocalRange;
            float _MaxBlurSize;
            float _Aperture;
            float4 _ProjectionParams;

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

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.uvDepth = ComputeScreenPos(o.vertex).xy / ComputeScreenPos(o.vertex).w;
                return o;
            }

            float LinearEyeDepth(float z)
            {
                return -Linear01Depth(z) * _ProjectionParams.z;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // Get scene depth
                float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uvDepth);
                float sceneDepth = LinearEyeDepth(depth);
                float focalPlane = _FocalDepth * _ProjectionParams.z;

                // Calculate circle of confusion
                float coc = abs(sceneDepth - focalPlane) / _FocalRange * _Aperture;
                coc = saturate(coc);

                // Apply blur based on CoC
                float blurSize = coc * _MaxBlurSize;

                fixed4 color = tex2D(_MainTex, i.uv);

                if(blurSize > 1.0)
                {
                    // Box blur
                    float2 texelSize = _MainTex_TexelSize.xy;
                    int blurRadius = (int)blurSize;

                    fixed4 blurredColor = fixed4(0,0,0,0);
                    int sampleCount = 0;

                    for(int x = -blurRadius; x <= blurRadius; x++)
                    {
                        for(int y = -blurRadius; y <= blurRadius; y++)
                        {
                            if(x*x + y*y <= blurRadius * blurRadius)
                            {
                                float2 offset = float2(x, y) * texelSize;
                                blurredColor += tex2D(_MainTex, i.uv + offset);
                                sampleCount++;
                            }
                        }
                    }

                    blurredColor /= sampleCount;

                    // Blend based on CoC
                    color = lerp(color, blurredColor, coc);
                }

                return color;
            }
            ENDCG
        }
    }
}

// 3. Motion Blur Shader
Shader "Hidden/PostProcessing/MotionBlur"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _VelocityScale ("Velocity Scale", Range(0, 2)) = 1.0
        _MaxVelocity ("Max Velocity", Range(0, 10)) = 5.0
        _NumSamples ("Number of Samples", Range(4, 32)) = 16
    }

    SubShader
    {
        Cull Off ZWrite Off ZTest Always

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

            sampler2D _MainTex;
            sampler2D _VelocityTex;
            float2 _MainTex_TexelSize;
            float _VelocityScale;
            float _MaxVelocity;
            int _NumSamples;

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

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // Get velocity vector
                float2 velocity = tex2D(_VelocityTex, i.uv).rg * 2.0 - 1.0;
                velocity *= _VelocityScale;

                // Limit velocity
                float velocityLength = length(velocity);
                if(velocityLength > _MaxVelocity)
                {
                    velocity = normalize(velocity) * _MaxVelocity;
                }

                // Motion blur
                float2 texelSize = _MainTex_TexelSize.xy;
                fixed4 blurredColor = fixed4(0,0,0,0);
                float totalWeight = 0.0;

                for(int j = 0; j < _NumSamples; j++)
                {
                    float t = (float)j / (_NumSamples - 1) - 0.5;
                    float2 sampleUV = i.uv + velocity * texelSize * t;

                    // Weight based on distance from center
                    float weight = 1.0 - abs(t);
                    blurredColor += tex2D(_MainTex, sampleUV) * weight;
                    totalWeight += weight;
                }

                blurredColor /= totalWeight;

                return blurredColor;
            }
            ENDCG
        }
    }
}

// 4. Screen Transition Shader
Shader "Hidden/PostProcessing/ScreenTransition"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _TransitionTex ("Transition Texture", 2D) = "white" {}
        _NextTex ("Next Texture", 2D) = "white" {}
        _Progress ("Transition Progress", Range(0, 1)) = 0.0
        _TransitionType ("Transition Type", Range(0, 4)) = 0
        _EdgeWidth ("Edge Width", Range(0, 0.5)) = 0.1
        _EdgeSoftness ("Edge Softness", Range(0, 0.5)) = 0.05
    }

    SubShader
    {
        Cull Off ZWrite Off ZTest Always

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

            sampler2D _MainTex;
            sampler2D _TransitionTex;
            sampler2D _NextTex;
            float _Progress;
            int _TransitionType;
            float _EdgeWidth;
            float _EdgeSoftness;

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

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            float FadeTransition(float progress)
            {
                return progress;
            }

            float WipeTransition(float2 uv, float progress)
            {
                return progress > uv.x ? 1.0 : 0.0;
            }

            float CircleTransition(float2 uv, float progress)
            {
                float2 center = float2(0.5, 0.5);
                float distance = length(uv - center);
                return distance > (1.0 - progress) ? 1.0 : 0.0;
            }

            float DiagonalWipeTransition(float2 uv, float progress)
            {
                float2 diagonal = float2(1.0, 1.0);
                float diagonalPos = dot(uv, normalize(diagonal));
                return diagonalPos > progress ? 1.0 : 0.0;
            }

            float RandomTransition(float2 uv, float progress)
            {
                float noise = tex2D(_TransitionTex, uv).r;
                return noise > progress ? 1.0 : 0.0;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float transitionValue = 0.0;

                switch(_TransitionType)
                {
                    case 0: // Fade
                        transitionValue = FadeTransition(_Progress);
                        break;
                    case 1: // Wipe
                        transitionValue = WipeTransition(i.uv, _Progress);
                        break;
                    case 2: // Circle
                        transitionValue = CircleTransition(i.uv, _Progress);
                        break;
                    case 3: // Diagonal Wipe
                        transitionValue = DiagonalWipeTransition(i.uv, _Progress);
                        break;
                    case 4: // Random Noise
                        transitionValue = RandomTransition(i.uv, _Progress);
                        break;
                }

                // Edge smoothing
                float edge = smoothstep(_Progress - _EdgeSoftness, _Progress + _EdgeSoftness, transitionValue);
                edge = smoothstep(_Progress - _EdgeWidth - _EdgeSoftness,
                                 _Progress - _EdgeWidth + _EdgeSoftness, edge);

                fixed4 currentColor = tex2D(_MainTex, i.uv);
                fixed4 nextColor = tex2D(_NextTex, i.uv);

                // Blend between scenes
                fixed4 finalColor = lerp(nextColor, currentColor, edge);

                return finalColor;
            }
            ENDCG
        }
    }
}

// 5. Vignette Effect Shader
Shader "Hidden/PostProcessing/Vignette"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _VignetteIntensity ("Vignette Intensity", Range(0, 2)) = 1.0
        _VignetteRadius ("Vignette Radius", Range(0, 2)) = 0.8
        _VignetteSmoothness ("Vignette Smoothness", Range(0, 1)) = 0.1
        _VignetteColor ("Vignette Color", Color) = (0,0,0,1)
    }

    SubShader
    {
        Cull Off ZWrite Off ZTest Always

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

            sampler2D _MainTex;
            float _VignetteIntensity;
            float _VignetteRadius;
            float _VignetteSmoothness;
            fixed4 _VignetteColor;

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

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 originalColor = tex2D(_MainTex, i.uv);

                // Calculate vignette
                float2 center = float2(0.5, 0.5);
                float dist = distance(i.uv, center);

                float vignette = 1.0 - smoothstep(_VignetteRadius, _VignetteRadius + _VignetteSmoothness, dist);
                vignette = saturate(vignette * _VignetteIntensity);

                // Apply vignette
                fixed3 vignetteColor = lerp(_VignetteColor.rgb, originalColor.rgb, vignette);

                return fixed4(vignetteColor, originalColor.a);
            }
            ENDCG
        }
    }
}

工具

经常与该案例搭配使用的工具

相关内容

相关案例集合

工具使用指南

帮助搜索与理解工作流的案例说明

标题

Unity Shader 示例

描述

Unity HLSL着色器示例,包括表面着色器、顶点/片段着色器和后期处理效果

概览

Unity HLSL着色器示例,包括表面着色器、顶点/片段着色器和后期处理效果

适用场景

  • Use this sample set when you want reference inputs for Unity Shader 示例.
  • Use it to preview output formats and compare related sample variants.

使用方式

  1. 1Open a sample entry to inspect the prepared example payload or asset.
  2. 2Compare it with related tools to understand how the workflow connects.

常见用途

  • 基础 Unity 着色器
  • 高级 Unity 着色器
  • 后期处理着色器

常见问题

What is included in Unity Shader 示例?

This page includes curated sample entries, related tools, and neighboring sample collections for Unity Shader 示例.

首页
工具3197
案例593
可视化461
文件查看器103
专题229
标签333
图像、音频与视频655

图像、音频、视频处理、转换与优化工具

数学、日期与金融644

计算器、数值计算、日期逻辑、统计与金融工具

设计与颜色296

颜色、版式、图形、视觉样式与设计辅助工具

文本与写作209

写作、清洗、格式化、提取与文本分析工具

开发与 Web193

开发者工具、网络处理、Web 调试与自动化辅助工具

转换与编码175

格式、文件、压缩包、单位与编码转换工具

界面截图结构化、人工校对与开发交付
钢琴旋律草稿创作、MIDI 核验与试听样稿交付
复古游戏纹理制作、候选评审与素材交付
操作截图到可复核图文指南与培训交付
网页改版响应式视觉回归审核与证据交付

© 2026 Elysia Tools. 保留所有权利。

文档价格关于我们服务条款隐私政策Cookie 政策联系我们

Development

HTML标签参考

完整的HTML5标准标签参考指南,包含分类和描述

AI Tools

AI 年龄与性别估计

对检测到的人脸进行年龄与性别预测

AI Tools

AI 人脸比对 (1:1)

对比两张图片的人脸,输出距离与匹配结果, 仅对比每张图片中的第一个人脸

AI Tools

AI 人脸检测

检测图片中的人脸并返回边框坐标

AI Tools

AI 表情识别

识别每张人脸的表情(平静/高兴/悲伤/愤怒/害怕/厌恶/惊讶)

AI Tools

AI 人脸关键点

检测面部 68 个关键点并返回坐标

Development

API 破坏性变更检测与迁移规划器

对比两份 OpenAPI 3.x schema,识别 breaking changes 并给出影响评级与迁移建议

Development

数组分组器

根据各种条件对数组元素进行分组,如长度、字母顺序、数值范围、自定义条件等

游戏开发

Unity C# 脚本示例

Unity C#脚本示例,涵盖玩家移动、UI系统、物理、动画和游戏机制

游戏开发

Bevy 游戏引擎示例

Bevy Rust 游戏引擎示例,包含 ECS、2D/3D 图形、音频和游戏机制实现

游戏开发

Phaser.js 示例

Phaser.js游戏引擎示例,包括2D游戏、动画、物理、精灵和交互式游戏机制