Files
engine/docs/zh/graphics/material/baseUse.mdx
zhuxudong 8d57c2c6df Refactor shader document (#2833)
* docs: refactor shader document and add shader101 guide
2025-09-19 16:11:48 +08:00

190 lines
6.5 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 材质的基本使用
---
## 创建材质
创建材质一般有以下 3 种方式:
### 1. 手动创建
<Image src="https://gw.alipayobjects.com/zos/OasisHub/b01b0ee2-317e-4acb-8c2f-e07736179d67/image-20240206163405147.png" />
### 2. 模型中的材质
参考[模型的导入和使用](/docs/graphics/model/use/)教程,我们可以先将模型导入到编辑器,一般情况下,模型已经自动绑定好材质,用户可以不用做任何操作;
#### 2.1. Remap 材质
如果想要修改模型材质,我们可以点击 `duplicate and remap` 按钮来生成一份该材质的副本,注意 Remap 会修改模型预设,如下图所有模型实例都会受到影响:
<Image src="https://gw.alipayobjects.com/zos/OasisHub/4a41f66e-5523-43f0-a9b5-4028b9d14cbc/2025-01-24%25252015.30.31.gif" />
#### 2.2. 增量修改
如果只想修改某个模型的材质,可以使用增量修改的功能:
<Image src="https://gw.alipayobjects.com/zos/OasisHub/5d2409f2-a7b2-4b5e-9e6a-9845c3358af3/2025-01-24%25252015.32.04.gif" />
### 3. 绑定材质
我们直接将材质拖到场景中即可进行绑定。
<Image src="https://gw.alipayobjects.com/zos/OasisHub/62d6a8cb-fd70-4c37-beab-9dacc8ae4d5b/2025-05-23%25252017.13.59.gif" />
### 4. 脚本方式
我们还可以通过脚本来创建/修改材质,我们将脚本挂载到立方体实体上,实现替换材质的一个 Demo
```ts showLineNumbers
export default class extends Script {
onStart() {
// 获取所有 renderer
const renderers = [];
this.entity.getComponentsIncludeChildren(MeshRenderer, renderers);
const renderer = renderers[0];
// 直接修改材质
const material = renderer.getMaterial();
material.baseColor.set(1, 0, 0, 1);
// 或者替换材质
const pbrMaterial = new PBRMaterial(engine);
const material = renderer.setMaterial(material);
}
}
```
## 切换 Shader
可以在编辑器中选中材质,切换 shader 观察实时渲染效果变化。
<Image src="https://gw.alipayobjects.com/zos/OasisHub/cd87c11a-7a68-4cde-a19a-40cff943e878/2025-02-10%25252017.05.33.gif" />
每个 Shader 有不同的渲染效果和应用场景,更多详情参考 [内置着色器教程](/docs/graphics/material/builtinShaders/pbr/) 和 [自定义 Shader 实战教程](/docs/graphics/material/examples/shaderlab-01-basic-shader) 。
## 创建自定义 Shader
如果内置 Shader 不能满足需求我们可以自定义一个Shader在编辑器资产面板中新建 Shader选择 PBR 模板或者 Unlit 模板:
<img
src="https://gw.alipayobjects.com/zos/OasisHub/9abd1026-4e4d-4994-b36a-f964375c38cb/image-20240731105324320.png"
style={{ zoom: "50%" }}
/>
编辑器会自动帮我们创建好 Shader 文件和 [UIScript](/docs/graphics/material/shader/#uiscript-脚本系统) 文件。
<img
src="https://gw.alipayobjects.com/zos/OasisHub/6351fa81-5159-4469-bd95-8f21a8f2f4ac/image-20250124162909194.png"
style={{ zoom: "50%" }}
/>
<Callout type="info">
具体 shader 内容编写可以从 [自定义 Shader 实战教程](/docs/graphics/material/examples/shaderlab-01-basic-shader) 快速上手。
</Callout>
## Shader 数据的传输
跟别的编程语言一样,我们在写 Shader 过程中也会用到很多变量,首先引擎有很多 [内置变量](/docs/graphics/material/variables),这部分的变量我们是不需要手动设置的,可以直接在 shader 中使用。接下来我们看看如何设置和使用自定义数据。
### 声明变量
```glsl showLineNumbers
...
Pass "Forward" {
// 声明自定义变量
vec4 u_color;
// 声明引擎内置变量
mat4 renderer_MVPMat;
// 通过引入代码片段
#include "Transform.glsl"
}
...
```
### 设置数据
Shader 支持通过 [UIScript](/docs/graphics/material/shader/#uiscript-脚本系统) 帮我们自动生成可以交互的面板:
<div style={{display: "flex"}}>
<Image src="https://mdn.alipayobjects.com/huamei_aftkdx/afts/img/A*mwAxRr45kE8AAAAAAAAAAAAAeteEAQ/fmt.webp" width="435px" />
<Image src= "https://mdn.alipayobjects.com/huamei_aftkdx/afts/img/A*7MrxTIG5fpkAAAAAAAAAAAAAeteEAQ/fmt.webp" width="200px" />
</div>
<Callout type="info">
参考 [Shader Editor 模块 ](/docs/graphics/material/shader/#2-editor-模块) 使用更多类型的数据和宏。
</Callout>
当然,我们也可以通过代码设置着色器数据:
```ts showLineNumbers
// shaderData 可以分别保存在 scene 、camera 、renderer、 material 中。
const shaderData = material.shaderData;
// 上传不同类型的着色器数据
shaderData.setFloat("u_float", 1.5);
shaderData.setInt("u_int", 1);
shaderData.setInt("u_bool", 1);
shaderData.setVector2("u_vec2", new Vector2(1, 1));
shaderData.setVector3("u_vec3", new Vector3(1, 1, 1));
shaderData.setVector4("u_vec4", new Vector4(1, 1, 1, 1));
shaderData.setMatrix("u_matrix", new Matrix());
shaderData.setIntArray("u_intArray", new Int32Array(10));
shaderData.setFloatArray("u_floatArray", new Float32Array(10));
shaderData.setTexture("u_sampler2D", texture2D);
shaderData.setTexture("u_samplerCube", textureCube);
shaderData.setTextureArray("u_samplerArray", [texture2D, textureCube]);
// 开启宏开关
shaderData.enableMacro("DISCARD");
// 关闭宏开关
shaderData.disableMacro("DISCARD");
// 开启变量宏
shaderData.enableMacro("LIGHT_COUNT", "3");
// 切换变量宏。这里底层会自动 disable 上一个宏,即 “LIGHT_COUNT 3”
shaderData.enableMacro("LIGHT_COUNT", "2");
// 关闭变量宏
shaderData.disableMacro("LIGHT_COUNT");
```
### 获取数据
当你设置完数据后,你已经可以在 Shader 中直接使用,如下:
```glsl showLineNumbers filename="test.glsl"
float test = u_float;
int test = u_int;
bool test = u_bool;
vec2 test = u_vec2;
mat4 test = u_matrix;
sampler2D test = u_sampler2D;
...
```
你也可以通过代码获取这个变量的值:
```ts showLineNumbers filename="test.ts"
const test = shaderData.getFloat("u_float");
const test = shaderData.getInt("u_int");
const test = shaderData.getVector2("u_vec2");
const test = shaderData.getMatrix("u_matrix");
const test = shaderData.getTexture("u_sampler2D");
```
## 下一步学习
- [自定义 Shader](/docs/graphics/material/examples/shaderlab-01-basic-shader) - 从 0 开始 Shader 创作之旅
- [Shader 语法深入学习](/docs/graphics/material/shader) - 完整的语法参考
- [Shader 内置变量参考](/docs/graphics/material/variables) - 引擎提供的所有内置变量
- [Shader 内置 API 参考](/docs/graphics/material/shaderAPI) - 引擎提供的所有 Shader API
- [光照系统](/docs/graphics/light/light) - 实现更真实的光照效果