ShaderLab 是 Galacean 针对 Shader 自主研发的一套描述语言,它提供了一套完整的语法来定义着色器的结构、属性、渲染状态和着色器代码。通过 ShaderLab,开发者可以创建从简单到复杂的各种视觉效果。
ShaderLab 是一种声明式的着色器描述语言,它将着色器的各个组成部分组织成模块化的结构。与传统的 GLSL/HLSL 不同,ShaderLab 不仅包含着色器代码,还包含材质属性定义、UI界面配置、渲染状态设置等完整信息。
ShaderLab 框架主要解决以下传统着色器开发中的痛点:
Shader "Custom/MyShader" {
// -------------------- 编辑器配置区 --------------------
Editor {
Properties {
material_BaseColor("基础颜色", Color) = (1, 1, 1, 1);
material_BaseTexture("基础纹理", Texture2D);
material_Metallic("金属度", Range(0, 1, 0.01)) = 0.0;
material_Roughness("粗糙度", Range(0, 1, 0.01)) = 1.0;
Header("高级选项") {
material_EmissiveColor("自发光", Color) = (0, 0, 0, 1);
material_NormalTexture("法线贴图", Texture2D);
}
}
Macros {
[Off] HAS_VERTEX_COLOR("顶点颜色");
[On] ENABLE_NORMAL_MAP("法线贴图", Boolean) = false;
}
UIScript "path/to/script.ts";
}
// -------------------- 全局变量声明区 --------------------
struct Attributes {
vec3 POSITION;
vec2 TEXCOORD_0;
};
struct Varyings {
vec2 uv;
};
// 声明全局材质属性
vec4 material_BaseColor;
sampler2D material_BaseTexture;
mat4 renderer_MVPMat;
// 声明全局渲染状态
BlendState customBlendState {
Enabled = true;
SourceColorBlendFactor = BlendFactor.SourceAlpha;
DestinationColorBlendFactor = BlendFactor.OneMinusSourceAlpha;
SourceAlphaBlendFactor = BlendFactor.One;
DestinationAlphaBlendFactor = BlendFactor.OneMinusSourceAlpha;
};
// -------------------- SubShader 定义区 --------------------
SubShader "Default" {
// 引入阴影投射 Pass
UsePass "pbr/Default/ShadowCaster"
// 自定义 Pass
Pass "Forward Pass" {
// 指定 Shader Tag, 管线根据不同配置调用
Tags { "pipelineStage" = "Forward" }
// 声明局部渲染状态
DepthState customDepthState {
Enabled = true;
WriteEnabled = true;
CompareFunction = CompareFunction.LessEqual;
}
// 使用全局渲染状态
BlendState = customBlendState;
// 使用局部渲染状态
DepthState = customDepthState;
// 代码段引用
#include "Common.glsl"
// 指定 顶点、片元 入口
VertexShader = PBRVertex;
FragmentShader = PBRFragment;
// 顶点着色器代码编写
Varyings vert(Attributes input) {
Varyings output;
output.uv = input.TEXCOORD_0;
gl_Position = renderer_MVPMat * vec4(input.POSITION, 1.0);
return output;
}
// 片元着色器代码编写
void frag(Varyings input) {
vec4 baseColor = material_BaseColor;
#ifdef MATERIAL_HAS_BASETEXTURE
baseColor *= texture2D(material_BaseTexture, input.uv);
#endif
gl_FragColor = baseColor;
}
}
}
}Shader 模块是 ShaderLab 的根模块,定义着色器的基本信息和全局设置:
Shader "Custom/MyShader" {
// 全局变量声明
// Editor 配置
// SubShader 定义
}功能特性:
Editor 模块定义材质属性面板和交互逻辑:


支持的属性类型:
| 类型 | 语法示例 | 描述 |
|---|---|---|
Boolean | property("描述", Boolean) = true | 布尔开关 |
Int | property("描述", Int) = 1 | 整数 |
Float | property("描述", Float) = 0.5 | 浮点数 |
Range | property("描述", Range(0, 1, 0.01)) = 0.5 | 范围滑块 |
Color | property("描述", Color) = (1, 1, 1, 1) | 颜色选择器 |
Vector2/3/4 | property("描述", Vector4) = (1, 1, 1, 1) | 向量输入 |
Texture2D | property("描述", Texture2D) | 2D纹理 |
TextureCube | property("描述", TextureCube) | 立方体纹理 |
Enum | property("描述", Enum(A:0, B:1)) = 0 | 枚举选择 |
支持的宏类型:
宏也可以反射到编辑器面板中,从而在编辑器中对 Shader 依赖的宏进行灵活的调整,当然我们更推荐通过 UIScript 脚本系统来实现宏的自动切换:
// 开启/关闭
[On/Off]macroName("MacroLabel", EditType) = [DefaultValue];通过[On/Off]指令指定宏的默认开关,当前编辑器支持的宏类型如下:
| Type | Example |
|---|---|
无值宏 | macroName("Macro Description"); |
Bool | macroName("Macro Description", Boolean) = true; |
Int | macroName("Macro Description", Int) = 1; macroName("Macro Description", Range(0,8)) = 1; |
Float | macroName("Macro Description", FLoat) = 0.5; macroName("Macro Description", Range(0.0, 1.0)) = 0.5; |
Color | macroName("Macro Description", Color) = (0.25, 0.5, 0.5, 1); |
Vector2 | macroName("Macro Description", Vector2) = (0.25, 0.5); |
Vector3 | macroName("Macro Description", Vector3) = (0.25, 0.5, 0.5); |
Vector4 | macroName("Macro Description", Vector4) = (0.25, 0.5, 0.5, 1.0); |
SubShader 定义渲染子着色器,目前仅支持指定 replacementTag, 通过引擎的 camera.setReplacementShader(shader, tagName) 调用:
SubShader "SubShaderName" {
Tags {
"replacementTag" = "test1";
}
Pass "PassName" {
// Pass 内容
}
}Pass 定义具体的渲染通道:
Pass "PassName" {
Tags { "pipelineStage" = "Forward" }
// 渲染状态
BlendState customBlendState{
Enabled = true;
SourceColorBlendFactor = BlendFactor.SourceAlpha;
DestinationColorBlendFactor = BlendFactor.OneMinusSourceAlpha;
}
// 局部变量
vec4 color1;
// 指定 顶点、片元 入口
VertexShader = PBRVertex;
FragmentShader = PBRFragment;
}每个 Pass 都可以设置渲染状态,比如透明、深度写入等。
渲染状态变量和引擎枚举类型保持一致,比如 BlendOperation.Add 对应引擎的 API。
BlendState {
Enabled: bool;
ColorBlendOperation: BlendOperation;
AlphaBlendOperation: BlendOperation;
SourceColorBlendFactor: BlendFactor;
SourceAlphaBlendFactor: BlendFactor;
DestinationColorBlendFactor: BlendFactor;
DestinationAlphaBlendFactor: BlendFactor;
ColorWriteMask: ColorWriteMask;
BlendColor: Color;
AlphaToCoverage: bool;
}DepthState {
Enabled: bool;
WriteEnabled: bool;
CompareFunction: CompareFunction;
}StencilState {
Enabled: bool;
ReferenceValue: int;
Mask: float;
WriteMask: float;
CompareFunctionFront: CompareFunction;
CompareFunctionBack: CompareFunction;
PassOperationFront: StencilOperation;
PassOperationBack: StencilOperation;
FailOperationFront: StencilOperation;
FailOperationBack: StencilOperation;
ZFailOperationFront: StencilOperation;
ZFailOperationBack: StencilOperation;
}RasterState {
CullMode: CullMode;
FillMode: FillMode;
DepthBias: float;
SlopeScaledDepthBias: float;
}渲染状态支持常量赋值和变量赋值:
// 变量名称
RenderQueueType renderQueueType;
BlendFactor destinationColorBlendFactor;
BlendFactor sourceAlphaBlendFactor;
BlendFactor destinationAlphaBlendFactor;
BlendState customBlendState {
// 常量赋值方式
Enabled = true;
SourceColorBlendFactor = BlendFactor.SourceColor;
// 变量赋值方式
DestinationColorBlendFactor = destinationColorBlendFactor;
SourceAlphaBlendFactor = sourceAlphaBlendFactor;
DestinationAlphaBlendFactor = destinationAlphaBlendFactor;
}// 使用结构体
BlendState = customBlendState;
// 变量渲染队列
RenderQueueType = renderQueueType;
// 常量渲染队列
RenderQueueType = Opaque;
RenderQueueType = AlphaTest;
RenderQueueType = Transparent;struct MRT {
layout(location = 0) vec4 fragColor0;
layout(location = 1) vec4 fragColor1;
};
MRT frag(Varyings input) {
MRT output;
output.fragColor0 = vec4(1, 0, 0, 1);
output.fragColor1 = vec4(0, 1, 0, 1);
return output;
}通过 #include 指令引入代码片段:
#include "Common.glsl" // 通用函数
#include "Light.glsl" // 光照计算
#include "Shadow.glsl" // 阴影计算
#include "Fog.glsl" // 雾效计算
#include "./MyCustom.glsl" // 自定义片段官方提供了很多内置代码段,开发者可以直接注册后使用:
import { registerIncludes } from "@galacean/engine-shader";
// 对内置 ShaderLab 代码段注册。
registerIncludes();如果是自定义的片段,可以通过接口进行手动注册:
import { ShaderFactory } from '@galacean/engine';
const shaderSource = `{{Your shader code}}`;
ShaderFactory.registerInclude('YourKey', shaderSource);UIScript 是 ShaderLab 的核心特性之一,允许通过 TypeScript 脚本实现智能的属性面板交互,包括设置宏开关、渲染状态等:
import { ShaderUIScript, Material } from "@galacean/engine";
export default class MyShaderScript extends ShaderUIScript {
constructor() {
super();
// 属性变化监听
this.onPropertyChanged("material_BaseTexture", this.onBaseTextureChanged);
this.onPropertyChanged("material_BlendMode", this.onBlendModeChanged);
}
// 监听属性,设置宏开关
private onBaseTextureChanged = (material: Material, value: Texture2D) => {
if (value) {
material.shaderData.enableMacro("MATERIAL_HAS_BASETEXTURE");
} else {
material.shaderData.disableMacro("MATERIAL_HAS_BASETEXTURE");
}
};
// 监听属性,设置渲染状态
private onBlendModeChanged = (material: Material, value: BlendMode) => {
const shaderData = material.shaderData;
switch (value) {
case BlendMode.Normal:
shaderData.setInt("sourceColorBlendFactor", BlendFactor.SourceAlpha);
shaderData.setInt("destinationColorBlendFactor", BlendFactor.OneMinusSourceAlpha);
shaderData.setInt("sourceAlphaBlendFactor", BlendFactor.One);
shaderData.setInt("destinationAlphaBlendFactor", BlendFactor.OneMinusSourceAlpha);
break;
case BlendMode.Additive:
shaderData.setInt("sourceColorBlendFactor", BlendFactor.SourceAlpha);
shaderData.setInt("destinationColorBlendFactor", BlendFactor.One);
shaderData.setInt("sourceAlphaBlendFactor", BlendFactor.One);
shaderData.setInt("destinationAlphaBlendFactor", BlendFactor.OneMinusSourceAlpha);
break;
}
};
}在 Shader 中绑定 UIScript:
Editor {
...
UIScript "/path/to/script";
...
}绑定的UIScript脚本路径支持相对路径和绝对路径,以下图项目根目录为例,绝对路径为
/PBRScript1.ts,相对路径为./PBRScript1.ts
