Pass
代表一次 GPU 绘制过程,因此每个 Pass
必须包含一个顶点着色器和片元着色器。ShaderLab 中通过 VertexShader
和 FragmentShader
分别指定其入口函数。
...
Pass "0" {
...
VertexShader = vert;
FragmentShader = frag;
v2f vert(a2v o) {
...
}
...
void frag(v2f i) {
...
}
...
}
跟传统 GLSL Shader 程序一样,ShaderLab 通过 Attribute 和 Uniform 变量接收来自 CPU 的渲染数据,同时顶点着色器和片元着色器通过 Varying 变量进行数据传递。不同的是,ShaderLab 是通过结构体和着色器入口函数签名来完成对 Attribute 和 Varying 变量的声明。
struct Attributes {
vec3 POSITION;
vec4 COLOR_0;
...
}
struct Varyings {
vec2 uv;
vec3 position;
...
}
...
Varyings vert(Attributes attr) {
Varyings vary;
...
vary.position = attr.Position;
...
return vary;
}
void frag(Varyings vary) {
...
gl_FragColor = vary.COLOR_0;
}
...
VertexShader = vert;
FragmentShader = frag;
ShaderLab
同时兼容 GLSL 100
和 GLSL 300
语法,因此你可以使用两种语法进行 MRT
指定。
gl_FragData[i]
进行指定 MRT 指定void main(v2f input) {
gl_FragData[0] = vec4(1.,0.,0.,1.); // render target 0
gl_FragData[1] = vec4(1.,0.,0.,1.); // render target 1
}
struct mrt {
layout(location = 0) vec4 fragColor0; // render target 0
layout(location = 1) vec4 fragColor1; // render target 1
}
mrt main(v2f input) {
mrt output;
output.fragColor0 = vec4(1.,0.,0.,1.);
output.fragColor1 = vec4(1.,0.,0.,1.);
return output;
}
当前 ShaderLab
仅支持 GLSL 标准语法中的以下部分宏和宏操作函数:
宏 | 描述 |
---|---|
#define | 等同 GLSL 用法 |
#undef | 等同 GLSL 用法 |
#if | 等同 GLSL 用法 |
#ifdef | 等同 GLSL 用法 |
#ifndef | 等同 GLSL 用法 |
#else | 等同 GLSL 用法 |
#elif | 等同 GLSL 用法 |
#endif | 等同 GLSL 用法 |
defined | 等同 GLSL 用法 |
#include | ShaderLab 特有,用于代码段引用,详细使用参考文档 |
除了 #include
,其它的宏使用同 GLSL 标准一致,详细用法参考 GLSL 语法标准。
ShaderLab 宏会在预处理器阶段被展开,因此宏不能影响 ShaderLab 结构解析,即 Shader
,SubShader
,Pass
,EditorProperties
,EditorMacros
关键字不能被包含在类似 #ifdef
这样的分支宏内。