Skip to content

Scene3D

Scene3D 继承自 Object3D,拥有 Object3D 相同的属性和方法,不同的是 Scene3D 是引擎渲染根节点,是场景树的最高层级,所有想要被渲染的节点必须添加到 Scene3DScene3D 的子节点中。

Scene3D

Scene3D 主要功能:

  1. Scene3D 中定义了场景的天空盒和环境光贴图。
  2. Scene3D 可以用来控制和管理场景树中的节点,例如:添加、删除、查找节点。

基础用法

ts
await Engine3D.init();
// 创建场景
let scene = new Scene3D();
// 添加一个节点
let obj = new Object3D();
scene.addChild(obj);
// 添加相机节点
let cameraObj = new Object3D();
let camera = cameraObj.addComponent(Camera3D);
scene.addChild(cameraObj);

// 开始渲染
let view = new View3D();
view.scene = scene;
view.camera = camera;
Engine3D.startRenderView(view);

// 移除一个节点
scene.removeChild(obj);

大气天空盒

可以通过 AtmosphericComponent 组件创建一个大气散射的天空盒:

ts
// 添加大气天空盒组件,自动生成背景和环境光
let sky = scene3D.addComponent(AtmosphericComponent);

详见以下示例:

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

<
ts
import { Engine3D, Scene3D, Object3D, Camera3D, AtmosphericComponent, View3D } from '@orillusion/core';
import * as dat from 'dat.gui';

// initializa engine
await Engine3D.init();
// create a Scene3D
let scene3D = new Scene3D();

// add an Atmospheric sky enviroment
let sky = scene3D.addComponent(AtmosphericComponent);
// set sun position
sky.sunX = 0.8;
sky.sunY = 0.54;
// set exposure
sky.exposure = 1;

// create a camera
let cameraObj: Object3D = new Object3D();
let camera = cameraObj.addComponent(Camera3D);
camera.perspective(60, Engine3D.aspect, 1, 5000.0);
scene3D.addChild(cameraObj);

// create a view with target scene and camera
let view = new View3D();
view.scene = scene3D;
view.camera = camera;

// start render
Engine3D.startRenderView(view);

// debug GUI
const GUIHelp = new dat.GUI({ name: 'Orillusion' });
GUIHelp.addFolder('Atmospher');
GUIHelp.add(sky, 'sunX', 0, 1, 0.01);
GUIHelp.add(sky, 'sunY', 0, 1, 0.01);
GUIHelp.add(sky, 'eyePos', 1000, 2000, 10);
GUIHelp.add(sky, 'sunRadius', 100, 1000, 10);
GUIHelp.add(sky, 'sunRadiance', 0, 20, 1);
GUIHelp.add(sky, 'sunBrightness', 0, 1, 0.1);

通过 AtmosphericComponent 组件的 sunX, sunY, exposure 等属性来调整环境光的的变化。

ts
let sky = scene3D.addComponent(AtmosphericComponent);
sky.sunY = 0.54  // 太阳垂直位置,可以调节环境光亮度
sky.exposure = 1.5; //调整环境光曝光度, 默认值1
sky.roughness = 0.5; // 设置天空盒背景模糊强度, 范围[0, 1], 默认值0

自动跟随灯光

除了手动设置 sunX, sunY 的数值,引擎还支持自动跟随场景中的灯光角度调整大气环境光位置

ts
// 平行光
let lightObj3D = new Object3D();
lightObj3D.rotationX = 46;
lightObj3D.rotationY = 62;
lightObj3D.rotationZ = 0;
let directLight = lightObj3D.addComponent(DirectLight);

let sky = scene3D.addComponent(AtmosphericComponent);
// 跟随平行光自动设置 sunX sunY
sky.relativeTransform = directLight.transform

自定义天空盒

如果想要自定义天空盒材质纹理,可以通过给 Scene3D 添加 SkyRenderer 组件来显示自定义背景; 同时,可以通过 Scene3D 对象的 envMap 属性来设置环境光。

1. 单色背景和环境光

可以通过 SolidColorSky 创建一个纯色的贴图来设置背景和环境光:

ts
import {Scene3D, SolidColorSky, Color, SkyRenderer} from '@orillusion/core';

let scene = new Scene3D();
// 创建一个纯色贴图
let colorSky = new SolidColorSky(new Color(0.5, 1.0, 0.8, 1))
// 添加 SkyRenderer 组件,然后设置 map 贴图
let sky = scene.addComponent(SkyRenderer);
sky.map = colorSky;

// 同时设置单色环境光
scene.envMap = colorSky;

2. 十字天空盒

可以通过加载 十字立方贴图 设置天空盒:

ts
// 可以加载一张完整十字立方贴图
let textureCube = Engine3D.res.loadTextureCube('path/to/sky.png')
// 或加载独立的6张立方贴图
textureCube = Engine3D.res.loadTextureCube([
    'path/to/px.png',
    'path/to/nx.png',
    'path/to/py.png',
    'path/to/ny.png',
    'path/to/pz.png',
    'path/to/nz.png'
])
// 添加 SkyRenderer 组件,设置 map 贴图
let sky = scene.addComponent(SkyRenderer);
sky.map = textureCube;

// 设置环境光
scene.envMap = textureCube;

目前十字天空盒只支持 LDR 普通格式的图片。

3. 全景天空盒

引擎还支持设置 全景图(equirectangular) 类型的天空盒。我们可以通过内置的 res 快速加载普通 RGBA 格式的 LDR 图片, 也支持加载 RGBE 格式的 HDR 图片:

ts
// 普通全景贴图
let skyTexture = Engine3D.res.loadLDRTextureCube('path/to/sky.png');
// HDR全景贴图
skyTexture = Engine3D.res.loadHDRTextureCube('path/to/sky.hdr');

// 添加 SkyRenderer 组件,设置 map 贴图
let sky = scene.addComponent(SkyRenderer);
sky.map = skyTexture;

// 设置环境光
scene.envMap = skyTexture;

4. 透明背景

如果想显示透明背景,通过关闭天空盒组件来隐藏背景,注意一般还需要使用透明 Canvas 才能生效:

ts
// 初始化引擎
await Engine3D.init({
    canvasConfig:{
        alpha: true, // 使用透明的 Canvas 配置
        zIndex: 1
    }
});
let scene = new Scene3D();

// 可以先添加大气天空盒,获得基本环境光
let sky = scene3D.addComponent(AtmosphericComponent);
// 再隐藏大气天空盒, 环境光不会消失
sky.enable = false

当然也可以不添加大气天空盒或背景,直接设置环境光

ts
// 设置一个简单白色环境光
scene.envMap = new SolidColorSky(new Color(0.75, 0.75, 0.75));
// 或者加载环境贴图
scene.envMap = await Engine3D.res.loadHDRTextureCube('path/to/sky.hdr');

更多详细用法请参考 Scene3D