材质
材质总览
引擎通过 MeshRenderer 组件给物体添加相应的 材质
对象,用来模拟其颜色、光照、纹理等属性。目前引擎内置了2种经典材质模型:
名称 | 描述 |
---|---|
UnLitMaterial | 不计算光照和阴影,仅渲染原始颜色与纹理信息 |
LitMaterial | PBR 即基于物理渲染,旨在模拟现实世界光照效果 |
我们推荐使用的 glTF 格式文件包含了物体材质信息。用户可以通过常用建模软件设计并修改模型文件。引擎解析模型文件后,自动赋予物体相应材质。
基础用法
ts
import {Object3D. MeshRenderer, LitMaterial, SphereGeometry, Color} from '@orillusion/core'
let object = new Object3D();
// 添加 MeshRenderer 组件
let mesh = object.addComponent(MeshRenderer);
// 设置组件 material
mesh.material = new UnLitMaterial();
mesh.material.baseColor = new Color(1, 1, 1, 1);
// 切换 Material
mesh.material = new LitMaterial();
Unlit 材质
引擎提供了 UnLitMaterial 材质,紧渲染物理基础颜色,不计算光照和阴影。
属性 | 描述 |
---|---|
baseColor | 基础颜色 |
baseMap | 基础贴图 |
ts
import { Camera3D, DirectLight, Engine3D, AtmosphericComponent, View3D, HoverCameraController, KelvinUtil, MeshRenderer, Object3D, Scene3D, SphereGeometry, UnLitMaterial, Color } from '@orillusion/core';
class Sample_Materials {
scene: Scene3D;
lightObj: Object3D;
constructor() {}
async run() {
await Engine3D.init();
this.scene = new Scene3D();
let cameraObj = new Object3D();
let mainCamera = cameraObj.addComponent(Camera3D);
this.scene.addChild(cameraObj);
mainCamera.perspective(60, Engine3D.aspect, 1, 5000.0);
mainCamera.object3D.addComponent(HoverCameraController);
await this.initScene();
// add an Atmospheric sky enviroment
this.scene.addComponent(AtmosphericComponent).sunY = 0.6;
// create a view with target scene and camera
let view = new View3D();
view.scene = this.scene;
view.camera = mainCamera;
// start render
Engine3D.startRenderView(view);
}
async initScene() {
{
this.lightObj = new Object3D();
this.lightObj.x = 0;
this.lightObj.y = 0;
this.lightObj.z = 0;
this.lightObj.rotationX = 0;
this.lightObj.rotationY = 0;
this.lightObj.rotationZ = 0;
let lc = this.lightObj.addComponent(DirectLight);
lc.lightColor = KelvinUtil.color_temperature_to_rgb(5355);
lc.intensity = 1.7;
this.scene.addChild(this.lightObj);
}
{
// UnLitMaterial
let sphere = new Object3D();
let mr = sphere.addComponent(MeshRenderer);
mr.geometry = new SphereGeometry(2.5, 30, 30);
let mat = new UnLitMaterial();
mat.baseColor = new Color(1, 1, 1, 1);
mr.material = mat;
this.scene.addChild(sphere);
sphere.localPosition.set(0, 0, 0);
}
}
}
new Sample_Materials().run();
PBR 材质
我们提倡使用 LitMaterial 即 PBR
材质进行渲染。PBR
是 Physically-Based Rendering
的缩写,是指基于物理渲染的材质,它更符合真实的物理光照模型。
属性 | 描述 |
---|---|
baseColor | 材质基础颜色 |
emissiveColor | 材质发光颜色 |
emissiveIntensity | 材质发光强度,需要开启 BloomPost 才能显示发光效果 |
roughness | 材质粗糙程度 |
metallic | 材料金属度 |
normalScale | 法线贴图对材质的影响程度 |
clearCoat | 透明涂层强度 |
envMap | 环境贴图 |
envIntensity | 环境光强度 |
materialF0 | 材质反射率 |
ao | Ambient Occlussion, 处理环境光对物体遮挡的效果 |
aoMap | 环境光遮挡贴图 |
baseMap | 基础贴图 |
normalMap | 法线贴图 |
maskMap | 遮罩贴图 |
emissiveMap | 材质发光贴图 |
brdfLUT | BRDF查找表 |
ts
import { Camera3D, DirectLight, Engine3D, AtmosphericComponent, View3D, HoverCameraController, MeshRenderer, Object3D, Scene3D, SphereGeometry, LitMaterial } from '@orillusion/core';
class Sample_Materials {
scene: Scene3D;
lightObj: Object3D;
constructor() {}
async run() {
await Engine3D.init();
this.scene = new Scene3D();
let cameraObj = new Object3D();
let mainCamera = cameraObj.addComponent(Camera3D);
this.scene.addChild(cameraObj);
mainCamera.perspective(60, Engine3D.aspect, 1, 5000.0);
mainCamera.object3D.addComponent(HoverCameraController);
await this.initScene();
// add an Atmospheric sky enviroment
this.scene.addComponent(AtmosphericComponent).sunY = 0.6;
// create a view with target scene and camera
let view = new View3D();
view.scene = this.scene;
view.camera = mainCamera;
// start render
Engine3D.startRenderView(view);
}
async initScene() {
{
this.lightObj = new Object3D();
this.lightObj.x = -20;
this.lightObj.y = 20;
this.lightObj.z = -20;
this.lightObj.rotationX = 45;
this.lightObj.rotationY = 45;
this.lightObj.rotationZ = 0;
let lc = this.lightObj.addComponent(DirectLight);
lc.intensity = 0.2;
this.scene.addChild(this.lightObj);
}
{
// PRB
let sphere = new Object3D();
let mr = sphere.addComponent(MeshRenderer);
mr.geometry = new SphereGeometry(2.5, 30, 30);
let mat = new LitMaterial();
mr.material = mat;
this.scene.addChild(sphere);
sphere.localPosition.set(0, 0, 0);
}
}
}
new Sample_Materials().run();
材质设置
颜色
ts
let mat = new UnLitMaterial();
mat.baseColor = new Color(1, 0, 0, 1);
透明度 & 混合模式
ts
let mat = new UnLitMaterial();
mat.transparent = true;
mat.blendMode = BlendMode.ALPHA;
mat.baseColor = new Color(1, 0, 0, 0.5);
混合模式详情请参考 BlendMode
切换剔除模式
为了节省 GPU
性能,Orillusion
默认使用 back
剔除模式,即只渲染物体正面材质,我们可以设置材质 cullMode 属性来切换显示模式
ts
let mat = new LitMaterial();
mat.cullMode = GPUCullMode.none; // 不剔除,双面显示
mat.cullMode = GPUCullMode.front; // 剔除正面,显示后面
mat.cullMode = GPUCullMode.back; // 剔除后面,显示正面
UV 变换
模型顶点会存有多组纹理映射坐标,定义了该顶点在纹理中对应的2D坐标,它通常由一个二维变量 (u,v)
表示,所以也被称为 UV坐标
。
我们可以通过对模型的 uv
坐标进行矩阵变换来自定义纹理的映射关系。比如,设置材质shader 中的 transformUV1
变量来对原始 uv
进行 位移(offset)
和 缩放(scaling)
的坐标变换:
ts
let mat = new LitMaterial();
// 获取 uv - Vector4(offsetU, offsetV, scalingU, scalingV)
let uv: Vector4 = mat.getUniformV4(`transformUV1`);
// 设置 uv
uv.set(1, 1, 2, 2);
// 更新 uv
mat.setUniformVector4(`transformUV1`, uv);
TIP
从 v0.8
开始,LitMaterial 使用 xxxMapOffsetSize
获取和设置各个贴图的 uv
变换:
ts
let mat = new LitMaterial();
let baseUV = mat.getUniformV4('baseMapOffsetSize');
let normalUV = mat.getUniformV4('normalMapOffsetSize');
let emissiveUV = mat.getUniformV4('emissiveMapOffsetSize');
let roughnessUV = mat.getUniformV4('roughnessMapOffsetSize');
let metallicUV = mat.getUniformV4('metallicMapOffsetSize');
let aoUV = mat.getUniformV4('aoMapOffsetSize');