Unity Shader 顶点着色器实战案例
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
}
}
}