顶点、片元着色器程序编写

Pass 代表一次 GPU 绘制过程,因此每个 Pass 必须包含一个顶点着色器和片元着色器。ShaderLab 中通过 VertexShaderFragmentShader 分别指定其入口函数。

...
Pass "0" {
  ...
  VertexShader = vert;
  FragmentShader = frag;
 
  v2f vert(a2v o) {
    ...
  }
 
  ...
 
  void frag(v2f i) {
    ...
  }
  ...
}

Attribute 和 Varying 变量声明

跟传统 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;

MRT(多目标渲染)

ShaderLab 同时兼容 GLSL 100GLSL 300 语法,因此你可以使用两种语法进行 MRT 指定。

1. 通过 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
}

2. 通过入口函数返回结构体指定

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 用法
#includeShaderLab 特有,用于代码段引用,详细使用参考文档

除了 #include,其它的宏使用同 GLSL 标准一致,详细用法参考 GLSL 语法标准

ShaderLab 宏会在预处理器阶段被展开,因此宏不能影响 ShaderLab 结构解析,即 ShaderSubShaderPassEditorPropertiesEditorMacros 关键字不能被包含在类似 #ifdef 这样的分支宏内。

这篇文档对您有帮助吗?