Files
engine/docs/zh/graphics/material/examples/shaderlab-01-basic-shader.mdx
zhuxudong 8d57c2c6df Refactor shader document (#2833)
* docs: refactor shader document and add shader101 guide
2025-09-19 16:11:48 +08:00

208 lines
5.0 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 基础着色器语法
---
本教程将通过一个简单的纹理渲染着色器,介绍 ShaderLab 的基础语法结构,通过这个基础示例,你将学会:
- ShaderLab 的基本结构
- 如何声明变量和结构体
- 顶点着色器的基本变换
- 片元着色器的纹理采样
- UV 坐标的传递和使用
<Image
src="https://mdn.alipayobjects.com/huamei_dmxymu/afts/img/A*Ykx2T7IuiAIAAAAAT0AAAAgAeuuHAQ/original"
/>
## 着色器结构
ShaderLab 采用三层嵌套结构:`Shader` → `SubShader` → `Pass`
```glsl
Shader "Tutorial/01-BasicShader" {
SubShader "Default" {
Pass "Forward" {
// 着色器代码写在这里
}
}
}
```
- **Shader**:着色器的根节点,定义着色器名称
- **SubShader**:着色器的变体,可以有多个,引擎会选择最适合的
- **Pass**:渲染通道,定义具体的渲染逻辑
## 变量声明
在 Pass 中,我们需要声明着色器使用的变量:
```glsl
// 引擎内置变量MVP 变换矩阵
mat4 renderer_MVPMat;
// 自定义材质属性
vec4 material_BaseColor; // 基础颜色
sampler2D material_BaseTexture; // 纹理采样器
```
## 结构体定义
使用结构体定义顶点数据和传递数据:
```glsl
// 顶点着色器输入(从网格获取)
struct Attributes {
vec4 POSITION; // 顶点位置
vec2 TEXCOORD_0; // UV 坐标
};
// 顶点着色器输出 / 片元着色器输入
struct Varyings {
vec2 uv; // 传递给片元着色器的 UV 坐标
};
```
**内置顶点属性**
- `POSITION`:顶点位置
- `TEXCOORD_0`第一套UV坐标
- `NORMAL`:顶点法线
- `COLOR_0`:顶点颜色
## 着色器入口函数
指定顶点着色器和片元着色器的入口函数:
```glsl
VertexShader = vert; // 顶点着色器入口
FragmentShader = frag; // 片元着色器入口
```
## 顶点着色器
顶点着色器负责处理每个顶点的变换:
```glsl
Varyings vert(Attributes attr) {
Varyings output;
// MVP 变换:将顶点从模型空间变换到裁剪空间
gl_Position = renderer_MVPMat * attr.POSITION;
// 传递 UV 坐标给片元着色器
output.uv = attr.TEXCOORD_0;
return output;
}
```
**关键点**
- `gl_Position` 是内置输出变量,必须赋值
- 返回的结构体数据会传递给片元着色器
## 片元着色器
片元着色器负责计算每个像素的颜色:
```glsl
void frag(Varyings varying) {
// 从纹理中采样颜色
vec4 texColor = texture2D(material_BaseTexture, varying.uv);
// 与材质基础颜色相乘
vec4 finalColor = texColor * material_BaseColor;
// 输出最终颜色
gl_FragColor = finalColor;
}
```
**关键点**
- `texture2D()` 函数用于纹理采样
- `gl_FragColor` 是内置输出变量,表示像素最终颜色
- 颜色运算支持向量运算
## 纹理采样
纹理采样是着色器中的常见操作:
```glsl
// 声明纹理采样器
sampler2D material_BaseTexture;
// 在片元着色器中采样
vec4 texColor = texture2D(material_BaseTexture, uv);
```
**采样参数**
- 第一个参数:纹理采样器
- 第二个参数UV坐标vec2类型
## 完整示例解析
让我们分析完整的着色器代码:
```glsl showLineNumbers {}
Shader "Tutorial/01-BasicShader" {
SubShader "Default" {
// Pass 是渲染通道,定义具体的渲染逻辑
Pass "Forward" {
// 引擎内置的 MVP 矩阵,用于顶点变换
mat4 renderer_MVPMat;
// 自定义的材质属性
vec4 material_BaseColor;
sampler2D material_BaseTexture;
// 顶点着色器输入结构体 (Attributes)
struct Attributes {
vec4 POSITION; // 顶点位置
vec2 TEXCOORD_0; // UV 坐标
};
// 顶点着色器输出 / 片元着色器输入结构体 (Varyings)
struct Varyings {
vec2 uv; // 传递给片元着色器的 UV 坐标
};
// 指定着色器入口函数
VertexShader = vert;
FragmentShader = frag;
// 顶点着色器:处理顶点变换和数据传递
Varyings vert(Attributes attr) {
Varyings output;
// 将顶点从模型空间变换到裁剪空间
gl_Position = renderer_MVPMat * attr.POSITION;
// 传递 UV 坐标给片元着色器
output.uv = attr.TEXCOORD_0;
return output;
}
// 片元着色器:计算每个像素的最终颜色
void frag(Varyings varying) {
// 从纹理中采样颜色
vec4 texColor = texture2D(material_BaseTexture, varying.uv);
// 与材质基础颜色相乘
vec4 finalColor = texColor * material_BaseColor;
// 输出最终颜色
gl_FragColor = finalColor;
}
}
}
}
```
## 运行效果
这个着色器会:
1. 将3D模型的顶点变换到屏幕空间
2. 传递UV坐标到片元着色器
3. 对纹理进行采样
4. 将纹理颜色与基础颜色相乘得到最终颜色
前往 [游乐场](/examples/shaderlab-01-basic-shader)