核心内容摘要
亲测Z-Image-Turbo:16G显存跑出Midjourney级画质,效果惊艳
在使用 three.js 的过程中我们经常会遇到这样的需求有些物体只想让某个相机看到有些辅助线、调试对象不想被最终渲染多相机渲染时希望不同相机关注不同的物体做选中 / 拾取时只想检测部分物体three.js 并没有提供“分组渲染开关”这样的显式 API但其实它内部提供了一套非常轻量、但功能强大的机制——Layers层。
这篇文章将从概念、原理、用法、常见误区、实战场景几个方面完整讲清 three.js 的 Layers。
什么是 LayersLayers是 three.js 中用于控制对象是否会被相机看到的一套机制。
一句话
总结只有当「物体的 layer」和「相机的 layer」有交集时物体才会被渲染一个直观的类比非常重要你可以把 Layers 理解为“物体和相机身上贴的标签”物体贴了哪些标签相机只看哪些标签只有标签匹配物体才会被看到。
Layers 的底层结构其实是一个位掩码three.js 的 Layers 本质上是一个32 位的位掩码bitmask。
object.layers.mask // number camera.layers.mask // numberthree.js最多支持 32 个 layerlayer 编号范围是0 ~ 31每一位表示是否属于某一层默认情况layer 0开启 layer 1~31关闭也就是说所有 Object3D 默认都在 layer 0所有 Camera 默认也只看 layer 0所以你平时不用 layers也能正常渲染
一个最基础的示意图┌─────────────┐ ┌─────────────┐ │ Object A │ │ Object B │ │ layer 0 │ │ layer 1 │ └──────┬──────┘ └──────┬──────┘ │ │ ▼ ▼ ┌────────────────────────────────────┐ │ Camera │ │ enabled: layer 0 │ └────────────────────────────────────┘结果Object A ✅ 可见Object B ❌ 不可见
Layers 的常用 API1️⃣ 设置物体所在的层mesh.layers.set(
; // 只属于 layer 1⚠️ 注意set会清空原有层2️⃣ 追加一个 layer常用mesh.layers.enable(
; // 同时属于 layer 0 和 23️⃣ 移除某个 layermesh.layers.disable(
;4️⃣ 相机只渲染某一层camera.layers.set(
;5️⃣ 判断 layer 是否匹配底层逻辑object.layers.test(camera.layers);只有返回true物体才会被渲染。
渲染阶段 Layers 到底发生在什么时候这是一个非常容易被忽略但非常关键的点。
three.js 在渲染时逻辑大致是scene.traverse(object) └─ if object.layers.test(camera.layers) └─ push 到渲染队列也就是说Layers 是在“渲染收集阶段”生效的而不是在 GPU 阶段带来的好处几乎没有性能开销比 visible false 更“底层”对拾取、辅助相机特别友好
一个最经典的例子主相机 辅助相机场景需求主相机渲染正常场景辅助相机只渲染辅助线 / Gizmo / 调试物体// 主相机 const mainCamera new THREE.PerspectiveCamera(); mainCamera.layers.enable(
; // 辅助相机 const helperCamera new THREE.PerspectiveCamera(); helperCamera.layers.set(
; // 普通物体 mesh.layers.set(
; // 辅助线 helperLine.layers.set(
;渲染流程renderer.render(scene, mainCamera); renderer.render(scene, helperCamera);结构示意图
Layers 和 visible 的区别重点对比点layersvisible是否参与遍历❌❌是否被相机控制✅❌是否支持多相机✅❌语义“谁能看到”“是否存在”一个非常重要的结论visible 更像是“物体存在与否”layers 更像是“谁能看到它”
Layers 在 Raycaster拾取中的用法这是 layers 的一个高级但极其实用的用法。
raycaster.layers.set(
;此时Raycaster只会检测 layer 1 的物体其他物体直接被忽略常见应用只拾取可交互物体忽略背景 / 装饰模型点云拾取时分层处理
一个容易踩的坑很多人中招❌ 误区以为 set 是“追加”mesh.layers.set(
; mesh.layers.set(
;结果mesh只在 layer 2layer 1 被清掉了✅ 正确方式mesh.layers.set(
; mesh.layers.enable(
;
一个完整的小 Demo可直接跑const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight,
1, 1000 ); // 只看 layer 1 camera.layers.set(
; const renderer new THREE.WebGLRenderer(); document.body.appendChild(renderer.domElement); // 红色立方体不可见 const cube1 new THREE.Mesh( new THREE.BoxGeometry(), new THREE.MeshBasicMaterial({ color: red }) ); cube
layers.set(
; scene.add(cube
; // 绿色立方体可见 const cube2 new THREE.Mesh( new THREE.BoxGeometry(), new THREE.MeshBasicMaterial({ color: green }) ); cube
layers.set(
; cube
position.x 2; scene.add(cube
; renderer.render(scene, camera);
什么时候应该用 Layers✅ 推荐使用场景多相机渲染辅助对象 / GizmoRaycaster 精确控制Debug / Overlay 渲染点云 / 标注系统分层❌ 不适合用 Layers 的场景单纯开关物体显示用visible逻辑分组用Group
十二、