Skip to content

SPCustomShader

1746字约6分钟

2022-07-17

摘要

统一UE4/5和SubstancePainter的表现效果可以辅助提升美术设计师在SP中的绘制效率,达到所见即所得的制作体验。效果统一有多个环节需要处理,本文结合Substance提供的Shader API:Shader API | Substance 3D Painter (adobe.com),梳理自定义shader的流程。

框架

SP的Shader使用GLSL语言,且高度封装,只能编写像素着色器的一部分,类似于Unity的Surfeace Shader,好在提供了一系列的库函数和结构体。其着色入口为shade函数,例如写一个HelloWorld:

void shade(V2F inputs) 
{
  diffuseShadingOutput(vec3(1.0, 0.0, 1.0));
}

将此段函数复制粘贴到一个**.glsl**后缀的空文件中即编写完一个SP shader,随后将其导入SP并在着色器设置中启用,就能看到“美丽”的紫色了。

路径

先了解一下SP的Shader文件组织结构,所有Substance提供的Shader均存放在如下目录:

Substance Painter\resources\shelf\allegorithmic\shaders

另外还有一个目录:\Substance Painter\resources\shader-doc,存放的不是Shader本体而是着色器说明,也就是离线的Shader API文档。

此外,SP使用框架存储配置文件,导入的Shader也会被存储在当前使用的框架的根目录里,例如:D:\Document\Allegorithmic\Substance Painter\shelf\shaders

导入

SP有多种方式导入Shader文件:

  • 将编写完成的Shader文件放入Shader根目录。

    • 这种方式适合项目美术设计师,每次打开SP都会自动加载,无需其他操作。
    • 每当有Shader更新都需要手动替换并重启SP。
  • 将Shader文件拖入SP,并导入到当前文件

    • 这种方式适合TA或其他人员编写调试。在编辑器中保存更改之后,右键重载即可实时更新。
    • 导入到Self展架或是导入到当前会话均无法直接重载。
    • 不对其他文件生效。

结构

以SP自带的pbr-metal-rough.glsl为例,分析各个组成部分:

库函数

首先导入了库文件。为了避免编写大量的着色器代码,Substance提供了一个小巧但实用的函数库。不过目前来说,函数库不支持自定义。

//- Import from libraries.
import lib-sss.glsl
import lib-pbr.glsl
import lib-emissive.glsl
import lib-pom.glsl
import lib-utils.glsl

Metadata

用于IRay的MDL和自定义UI的QML,使用**//😗* 作为开头标识符,同时约定使用**//-** 作为普通注释开头,例如:

//- Declare the iray mdl material to use with this shader.
//: metadata {
//:   "mdl":"mdl::alg::materials::skin_metallic_roughness::skin_metallic_roughness"
//: }

MDL

MDL是nVidia定义的材质语言,参见:Material Definition Language | NVIDIA。SP使用MDL作为IRay的材质定义。

QML

QML是Qt定义的UI语言,参见:Qt QML 5.15.8。SP使用Qt开发界面,因此可以使用QML重写Shader部分的面板。

参数定义

这部分的参数主要提供给SP的Shader面板使用,或是用于绑定纹理。SP使用虚拟纹理显示视口中可见的纹理部分。

Engine Params

SP提供了很多内置的参数,比如纹理、矩阵、摄像机位置以及相机方向等等,参见:All Engine Params - Shader API | Substance 3D Painter (adobe.com)。和Metadata部分类似,这些参数UI部分使用**//😗* 作为开头标识符,然后下一行为参数声明:

// 在lib中定义了SampleSpares的数据结构
import lib-sparse.glsl

//: param auto TEXTURE_TAG
uniform SamplerSparse uniform_tex;

//- 声明长宽比
//: param auto aspect_ratio
uniform float uniform_aspect_ratio;

Custom Params

类似Unity,SP也支持自定义的参数,同时也能定义其在SP面板上的显示行为,只不过语法略微复杂,参见:All Custom Params - Shader API | Substance 3D Painter (adobe.com)。一些常用的UI控件如下:

//- 颜色的声明
//: param custom { "default": 0, "label": "Color RGB", "widget": "color" }
uniform vec3 u_color_float3;

//- SpinBox的声明
//: param custom { "default": 0, "label": "Int spinbox" }
uniform int u_spin_int1;

//- 滑条的声明
//: param custom { "default": 0, "label": "Float4 slider", "min": 0.0, "max": 1.0, "step": 0.02 }
uniform vec4 u_slider_float4_stepped;

//- Bool 变量
//: param custom { "default": false, "label": "Boolean" }
uniform bool u_bool;

//- 自定义采样器
//: param custom { "default": "", "default_color": [1.0, 1.0, 0.0, 1.0], "label": "Texture" }
uniform sampler2D u_sampler1;

//- 枚举的声明
//: param custom {
//:   "default": -1,
//:   "label": "Combobox",
//:   "widget": "combobox",
//:   "values": {
//:     "Value -1": -1,
//:     "Value 0": 0,
//:     "Value 10": 10
//:   }
//: }
uniform int u_combobox;

渲染设置

这部分可以配置渲染状态参数,参见:All Rendering States Params - Shader API | Substance 3D Painter (adobe.com)。例如背面剔除的控制如下:

//- Cull back faces
//:state cull_face on

//- Draw front and back faces
//: state cull_face off

像素着色

完成了前置的设置之后,可以开始动手写着色部分了。SP的着色入口为:

void shade(V2F inputs);

其输入和输出为:

struct V2F 
{
  vec3 normal;
  vec3 tangent;              
  vec3 bitangent;            
  vec3 position;
  vec4 color[1];             // 顶点色 0 (color0)
  vec2 tex_coord;            // UV0
  SparseCoord sparse_coord;  // 用于虚拟纹理采样的UV
  vec2 multi_tex_coord[8];   // uv0-uv7
};
// 像素透明度,默认值: 1.0
void alphaOutput(float);
// 漫反射照明,默认值: vec3(0.0)
void diffuseShadingOutput(vec3);
// 镜面反射照明,默认值: vec3(0.0)
void specularShadingOutput(vec3);
// 像素自发光,默认值: vec3(0.0)
void emissiveColorOutput(vec3);
// 反照率值,默认值: vec3(1.0)
void albedoOutput(vec3);
// 此表面散射值,参看SSS的库函数,默认值: vec4(0.0)
void sssCoefficientsOutput(vec4);

SP中最基本的像素着色方程如下:

emissiveColor + albedo * diffuseShading + specularShading

综合

结合之前的内容,熟悉Unity的TA应该很快就能实现ToonShading了。总体来讲,SP的Shader并没有那么开放,一些特殊功能或许难以实现,但DCC软件和UE的完全一致本身也不太现实,效果接近即可。

贡献者: Astroite