mirror of
https://github.com/galacean/engine.git
synced 2026-07-02 10:34:29 +08:00
208 lines
5.0 KiB
Plaintext
208 lines
5.0 KiB
Plaintext
---
|
||
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) |