# 自定义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主要由以下几块组成
- name
- shaderProperties
- textures
- defaultRenderQueue
- 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变体,分别为:
- CUSTOM_MACRO_A + CUSTOM_MACRO_B
- CUSTOM_MACRO_A + CUSTOM_MACRO_C
- CUSTOM_MACRO_B
- CUSTOM_MACRO_C
"__" 表示该项宏可为空
请不要使用__作为自定义宏名字的开头,以免与内置宏冲突。