内置 Legacy Shader 导读
Legacy Shader 相关的源码,有两个目录:
- internal/chunks/legacy/
- internal/effects/legacy/
在 chunks/legacy/
目录中,存放的是一些公共函数,如解码器、雾效、输入、输出、阴影、骨骼蒙皮等等。
Legacy Shader 和 Surface Shader 都会调用 internal/chunks/builtin/ 和 internal/chunks/common/ 提供的函数。
在 effects/legacy/
目录中,提供了三个内置的 Legacy Shader:
- standard: 标准材质
- terrain:用于地形渲染
- toon:用于卡通渲染
基本结构
Legacy Shader 代码通常由几个部分组成:
- 信息描述(
CCEffect
):描述此 Shader 的技术、渲染过程组成部分,以及每个渲染过程使用的 Shader、渲染状态、属性等。 - 共享常量(
Shared UBOs
):把 vs 和 fs 都需要用到的 uniforms 定义在一起,方便管理。 - 主体函数(
Shader Body
):用于实现具体的 Shader 主体。
Legacy Shader 中的 CCEffect 和 共享常量部分与 Surface Shader 一致,可前往 内置 Surface Shader 导读 了解详情。
着色函数
为了更好地理解渲染流程,请先查看 前向渲染与延迟渲染 Shader 执行流程。
standard(PBR)
在 legacy/standard.effect 中,定义了着色相关的Shader代码:
CCProgram standard-vs %{
//...
void main(){
StandardVertInput In;
CCVertInput(In);
//...
gl_Position = cc_matProj * (cc_matView * matWorld) * In.position;
}
}%
CCProgram standard-fs %{
//...
void surf(out StandardSurface s){
//s.albedo = ...
//s.occlusion = ...
//s.roughness = ...
//s.metallic = ...
//s.specularIntensity = ...
//s.normal = ...
}
CC_STANDARD_SURFACE_ENTRY()
}%
可以看到,在 vs 中,直接使用了 main 函数作为入口,而在 fs 中,只有一个 surf 函数。
这是因为 CC_STANDARD_SURFACE_ENTRY
宏展开后,就是 main 函数,这个 main 函数会调用 surf 函数。
terrain
terrain 使用 StandardSurface 作为材质表面数据结构,使用 CC_STANDARD_SURFACE_ENTRY
作为入口。这就说明,terrain 的渲染流程与光照计算和 standard 完全一致。
只是由于地形采用的是多层纹理混合,所以 terrain 使用的纹理以及 surf 函数实现细节与 standard 的有较大区别。
toon
在 legacy/toon.effect 中,我们可以看到:
CCProgram toon-vs %{
//...
void main(){
StandardVertInput In;
CCVertInput(In);
//...
gl_Position = cc_matProj * (cc_matView * matWorld) * In.position;
}
}%
CCProgram toon-fs %{
//...
void surf(out ToonSurface s){
//s.baseStep = ...
//s.baseFeather = ...
//s.shadeStep = ...
//s.shadeFeather = ...
//s.shadowCover = ...
}
void frag(){
ToonSurface s; surf(s);
vec4 color = CCToonShading(s);
return CCFragOutput(color);
}
}%
toon 最大的特征是在 CCEffect 中,多定义了一个 outline pass,outline pass 的代码在 chunks/legacy/main-functions/outline-vs(fs) 中。
toon 材质表面数据结构为 ToonSurface,与 standard 使用的不一样。 在 frag 函数中可以看到, toon 的光照计算使用了专门的 CCToonShading 函数。
并且,toon 自己定义了一个 frag 入口函数,未使用 CC_STANDARD_SURFACE_ENTRY
宏。这也意味着,toon 是不支持延迟渲染的。
shadow-caster
可以看到,standard,terrain,toon 都有关于 shadow 的代码片段:
CCProgram shadow-caster-vs %{
//...
}%
CCProgram shadow-caster-fs %{
//...
}%
这个套 vs/fs 用于阴影贴图生成,引擎渲染管线会在阴影贴图生成阶段,查找 phase 为 shadow-add 的 pass 进行绘制。