当前位置:首页 > 技术 > 正文内容

Unity Shader 顶点着色器实战案例

访客 技术 2026年7月2日 1

1. 基于顶点的凸起形变效果

通过修改顶点高度实现局部隆起,利用距离计算控制影响范围。


Shader "Custom/VertexBump" {
    Properties {
        _Radius ("Bump Radius", Range(0, 5)) = 1.0
        _OffsetX ("Horizontal Offset", Range(-5, 5)) = 0.0
    }
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex Vert
            #pragma fragment Frag
            #include "UnityCG.cginc"

            float _Radius;
            float _OffsetX;

            struct Input {
                float4 vertex : POSITION;
            };

            struct Output {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            Output Vert(Input v) {
                float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
                float2 center = float2(_OffsetX, 0);
                float2 xy = worldPos.xz;
                float dist = _Radius - length(xy - center);
                dist = max(0, dist);

                float4 displaced = float4(v.vertex.x, dist, v.vertex.z, v.vertex.w);
                Output o;
                o.pos = UnityObjectToClipPos(displaced);
                o.color = fixed4(dist / _Radius, dist / _Radius, dist / _Radius, 1.0);
                return o;
            }

            fixed4 Frag(Output i) : SV_Target {
                return i.color;
            }
            ENDCG
        }
    }
}

2. 动态渐变与高光流动效果

基于时间变量在特定区间内渲染红色高光,其余区域为灰度渐变。


Shader "Custom/FlowEffect" {
    Properties {
        _Width ("Flow Width", Range(0, 1)) = 0.1
    }
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex Vert
            #pragma fragment Frag
            #include "UnityCG.cginc"

            float _Width;

            struct Input {
                float4 vertex : POSITION;
            };

            struct Output {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            Output Vert(Input v) {
                Output o;
                o.pos = UnityObjectToClipPos(v.vertex);
                float x = o.pos.x / o.pos.w;
                float timeOffset = _SinTime.y * 2.0;
                if (x > timeOffset && x < timeOffset + _Width)
                    o.color = fixed4(1, 0, 0, 1);
                else
                    o.color = fixed4(x * 0.5 + 0.5, x * 0.5 + 0.5, x * 0.5 + 0.5, 1);
                return o;
            }

            fixed4 Frag(Output i) : SV_Target {
                return i.color;
            }
            ENDCG
        }
    }
}

3. 顶点空间扭曲——边界波纹

通过非线性矩阵变形使模型边缘产生波动形变。


Shader "Custom/WaveDistortion" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex Vert
            #pragma fragment Frag
            #include "UnityCG.cginc"

            struct Input {
                float4 vertex : POSITION;
            };

            struct Output {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            Output Vert(Input v) {
                float time = _Time.y + v.vertex.z;
                float waveFactor = sin(time) * 0.125 + 0.5;

                float4x4 transformMatrix = {
                    waveFactor, 0, 0, 0,
                    0, 1, 0, 0,
                    0, 0, 1, 0,
                    0, 0, 0, 1
                };

                v.vertex = mul(transformMatrix, v.vertex);

                Output o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color = fixed4(0, 1, 1, 1);
                return o;
            }

            fixed4 Frag(Output i) : SV_Target {
                return i.color;
            }
            ENDCG
        }
    }
}

4. 多种波形模拟:旗帜、涟漪、水波

使用正弦函数叠加生成复杂动态波形。


Shader "Custom/WavePatterns" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex Vert
            #pragma fragment Frag
            #include "UnityCG.cginc"

            struct Input {
                float4 vertex : POSITION;
            };

            struct Output {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            Output Vert(Input v) {
                // 旗帜波:沿X方向波动
                // v.vertex.y += 0.2 * sin(v.vertex.x + _Time.y);

                // 涟漪波:以原点为中心向外扩散
                // v.vertex.y += 0.2 * sin(-length(v.vertex.xz) * 2 + _Time.y);

                // 水波:双方向叠加形成交叉波纹
                v.vertex.y += 0.2 * sin((v.vertex.x + v.vertex.z) + _Time.y);
                v.vertex.y += 0.3 * sin((v.vertex.x - v.vertex.z) + _Time.w);

                Output o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.color = fixed4(v.vertex.y, v.vertex.y, v.vertex.y, 1);
                return o;
            }

            fixed4 Frag(Output i) : SV_Target {
                return i.color;
            }
            ENDCG
        }
    }
}

5. 漫反射 + 环境光基础光照

在顶点阶段完成法线与光源方向计算,实现基础光照模型。


Shader "Custom/DiffuseLighting" {
    SubShader {
        Pass {
            Tags { "LightMode" = "ForwardBase" }
            CGPROGRAM
            #pragma vertex Vert
            #pragma fragment Frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct Input {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct Output {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            Output Vert(Input v) {
                Output o;
                o.pos = UnityObjectToClipPos(v.vertex);

                float3 worldNormal = normalize(mul(float4(v.normal, 0), unity_WorldToObject).xyz);
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                float NdotL = saturate(dot(worldNormal, lightDir));

                o.color = _LightColor0 * NdotL;

                // 添加点光源贡献
                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                o.color.rgb += Shade4PointLights(
                    unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
                    unity_LightColor[0].rgb, unity_LightColor[1].rgb,
                    unity_LightColor[2].rgb, unity_LightColor[3].rgb,
                    unity_4LightAtten0,
                    worldPos, worldNormal
                );

                return o;
            }

            fixed4 Frag(Output i) : SV_Target {
                return i.color + UNITY_LIGHTMODEL_AMBIENT;
            }
            ENDCG
        }
    }
}

6. 高光反射实现(镜面高光)

基于反射向量与视线向量夹角计算高光强度。


Shader "Custom/SpecularHighlight" {
    SubShader {
        Pass {
            Tags { "LightMode" = "ForwardBase" }
            CGPROGRAM
            #pragma vertex Vert
            #pragma fragment Frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct Input {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct Output {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            Output Vert(Input v) {
                Output o;
                o.pos = UnityObjectToClipPos(v.vertex);

                float3 worldNormal = normalize(mul(float4(v.normal, 0), unity_WorldToObject).xyz);
                float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                float3 viewDir = WorldSpaceViewDir(v.vertex);

                float NdotL = saturate(dot(worldNormal, lightDir));
                o.color = _LightColor0 * NdotL;

                // 计算高光
                float3 reflectDir = reflect(-lightDir, worldNormal);
                float3 viewReflect = normalize(reflectDir);
                float3 viewDirNorm = normalize(viewDir);
                float specular = pow(saturate(dot(viewReflect, viewDirNorm)), 10);
                o.color.rgb += _LightColor0.rgb * specular;

                return o;
            }

            fixed4 Frag(Output i) : SV_Target {
                return i.color + UNITY_LIGHTMODEL_AMBIENT;
            }
            ENDCG
        }
    }
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。