Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update shaderlab doc #2505

Open
wants to merge 1 commit into
base: dev/1.4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/zh/graphics/shader/shaderLab/syntax/_meta.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"intro": "总览",
"shader": "Shader",
"editor": "Editor",
"subShader": "SubShader",
"pass": "Pass",
"macro": "宏"
}
}
260 changes: 260 additions & 0 deletions docs/zh/graphics/shader/shaderLab/syntax/editor.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
import { Image } from "@/mdx";

---

# Editor

```glsl
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";
}
```

## Properties 属性

可用于定义绑定了该 Shader 自定义材质的属性,在编辑器中开发者可以通过自定义材质 Inspector 面板对定义的属性进行调整。

<Image
src="https://mdn.alipayobjects.com/huamei_aftkdx/afts/img/A*1mjVR5GXXOkAAAAAAAAAAAAADteEAQ/fmt.webp"
figcaption="材质 Inspector 面板"
width="200px"
/>

### 属性定义

```glsl
/**
* @language zh
* Comments description
*/

/**
* @language en
* 注释描述
*/
propertyName("Description", EditType) = [DefaultValue];
```

<Callout type="info">

1. 可以使用 `Header` 指令将有关联的属性组织起来,Inspector 对应的面板中也会有相应的层级分类:

```
Header("Emissive") {
material_EmissiveColor("Emissive color", Color) = (1,1,1,1);
...
}
```

2. 通过注释标注 Inspector Hover 提示内容,支持使用 @language 指令进行多语言指定。

</Callout>

通过注释标注 Inspector Hover 提示内容,支持使用 @language 指令进行多语言指定。当前支持的 EditType 列表如下:

| EditType | Example |
| :-: | :-- |
| Bool | propertyName("Property Description", Boolean) = true; |
| Int | propertyName("Property Description", Int) = 1; <br/>propertyName("Property Description", Range(0,8)) = 1 <br/> propertyName("Property Description", Enum(Item1: 1, Item2: 2, Item3: 3)) = 1 // 枚举 |
| Float | propertyName("Property Description", FLoat) = 0.5; <br/>propertyName("Property Description", Range(0.0, 1.0)) = 0.5; <br/> 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); |

#### 枚举类型

```glsl
propertyName("Property Description", Enum(Item1: 1, Item2: 2, Item3: 3)) = 1;
```

<Callout typ="warning">
当前只有 Int 和 Float 类型支持枚举,且不支持类型混合,比如下面的枚举混合了Float和Int,将不会被正确解析 ```glsl
propertyName("Property Description", Enum("Item1":1, "Item2":2.0, "Item3": 3)) = 2.0; ```
</Callout>

## Macros

用于将 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; <br/> macroName("Macro Description", Range(0,8)) = 1; |
| Float | macroName("Macro Description", FLoat) = 0.5; <br/> 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`指定数据变更的回调行为。

- 在 ShaderLab 中绑定 `UIScript`:

```
Editor {
...
UIScript "/path/to/script";
...
}
```

<Image
src="https://mdn.alipayobjects.com/huamei_aftkdx/afts/img/A*t4LFQ4KEL6kAAAAAAAAAAAAADteEAQ/fmt.webp"
width="70%"
/>
绑定的`UIScript`脚本路径支持相对路径和绝对路径,以上图项目根目录为例,绝对路径为
`/PBRScript1.ts`,相对路径为`./PBRScript1.ts`

### UIScript API

编辑器通过内置`ShaderUIScript`类暴露相关API

```ts
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);
}
}
```

### UIScript 编写

1. 在编辑器中创建 UIScript 脚本

<Image
src="https://mdn.alipayobjects.com/huamei_aftkdx/afts/img/A*Qh4UTZgaY7MAAAAAAAAAAAAADteEAQ/fmt.webp"
width="60%"
figcaption="创建UIScript"
/>

2. 通过继承 ShaderUIScript 类指定属性变更回调。

```ts
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))
}
}
}

```

<Callout info="warning">
注意,当前版本 ShaderLab 材质属性模块只是定义了绑定该 Shader 的材质在编辑器中的 Inspector UI
面板,并不会替你在`ShaderPass`中声明对应的全局变量,如果`ShaderPass`代码中引用了该变量需在[全局变量](./shader/#全局变量)模块中明确声明补充。
</Callout>
9 changes: 8 additions & 1 deletion docs/zh/graphics/shader/shaderLab/syntax/intro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@ title: ShaderLab 语法标准

> 未来版本会推出 Galacean VSCode 插件,该插件会为`ShaderLab`提供语法检测和自动补全功能以及代码同步功能,敬请期待

<Image src="https://mdn.alipayobjects.com/huamei_aftkdx/afts/img/A*Djs2RJsoPawAAAAAAAAAAAAADteEAQ/original" style={{zoom:"50%"}}/>
<Image
src="https://mdn.alipayobjects.com/huamei_aftkdx/afts/img/A*c4yyRboqBSwAAAAAAAAAAAAADteEAQ/fmt.webp"
style={{ zoom: "50%" }}
/>

## 语法标准

`ShaderLab` 语法骨架如下:

```glsl
Shader "ShaderName" {
...
Editor {
...
}
...
SubShader "SubShaderName" {
...
Expand Down
29 changes: 28 additions & 1 deletion docs/zh/graphics/shader/shaderLab/syntax/pass.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,35 @@ material.renderQueueType = RenderQueueType.Opaque;

// 渲染状态设置 const renderState = material.renderState.depthState; depthState.writeEnabled = false;

```
````
当 ShaderLab 中声明了渲染状态和渲染队列,材质相应的设置会被忽略。
</Callout>


## MRT(多目标渲染)

ShaderLab 同时兼容 GLSL 100 和 GLSL 300 语法,因此你可以使用两种语法进行 MRT 指定。

1. 通过 `gl_FragData[i]` 进行指定 MRT 指定
```glsl
void main(v2f input) {
gl_FragData[0] = vec4(1.,0.,0.,1.); // render target 0
gl_FragData[1] = vec4(1.,0.,0.,1.); // render target 1
}
````

2. 通过入口函数返回结构体指定

```glsl
struct mrt {
layout(location = 0) vec4 fragColor0; // render target 0
layout(location = 1) vec4 fragColor1; // render target 1
}

mrt main(v2f input) {
mrt output;
output.fragColor0 = vec4(1.,0.,0.,1.);
output.fragColor1 = vec4(1.,0.,0.,1.);
return output;
}
```
Loading
Loading