Skip to content

材质

材质总览

引擎通过 MeshRenderer 组件给物体添加相应的 材质 对象,用来模拟其颜色、光照、纹理等属性。目前引擎内置了2种经典材质模型:

名称描述
UnLitMaterial不计算光照和阴影,仅渲染原始颜色与纹理信息
LitMaterialPBR 即基于物理渲染,旨在模拟现实世界光照效果

我们推荐使用的 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基础贴图

WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

<
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 材质

我们提倡使用 LitMaterialPBR 材质进行渲染。PBRPhysically-Based Rendering 的缩写,是指基于物理渲染的材质,它更符合真实的物理光照模型。

属性描述
baseColor材质基础颜色
emissiveColor材质发光颜色
emissiveIntensity材质发光强度,需要开启 BloomPost 才能显示发光效果
roughness材质粗糙程度
metallic材料金属度
normalScale法线贴图对材质的影响程度
clearCoat透明涂层强度
envMap环境贴图
envIntensity环境光强度
materialF0材质反射率
aoAmbient Occlussion, 处理环境光对物体遮挡的效果
aoMap环境光遮挡贴图
baseMap基础贴图
normalMap法线贴图
maskMap遮罩贴图
emissiveMap材质发光贴图
brdfLUTBRDF查找表

WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

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

WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

透明度 & 混合模式

ts
let mat = new UnLitMaterial();
mat.transparent = true;
mat.blendMode = BlendMode.ALPHA;
mat.baseColor = new Color(1, 0, 0, 0.5);

WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

混合模式详情请参考 BlendMode

切换剔除模式

为了节省 GPU 性能,Orillusion 默认使用 back 剔除模式,即只渲染物体正面材质,我们可以设置材质 cullMode 属性来切换显示模式

ts
let mat = new LitMaterial();
mat.cullMode = GPUCullMode.none; // 不剔除,双面显示
mat.cullMode = GPUCullMode.front; // 剔除正面,显示后面
mat.cullMode = GPUCullMode.back; // 剔除后面,显示正面

WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

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

WebGPU is not supported in your browser
Please upgrade to latest Chrome/Edge

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