材质的基本使用

创建材质

创建材质一般有以下 3 种方式:

1. 手动创建

2. 模型中的材质

参考模型的导入和使用教程,我们可以先将模型导入到编辑器,一般情况下,模型已经自动绑定好材质,用户可以不用做任何操作;

2.1. Remap 材质

如果想要修改模型材质,我们可以点击 duplicate and remap 按钮来生成一份该材质的副本,注意 Remap 会修改模型预设,如下图所有模型实例都会受到影响:

2.2. 增量修改

如果只想修改某个模型的材质,可以使用增量修改的功能:

3. 绑定材质

我们直接将材质拖到场景中即可进行绑定。

4. 脚本方式

我们还可以通过脚本来创建/修改材质,我们将脚本挂载到立方体实体上,实现替换材质的一个 Demo:

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 观察实时渲染效果变化。

每个 Shader 有不同的渲染效果和应用场景,更多详情参考 内置着色器教程自定义 Shader 实战教程

创建自定义 Shader

如果内置 Shader 不能满足需求,我们可以自定义一个Shader,在编辑器资产面板中,新建 Shader,选择 PBR 模板或者 Unlit 模板:

编辑器会自动帮我们创建好 Shader 文件和 UIScript 文件。

具体 shader 内容编写可以从 自定义 Shader 实战教程 快速上手。

Shader 数据的传输

跟别的编程语言一样,我们在写 Shader 过程中也会用到很多变量,首先引擎有很多 内置变量,这部分的变量我们是不需要手动设置的,可以直接在 shader 中使用。接下来我们看看如何设置和使用自定义数据。

声明变量

...
Pass "Forward" {
	// 声明自定义变量
	vec4 u_color;
 
	// 声明引擎内置变量
	mat4 renderer_MVPMat;
 
	// 通过引入代码片段
	#include "Transform.glsl"
}
...

设置数据

Shader 支持通过 UIScript 帮我们自动生成可以交互的面板:

参考 Shader Editor 模块 使用更多类型的数据和宏。

当然,我们也可以通过代码设置着色器数据:

// 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 中直接使用,如下:

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;
...

你也可以通过代码获取这个变量的值:

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");

下一步学习

这篇文档对您有帮助吗?