RenderView
RenderView 把一个 Engine-owned World、一个 borrowed Three.js Camera 与 Canvas 上的归一化 viewport 绑定起来。
ts
import { PerspectiveCamera } from 'three';
const camera = new PerspectiveCamera(50, 1, 0.01, 1000);
camera.position.set(0, 2, 5);
camera.updateProjectionMatrix();
camera.updateMatrixWorld(true);
const view = engine.pipeline.addView({
world: engine.world,
camera,
viewport: [0.65, 0.05, 0.3, 0.4],
order: 10,
});坐标与顺序
viewport = [x, y, width, height] 使用左上角原点,四个值都在 [0, 1]。默认值 [0, 0, 1, 1] 铺满 Canvas。
View 按 order 升序渲染;相同 order 保持加入顺序。重叠区域中最后渲染的 enabled View 同时也是 Pointer 选择的 topmost View。
┌──────────── full Canvas ────────────┐
│ default View │
│ ┌─────────────┐ │
│ │ inset View │ │
│ └─────────────┘ │
└─────────────────────────────────────┘可变与不可变字段
ts
view.enabled = false;
view.order = 20;
view.viewport = [0.7, 0.05, 0.25, 0.3];
console.log(view.world, view.camera); // 创建后不可换绑
engine.pipeline.removeView(view);
console.log(view.removed); // trueworld 与 camera 创建后不可变;需要换绑时移除旧 View 并创建新 View。enabled/order/viewport 的修改会在 mutation cold path 重建排序后的只读 snapshot,active frame 中修改会被拒绝。
pipeline.views 包含所有未移除 View,包括 disabled View。
多 World
ts
const secondWorld = engine.createWorld();
const secondView = engine.pipeline.addView({
world: secondWorld,
camera,
viewport: [0.5, 0, 0.5, 1],
});销毁 extra World 会同步移除绑定它的全部 RenderView。默认 World 不能单独销毁。
Camera 所有权
Pipeline 只借用 Camera,不会 dispose,也不会自动更新业务 Camera 的 projection/world matrix。需要跟随 View 变化时,由业务明确更新:
ts
function updateInsetCamera() {
const [, , width, height] = view.viewport;
camera.aspect = engine.size.width * width / (engine.size.height * height);
camera.updateProjectionMatrix();
camera.updateMatrixWorld(true);
}只有 Engine 的默认 View/Camera 组合具有自动 aspect 策略。
空 View
移除或禁用全部 View 后,Pipeline 不渲染任何 Scene,并在转换到空状态时清除旧 Canvas 内容。Pointer 不会定位到 RenderView,hitTest 返回 view: null。