内置 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 进行绘制。
