ShaderLab 关键点记录
ShaderLab 是 Unity 中用于编写着色器的语言。着色器是运行在 GPU 上的程序,负责处理渲染流水线中的各种图形计算。理解 ShaderLab 的关键概念和技术细节,对于开发高效、复杂的图形效果至关重要。本文将详细记录 ShaderLab 的关键点,帮助开发者深入掌握这门语言。
ShaderLab 基础
1. ShaderLab 结构
一个 ShaderLab 文件通常由以下几个部分组成:
- Shader 名称:定义着色器的名称。
- Properties:定义着色器可调节的属性。
- SubShader:定义具体的渲染过程。
- Pass:定义一个渲染通道。
示例结构:
Shader "Custom/MyShader" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Main Color", Color) = (1,1,1,1)
}
SubShader {
Pass {
// Shader code here
}
}
FallBack "Diffuse"
}
2. Properties
Properties
用于在 Inspector 窗口中暴露变量,方便调节。常见类型包括:
- Color:颜色。
- Vector:向量。
- Range:范围值。
- Float:浮点数。
- 2D:2D 纹理。
示例:
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_MainTex ("Texture", 2D) = "white" {}
_Shininess ("Shininess", Range(0.03, 1)) = 0.078125
}
3. SubShader 和 Pass
SubShader
包含一个或多个 Pass
,每个 Pass
代表一个渲染步骤。
- SubShader:用于定义多种渲染路径,以适应不同的硬件。
- Pass:包含具体的渲染指令。
示例:
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// Vertex and fragment shader code
ENDCG
}
}
CG/HLSL 代码
ShaderLab 中嵌入的 CG 或 HLSL 代码用于编写具体的顶点和片段着色器。
1. 顶点着色器
顶点着色器负责处理顶点属性,如位置、法线等。
示例:
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 normal : TEXCOORD0;
};
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.normal = v.normal;
return o;
}
2. 片段着色器
片段着色器负责计算每个像素的颜色。
示例:
float4 frag (v2f i) : SV_Target {
return float4(i.normal, 1.0);
}
常用指令和技巧
1. #pragma 指令
用于控制编译器行为,如定义顶点和片段着色器入口。
#pragma vertex vert
:定义顶点着色器入口。#pragma fragment frag
:定义片段着色器入口。
2. 内置变量
Unity 提供了一些内置变量,方便在着色器中使用。
UNITY_MATRIX_MVP
:模型视图投影矩阵。unity_ObjectToWorld
:对象到世界坐标的变换矩阵。
3. 纹理采样
使用 tex2D
函数进行纹理采样。
示例:
sampler2D _MainTex;
float4 frag (v2f i) : SV_Target {
float4 texColor = tex2D(_MainTex, i.uv);
return texColor;
}
4. 多通道渲染
使用多个 Pass
进行复杂的多通道渲染。
示例:
SubShader {
Pass {
// First pass
}
Pass {
// Second pass
}
}
实用例子:Phong 着色器
一个简单的 Phong 着色器示例,展示了基本的光照计算。
Shader "Custom/PhongShader" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Color ("Main Color", Color) = (1,1,1,1)
_Shininess ("Shininess", Range(0.03, 1)) = 0.078125
}
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float3 normal : TEXCOORD0;
float2 uv : TEXCOORD1;
};
sampler2D _MainTex;
float4 _Color;
float _Shininess;
v2f vert (appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.normal = UnityObjectToWorldNormal(v.normal);
o.uv = v.uv;
return o;
}
float4 frag (v2f i) : SV_Target {
float3 normal = normalize(i.normal);
float3 lightDir = normalize(float3(0.0, 0.0, 1.0));
float3 viewDir = normalize(float3(0.0, 0.0, 1.0));
// Diffuse
float diff = max(dot(normal, lightDir), 0.0);
// Specular
float3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), _Shininess);
// Texture and color
float4 texColor = tex2D(_MainTex, i.uv);
float4 color = _Color * texColor;
color.rgb *= diff;
color.rgb += spec;
return color;
}
ENDCG
}
}
FallBack "Diffuse"
}
分析说明表
关键点 | 说明 | 示例代码 |
---|---|---|
ShaderLab 结构 | 定义着色器的基本结构,包括名称、属性和渲染过程 | Shader "Custom/MyShader" |
Properties | 定义在 Inspector 中暴露的变量 | _MainTex ("Texture", 2D) = "white" {} |
SubShader 和 Pass | 定义具体的渲染步骤 | SubShader { Pass { CGPROGRAM ... ENDCG } } |
顶点着色器 | 处理顶点属性,如位置和法线 | v2f vert (appdata v) |
片段着色器 | 计算每个像素的颜色 | float4 frag (v2f i) : SV_Target |
#pragma 指令 | 控制编译器行为,定义着色器入口 | #pragma vertex vert |
内置变量 | Unity 提供的内置变量,方便在着色器中使用 | UNITY_MATRIX_MVP |
纹理采样 | 使用 tex2D 函数进行纹理采样 |
float4 texColor = tex2D(_MainTex, i.uv) |
多通道渲染 | 使用多个 Pass 进行复杂的渲染 |
SubShader { Pass { ... } Pass { ... } } |
总结
ShaderLab 是 Unity 中创建和管理着色器的核心工具。通过理解其基本结构、常用属性和关键技术,开发者可以创建出各种复杂的图形效果。从基础的颜色和纹理处理,到高级的光照和多通道渲染,ShaderLab 提供了强大的功能和灵活性。希望本文记录的关键点能帮助您更好地掌握 ShaderLab,提高图形编程的效率和效果。