【Unity Shader编程】之顶点着色器
来一张AI提供的资料
在shader编程中,定义的结构体,有些是会被自动赋值,有些是必须要手动赋值的,这就涉及到了语义,
例如
struct appdata
{
float4 vertex : POSITION;
float vertex2;
float2 uv : TEXCOORD0;
};
结构体里面定义的两个变量 vertex和uv,后面加了POSITION和TEXCORD0两个语义,就赋予了他们不同的特殊功能,他们会被自动赋值,而vertex2就是一个普通的变量了。
下面是语义表
**
一,坐标空间转换
空间转换中,一般有五个空间转换,模型空间→世界空间→视图空间→裁剪空间→NDC空间(其次坐标空间,执行其次坐标后的空间)→屏幕空间**
核心原则
1,数据依赖原则
当逻辑需要相对坐标系属性(如模型UV、顶点色)时,优先在模型空间处理(如gl_Vertex变换前)
当逻辑依赖全局交互状态(如光照方向、物理碰撞)时,必须转换到世界空间后处理
2,性能优化准则
在顶点着色器阶段处理空间转换(如UNITY_MATRIX_MVP),利用GPU并行性在片段着色器中避免重复坐标转换,通过TEXCOORD传递预处理数据
3,精度控制策略
高精度计算(如物理模拟)应在世界空间使用double类型
视觉效果类计算(如雾效)可在视图空间使用float类型
空间转换代码
Shader "SpaceTransform/BasicChain"
{
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
float4 worldPos : TEXCOORD0;
float4 viewPos : TEXCOORD1;
};
v2f vert (appdata v) {
v2f o;
// 模型空间 → 世界空间
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
// 世界空间 → 视图空间
o.viewPos = mul(UNITY_MATRIX_V, o.worldPos);
// 视图空间 → 裁剪空间
o.pos = mul(UNITY_MATRIX_P, o.viewPos);
return o;
}
fixed4 frag (v2f i) : SV_Target {
return fixed4(1,1,1,1); // 纯白输出
}
ENDCG
}
}
}
2,顶点动态变化
顶点动态变化日常会使用到的功能如下
-
基础正弦波波动例子(模型空间)
v2f vert (appdata v) { v2f o; float4 worldPos = mul(unity_ObjectToWorld, v.vertex); // Y轴波动计算(频率_Hz,振幅_Amp) float wave = _Amp * sin(_Time.y * _Hz + worldPos.x * _WaveDensity); v.vertex.y += wave; o.vertex = UnityObjectToClipPos(v.vertex); return o; }
后续效果相对复杂,这边大概讲入门,就不全部细说