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"
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现