Editor {
Properties {
material_BaseColor("Offset unit scale", Color) = (1,1,1,1);
...
Header("Emissive")
{
material_EmissiveColor("Emissive color", Color) = (1,1,1,1);
...
}
...
}
...
Macros {
[On] UV_OFFSET("UV Offset", Range(1,100)) = 10;
...
Header("") {
SOME_MACRO("label", Int) = 1;
}
}
...
// 指定 Shader 绑定的 UIScript 编辑器项目路径。
UIScript "./shaderScript.ts";
}
可用于定义绑定了该 Shader 自定义材质的属性,在编辑器中开发者可以通过自定义材质 Inspector 面板对定义的属性进行调整。
/**
* @language zh
* Comments description
*/
/**
* @language en
* 注释描述
*/
propertyName("Description", EditType) = [DefaultValue];
Header
指令将有关联的属性组织起来,Inspector 对应的面板中也会有相应的层级分类:Header("Emissive") {
material_EmissiveColor("Emissive color", Color) = (1,1,1,1);
...
}
当前支持的 EditType 列表如下:
EditType | Example |
---|---|
Bool | propertyName("Property Description", Boolean) = true; |
Int | propertyName("Property Description", Int) = 1; propertyName("Property Description", Range(0,8)) = 1 propertyName("Property Description", Enum(Item1: 1, Item2: 2, Item3: 3)) = 1 // 枚举 |
Float | propertyName("Property Description", FLoat) = 0.5; propertyName("Property Description", Range(0.0, 1.0)) = 0.5; propertyName("Property Description", Enum(Item1: 1.0, Item2: 2.0, Item3: 3.0)) = 1.0; // 枚举 |
Texture2D | propertyName("Property Description", Texture2D); |
TextureCube | propertyName("Property Description", TextureCube); |
Color | propertyName("Property Description", Color) = (0.25, 0.5, 0.5, 1); |
Vector2 | propertyName("Property Description", Vector2) = (0.25, 0.5); |
Vector3 | propertyName("Property Description", Vector3) = (0.25, 0.5, 0.5); |
Vector4 | propertyName("Property Description", Vector4) = (0.25, 0.5, 0.5, 1.0); |
propertyName("Property Description", Enum(Item1: 1, Item2: 2, Item3: 3)) = 1;
当前只有 Int 和 Float 类型支持枚举,且不支持类型混合,比如下面的枚举混合了Float和Int,将不会被正确解析 glsl propertyName("Property Description", Enum("Item1":1, "Item2":2.0, "Item3": 3)) = 2.0;
用于将 Shader 中用到的宏反射到 Inspector 中,从而在编辑器中对 Shader 依赖的宏进行灵活的调整。
// 开启/关闭
[On/Off]macroName("MacroLabel", EditType) = [DefaultValue];
通过[On/Off]
指令指定宏的默认开关,当前编辑器支持的宏类型如下:
Type | Example |
---|---|
无值宏 | macroName("Macro Description"); |
Bool | macroName("Macro Description", Boolean) = true; |
Int | macroName("Macro Description", Int) = 1; macroName("Macro Description", Range(0,8)) = 1; |
Float | macroName("Macro Description", FLoat) = 0.5; macroName("Macro Description", Range(0.0, 1.0)) = 0.5; |
Color | macroName("Macro Description", Color) = (0.25, 0.5, 0.5, 1); |
Vector2 | macroName("Macro Description", Vector2) = (0.25, 0.5); |
Vector3 | macroName("Macro Description", Vector3) = (0.25, 0.5, 0.5); |
Vector4 | macroName("Macro Description", Vector4) = (0.25, 0.5, 0.5, 1.0); |
开发者使用编辑器对自定义材质属性进行调节的同时,还可以通过UIScript
指定数据变更的回调行为。
UIScript
:Editor {
...
UIScript "/path/to/script";
...
}
绑定的UIScript
脚本路径支持相对路径和绝对路径,以上图项目根目录为例,绝对路径为
/PBRScript1.ts
,相对路径为./PBRScript1.ts
编辑器通过内置ShaderUIScript
类暴露相关API
import { Color, Material, Texture, Vector2, Vector3, Vector4 } from "@galacean/engine";
type ShaderPropertyValue = number | Vector2 | Vector3 | Vector4 | Color | Texture;
type ShaderMacroValue = number | Vector2 | Vector3 | Vector4 | Color;
/**
* Script for extending `Shader` UI logic.
*/
export abstract class ShaderUIScript {
/** @internal */
_propertyCallBacks: Map<string, (material: Material, value: ShaderPropertyValue) => void> = new Map();
/** @internal */
_macroCallBacks: Map<string, (material: Material, defined: boolean, value: ShaderMacroValue) => void> = new Map();
/**
* The method is called when then shader is switched.
* @param material - The material which the shader is bound to
*/
onMaterialShaderSwitched(material: Material): void {}
/**
* Register property change callback.
* @parma propertyName - Property name
* @parma onChanged - Fired on property changed
*/
protected onPropertyChanged(
propertyName: string,
onChanged: (material: Material, value: ShaderPropertyValue) => void
): void {
this._propertyCallBacks.set(propertyName, onChanged);
}
/**
* Register macro change callback.
* @parma macroName - Macro name
* @parma onChanged - Fired on macro changed
*/
protected onMacroChanged(
macroName: string,
onChanged: (material: Material, defined: boolean, value: ShaderMacroValue) => void
): void {
this._macroCallBacks.set(macroName, onChanged);
}
}
import { Material, RenderQueueType, Vector3, BlendFactor, RenderFace, CullMode, BlendMode } from "@galacean/engine";
export default class extends ShaderUIScript {
constructor() {
super();
......
// 在构造函数中注册监听属性回调
this.onPropertyChanged("material_NormalTexture", (material: Material, value) => {
const shaderData = material.shaderData;
if (value) {
shaderData.enableMacro("MATERIAL_HAS_NORMALTEXTURE");
} else {
shaderData.disableMacro("MATERIAL_HAS_NORMALTEXTURE");
}
})
......
}
// 指定 shader 绑定的回调
override onMaterialShaderSwitched(material: Material) {
const shaderData = material.shaderData;
shaderData.disableMacro("MATERIAL_OMIT_NORMAL");
shaderData.enableMacro("MATERIAL_NEED_WORLD_POS");
shaderData.enableMacro("MATERIAL_NEED_TILING_OFFSET");
// default value
const anisotropyInfo = shaderData.getVector3("material_AnisotropyInfo");
if (!anisotropyInfo) {
shaderData.setVector3("material_AnisotropyInfo", new Vector3(1, 0, 0));
} else {
shaderData.setFloat("anisotropy", anisotropyInfo.z);
const PI2 = Math.PI * 2;
const rotationRad = (Math.atan2(anisotropyInfo.y, anisotropyInfo.x) + PI2 ) % PI2;
shaderData.setFloat("anisotropyRotation", rotationRad * (180 / Math.PI))
}
}
}
注意,当前版本 ShaderLab 材质属性模块只是定义了绑定该 Shader 的材质在编辑器中的 Inspector
UI面板,并不会替你在ShaderPass
中声明对应的全局变量,如果ShaderPass
代码中引用了该变量需在全局变量模块中明确声明补充。