自定义Effect

创建自定义Effect

开发者可以在资源管理器中新建Effect, 在物体使用的Material中可以选择创建的自定义Effect, 如下所示

可以看到,创建时生成三个文件:

  • custom.effect
  • custom.vertex.hlsl
  • custom.pixel.hlsl

其中custom.effect是Effect主文件,另外两个分别为顶点着色器和片元着色器代码。

下面将介绍如何编写自定义Effect。


编写自定义Effect

以下是一个简单的effect文件

{
  "name":"Effect3D",
  "shaderProperties": [
    {
      "key": "_MainTex_ST",
      "type": "Vector4",
      "default": [1,1,0,0]
    },
    {
      "key": "_TintColor",
      "type": "Vector4",
      "default": [1,1,1,1]
    },
    {
      "key": "_Bright",
      "type": "Float",
      "default": [1.0]
    }
  ],
  "textures": [
    {
      "key": "_MainTex",
      "type": "Texture2D",
      "default": "white"
    },
    {
      "key": "_MaskTex",
      "type": "Texture2D",
      "default": "white"
    }
  ],
  "defaultRenderQueue": 3000,
  "passes": [
    {
      "lightMode": "ForwardBase",
      "vs": "./effect3d.vertex.hlsl",
      "ps": "./effect3d.pixel.hlsl",
      "compileFlags": [
        "Skin" , "Particle" , "Line" , "Trail"
      ],
      "multiCompile": [
        ["CUSTOM_MACRO_A","__"],
        ["CUSTOM_MACRO_B","CUSTOM_MACRO_C"]
      ],
      "useMaterialRenderStates": true,
      "renderStates": {
        "blendOn": true,
        "blendSrc": "SRC_ALPHA",
        "blendDst": "ONE",
        "cullOn": false,
        "cullFace": "BACK",
        "depthWrite": false
      }
    }
  ]
}

一个Effect主要由以下几块组成

  1. name
  2. shaderProperties
  3. textures
  4. defaultRenderQueue
  5. passes

shaderProperties

主要表示使用渲染中常量参数的格式,格式如下

  type ShaderProperties = Array<{
    // 对应shader中的uniform变量名
    key: string;
    // 数值类型,需与shader中uniform的类型对应
    type: "Float"|"Vector2"|"Vector3"|"Vector4";
    // 默认值,数组长度必须与type对应
    default: Array<number>;
  }>

textures

主要表示使用渲染中用到的贴图的格式,格式如下

  type Textures = Array<{
    // 对应shader中的texture变量名
    key: string;
    // 贴图类型,需与shader中texture的类型对应
    type: "Texture2D" | "TextureCube";
    // 默认值,
    default: string;
  }>

其中,default的可选值有:

  • "white": 白色贴图,0xFFFFFFFF
  • "black": 黑色贴图,0x000000FF
  • "red": 红色贴图,0xFF0000FF
  • "green": 绿色贴图,0x00FF00FF
  • "blue": 蓝色贴图,0x0000FFFF
  • "bump": 默认法线贴图,0x808080FF
  • "transparent": 透明贴图,0xFFFFFF00

defaultRenderQueue

指明使用该Effect创建的Material默认的RenderQueue

RenderQueue的定义,可见Material章节

passes

描述具体的绘制流程。一个Effect可以拥有多个Pass, 每个Pass的格式如下:

type Pass = Array<{
    // vertexShader的相对路径
    vs:string;
    // fragmentShader的相对路径
    fs:string;
    // Pass的光照模式,默认是"ForwardBase"
    lightMode: string;
    // 内置编译的功能选项,每个选项实际上是一组内置宏的组合
    compileFlags?: PassCompileFlags[];
    // 该pass的多重编译选项
    multiCompile?: string[][];
    // 该pass的默认renderStates
    renderStates?: RenderStateDesc;
    // 该pass的默认renderStates是否会被material上的renderStates覆盖
    useMaterialRenderStates: boolean;
}>

type PassCompileFlags = "LightMap" | "Fog" | "Shadow" | "Skin" | "Particle" | "Line" | "Trail" | "Mesh.Color";

renderStates

描述了该pass默认的渲染管线状态,格式如下

type RenderStateDesc = {
  blendOn?: boolean;
  blendSrc?: EnumBlendFactorString;
  blendDst?: EnumBlendFactorString;
  blendFunc?: EnumBlendOpString;
  cullOn?: boolean;
  cullFace?: EnumCullModeString;
  depthWrite?: boolean;
  depthTestOn?: boolean;
  depthTestComp?: EnumCompareFuncString;
  stencilWriteMask?: number;
  stencilTestOn?: boolean;
  stencilRef?: number;
  stencilReadMask?: number;
  stencilComp?: EnumCompareFuncString;
  stencilPass?: EnumStencilOpString;
  stencilFail?: EnumStencilOpString;
  stencilZFail?: EnumStencilOpString;
  primitiveType?: EnumPrimitiveTypeString;
}

enum EnumBlendFactorString {
	ZERO = "ZERO",
	ONE = "ONE",
	SRC_COLOR = "SRC_COLOR",
	ONE_MINUS_SRC_COLOR = "ONE_MINUS_SRC_COLOR",
	SRC_ALPHA = "SRC_ALPHA",
	ONE_MINUS_SRC_ALPHA = "ONE_MINUS_SRC_ALPHA",
	DST_COLOR = "DST_COLOR",
	ONE_MINUS_DST_COLOR = "ONE_MINUS_DST_COLOR",
	DST_ALPHA = "DST_ALPHA",
	ONE_MINUS_DST_ALPHA = "ONE_MINUS_DST_ALPHA",
	SRC_ALPHA_SATURATED = "SRC_ALPHA_SATURATED",
	BLEND_COLOR = "BLEND_COLOR",
	ONE_MINUS_BLEND_COLOR = "ONE_MINUS_BLEND_COLOR",
	BLEND_ALPHA = "BLEND_ALPHA",
	ONE_MINUS_BLEND_ALPHA = "ONE_MINUS_BLEND_ALPHA",
}

enum EnumBlendOpString {
	ADD = "ADD",
	SUBTRACT = "SUBTRACT",
	REVERSE_SUBTRACT = "REVERSE_SUBTRACT",
}

enum EnumCullModeString {
	NONE = "NONE",
	FRONT = "FRONT",
	BACK = "BACK",
}

enum EnumCompareFuncString {
	NEVER = "NEVER",
	LESS = "LESS",
	EQUAL = "EQUAL",
	LESS_EQUAL = "LESS_EQUAL",
	GREATER = "GREATER",
	NOT_EQUAL = "NOT_EQUAL",
	GREATER_EQUAL = "GREATER_EQUAL",
	ALWAYS = "ALWAYS",
}

enum EnumStencilOpString {
	KEEP = "KEEP",
	ZERO = "ZERO",
	REPLACE = "REPLACE",
	INCR_CLAMP = "INCR_CLAMP",
	DECR_CLAMP = "DECR_CLAMP",
	INVERT = "INVERT",
	INCR_WRAP = "INCR_WRAP",
	DECR_WRAP = "DECR_WRAP",
}

enum EnumPrimitiveTypeString {
	POINTS = "POINTS",
	LINES = "LINES",
	LINE_STRIP = "LINE_STRIP",
	TRIANGLES = "TRIANGLES",
	TRIANGLE_STRIP = "TRIANGLE_STRIP",
}

如果useMaterialRenderStates是false,则该pass上的renderStates将不会被material上的renderStates覆盖。可以用于如lightMode=ShaderCaster的pass上

多pass

一个Effect可以指定多个Pass,使用哪个Pass进行渲染是将根据LightMode进行自动选择。

在目前默认的内置Forward渲染管线中:

  • 如果定义了多个LightMode=ForwardBase的Pass,将会将同一个模型依次将每一个Pass渲染。可以用于绘制多层材质,例如头发;或者用于绘制双面材质。
  • 如果定义了LightMode=ShadowCaster的Pass,将会使用该Pass进行阴影投射的绘制,否则将使用内置的Fallback ShadowCaster Pass。可以用于定制阴影的效果,例如镂空阴影

自定义宏与变体

multiCompile配置指示需要编译哪些Shader变体组合

是一个二维数组,内层数组之间是互斥关系,外层数组之间是组合关系。

如示例

 [
    ["CUSTOM_MACRO_A","__"],
    ["CUSTOM_MACRO_B","CUSTOM_MACRO_C"]
  ]

将会被编译出4种Shader变体,分别为:

  1. CUSTOM_MACRO_A + CUSTOM_MACRO_B
  2. CUSTOM_MACRO_A + CUSTOM_MACRO_C
  3. CUSTOM_MACRO_B
  4. CUSTOM_MACRO_C

"__" 表示该项宏可为空

请不要使用__作为自定义宏名字的开头,以免与内置宏冲突。