Legacy Shader 主要函数与结构体

CCVertInput1

  • 为对接骨骼动画与数据解压流程,我们提供了 CCVertInput 工具函数,它有 generalstandard 两个版本,内容如下:

    1. // 位于 ‘input.chunk’ 的通用顶点着色器输入
    2. #define CCVertInput(position) \
    3. CCDecode(position); \
    4. #if CC_USE_MORPH \
    5. applyMorph(position); \
    6. #endif \
    7. #if CC_USE_SKINNING \
    8. CCSkin(position); \
    9. #endif \
    10. #pragma // 空 ‘pragma’ 技巧,在编译时消除尾随分号
    11. // 位于 ‘input-standard.chunk’ 的标准顶点着色器输入
    12. #define CCVertInput(In) \
    13. CCDecode(In); \
    14. #if CC_USE_MORPH \
    15. applyMorph(In); \
    16. #endif \
    17. #if CC_USE_SKINNING \
    18. CCSkin(In); \
    19. #endif \
    20. #pragma // 空 ‘pragma’ 技巧,在编译时消除尾随分号
  • 如果只需要获取 顶点位置信息,可以使用 general 版本,那么顶点着色器函数开头的代码示例如下:

    1. #include <legacy/input>
    2. vec4 vert () {
    3. vec3 position;
    4. CCVertInput(position);
    5. // ... 对位置信息做自定义操作
    6. }

    如果还需要法线等信息,可使用 standard 版本,像下面这样写:

    1. #include <legacy/input-standard>
    2. vec4 vert () {
    3. StandardVertInput In;
    4. CCVertInput(In);
    5. // ... 此时 ‘In.position’ 初始化完毕,并且可以在顶点着色器中使用
    6. }

上面的示例代码中,StandardVertInput 对象 In 会返回模型空间的顶点位置(position)、法线(normal)和切空间(tangent)信息,并对骨骼动画模型做完蒙皮计算。

StandardVertInput 结构体的定义如下:

  1. struct StandardVertInput {
  2. highp vec4 position;
  3. vec3 normal;
  4. vec4 tangent;
  5. };

注意:引用头文件后,不要在 Shader 内重复声明这些 attributes(a_positiona_normala_tangent 等)。对于其他顶点数据(如 uv 等)还是需要声明 attributes 后再使用。

如果要对接引擎动态 Mesh 合批和几何体实例化(GPU Instancing),需要包含 cc-local-batch 头文件,通过 CCGetWorldMatrix 工具函数获取世界矩阵,示例如下:

  1. mat4 matWorld;
  2. CCGetWorldMatrix(matWorld);
  3. mat4 matWorld, matWorldIT;
  4. CCGetWorldMatrixFull(matWorld, matWorldIT);

更多细节,请参考 Cocos Shader 内置全局 Uniform

CCFragOutput

Cocos Shader 提供了 CCFragOutput 工具函数用以简化片元着色器的输出,可用于直接返回片元着色器所需要的值,代码示例如下:

  1. #include <legacy/output>
  2. vec4 frag () {
  3. vec4 o = vec4(0.0);
  4. // ... 编写片元着实代码
  5. return CCFragOutput(o);
  6. }

CCFragOutput 会根据管线状态来决定是否需要做 ToneMap 转码处理,这样中间的颜色计算就不必区分当前渲染管线是否为 HDR 流程。

代码示例如下:

  1. vec4 CCFragOutput (vec4 color) {
  2. #if CC_USE_HDR
  3. color.rgb = ACESToneMap(color.rgb);
  4. #endif
  5. color.rgb = LinearToSRGB(color.rgb);
  6. return color;
  7. }

特别注意

如果采用 CCFragOutput 作为片元输出,中间的颜色运算必须转到 Linear 空间,因为 CCFragOutput 认为传入的参数是在 Linear 空间的,总是会进行 LinearToSRGB 转码。

CCFragOutput 函数一般不需要自己实现,它只起到与渲染管线对接的作用,且对于这种含有光照计算的输出,因为计算结果已经在 HDR 范围,所以应该包含 output-standard 而非 output 头文件。

如需包含标准的 PBR 光照计算,可使用 StandardSurface 结构体与函数 CCStandardShadingBase 一起构成 PBR 着色流程。

StandardSurface 结构体内容如下:

  1. struct StandardSurface {
  2. // albedo
  3. vec4 albedo;
  4. // these two need to be in the same coordinate system
  5. vec3 position;
  6. vec3 normal;
  7. // emissive
  8. vec3 emissive;
  9. // light map
  10. vec3 lightmap;
  11. float lightmap_test;
  12. // PBR params
  13. float roughness;
  14. float metallic;
  15. float occlusion;
  16. };

代码示例如下:

  1. #include <legacy/shading-standard-base>
  2. #include <legacy/output-standard>
  3. void surf (out StandardSurface s) {
  4. // fill in your data here
  5. }
  6. vec4 frag () {
  7. StandardSurface s; surf(s);
  8. vec4 color = CCStandardShadingBase(s);
  9. return CCFragOutput(color);
  10. }

也可以参考 builtin-standard.effect 中,使用 surf 函数与 CC_STANDARD_SURFACE_ENTRY() 宏组合。

CC_STANDARD_SURFACE_ENTRY() 是一个 wrapper,会根据渲染状态,利用 surf 函数构建出一个可用于片元的 main 函数,代码示例如下:

  1. CCProgram shader-fs %{
  2. #include <legacy/standard-surface-entry>
  3. void surf (out StandardSurface s) {
  4. // fill in your data here
  5. }
  6. CC_STANDARD_SURFACE_ENTRY()
  7. }%

StandardSurface

StandardSurface 为 PBR 材质信息结构体,记录了一个像素需要进行光照计算的表面信息。 Lagecy Shader 中的 surf 函数主要用于填充,它会在光照阶段被使用。

  1. struct StandardSurface {
  2. // albedo
  3. vec4 albedo;
  4. // these two need to be in the same coordinate system
  5. HIGHP_VALUE_STRUCT_DEFINE(vec3, position);
  6. vec3 normal;
  7. // emissive
  8. vec3 emissive;
  9. // light map
  10. vec3 lightmap;
  11. float lightmap_test;
  12. // PBR params
  13. float roughness;
  14. float metallic;
  15. float occlusion;
  16. float specularIntensity;
  17. #if CC_RECEIVE_SHADOW
  18. vec2 shadowBias;
  19. #endif
  20. };

ToonSurface

  1. struct ToonSurface {
  2. vec4 baseColor;
  3. vec4 specular;
  4. // these two need to be in the same coordinate system
  5. HIGHP_VALUE_STRUCT_DEFINE(vec3, position);
  6. vec3 normal;
  7. // shading params
  8. vec3 shade1;
  9. vec3 shade2;
  10. vec3 emissive;
  11. float baseStep;
  12. float baseFeather;
  13. float shadeStep;
  14. float shadeFeather;
  15. float shadowCover;
  16. #if CC_RECEIVE_SHADOW
  17. vec2 shadowBias;
  18. #endif
  19. };

和 StandardSurface 一样,ToonSurface 也是用于记录像素表面信息,只是它是卡通材质专用的结构体。

  1. 不包含粒子、Sprite、后期效果等不基于 Mesh 渲染的 Shader。