mcpField
T
threejs-scene

threejs-scene

github.com/moh4696设计与 UI18544 次安装2 天前更新
代码仓库

关于 threejs-scene

threejs-scene 是一项技能和起始项目,用于通过 three.js 构建基于实际尺寸的 3D 场景。它引导开发者从参考尺寸和几何建模,逐步完成照明、性能检查、响应式视角及逐帧精确录制。

主要功能

  1. 01包含渲染器和照明设置的起始场景
  2. 02重复部件与扫掠几何建模模式
  3. 03与天空匹配的照明预设
  4. 04摄像机视点与动画过渡
  5. 05性能检查与逐帧精确录制

适用场景

  1. 01构建按尺寸建模的建筑 3D 场景
  2. 02通过实例化创建重复几何体
  3. 03调整不同预设下的场景照明
  4. 04检查并录制 three.js 场景

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/moh4696/open-3d-skills --skill threejs-scene

安装后在 Claude Code 中输入/threejs-scene确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
assets/starter/
env.js
index.html
kit.js
main.js
scene.js
references/
geometry.md
lighting.md
performance.md
shaders.md

详细介绍

three.js 场景

令人信服的 3D 页面,关键在于光线和比例,而非多边形数量。白宫之所以看起来像白宫,是因为它的楼层高度、柱间距和檐口深度都恰到好处,也因为低角度的阳光在建筑上投下长长的阴影,而不是因为每扇窗户都有窗框。这项技能会像制作建筑模型一样构建场景:基于真实尺寸,用代码实现,并妥善处理光照。

从起始模板开始

assets/starter/ 是一个完整可用的场景(草坪上的圆形凉亭),下文提到的内容都已接好。复制它,保留 env.js、kit.js 和 main.js,然后用你的主题替换 scene.js。

cp -r assets/starter my-scene && cd my-scene
python3 -m http.server 8000      # any static server; ES modules need http://, not file://
文件内容
index.html固定使用 three r169([email protected])的导入映射、画布、标题、光照按钮、加载器
main.js渲染器、摄像机、后期处理栈、质量档位、视角和运镜、录制钩子、帧循环
env.js天空、太阳、基于图像的光照、雾、云、夜空;三个可混合的预设;阴影适配
kit.js带种子的随机数生成器、画布纹理、实例化工具包、旋转成形、弧线、带斜接角的轮廓扫掠
scene.js示例主题和所有值得借鉴的模式

URL 参数开箱即用:?view=front|corner|low|aerial、?light=morning|golden|night、?quality=high|balanced|fast,以及使用 frame-capture 进行帧精确录制的 ?record=1。

工作流

  1. 开始编写几何体前,先收集参考资料和尺寸。 准备平面图、立面图、各侧照片以及真实尺寸(楼层高度、开间间距、柱径、轴距)。将它们以米为单位写成场景文件顶部的常量。按猜测比例搭建的建筑无论多精细,看起来都像玩具。
  2. 先用方块搭建整体结构,确保尺寸正确,并从访客会看到的视角检查。现在就修正比例;细节掩盖不了问题。
  3. 按类型添加细节,而不是逐个制作。 将一根柱子、一扇窗户、一个栏杆柱写成函数,然后通过 Kit 放置数百个实例(每个部件一次绘制调用)。线脚、路缘、台阶和栏杆都是沿路径扫掠的轮廓(sweep);圆形物体则用旋转成形制作。
  4. 添加光照,使用 env.js 中的预设,然后调整曝光、太阳高度和雾效来营造氛围。大部分真实感都来自这一步。
  5. 增添生气: 为树木添加风动效果、水面、旗帜、行人或车流等实例化精灵,以及夜间亮起的灯。所有效果都由共享 uniforms(U.uTime、U.uWind、U.uNight)驱动,确保录制和光照变化保持同步。
  6. 测量并检查:使用 site-check 检查帧时间、绘制调用、每种光照下的每个视角,以及手机端效果。然后用 frame-capture 录制。

重要的渲染设置

这些设置位于 main.js 中;除非你知道原因,否则请保留。

  • 色调映射 使用 ACESFilmicToneMapping,并根据预设设置曝光(0.6 到 1.0)。不使用色调映射时,明亮的天空会过曝,整个画面看起来像 2009 年的游戏。
  • 在合成器中抗锯齿,而非在画布中: 渲染器设置为 antialias: false,并为效果合成器使用 samples: 4 的 HalfFloatType 渲染目标。启用后期处理后,画布 MSAA 不起作用。
  • 后期处理堆栈: RenderPass → GTAOPass(环境光遮蔽:为飞檐下方、柱子之间、墙地交界处添加接触阴影)→ UnrealBloomPass(白天强度约为 0.12,夜间为 0.5)→ OutputPass(最后进行色调映射和 sRGB 转换)。GTAO 通道通过子类化来隐藏任何带有 userData.noAO 的内容(天空层、粒子、玻璃),因为 AO 会使其看到的任何内容变暗。
  • 以天空本身为基础的图像光照: env.js 会将天空的私有副本渲染到 PMREM 环境贴图中,因此在每个预设下,反射和环境光的颜色都与天空相匹配。预设渐变期间重新生成环境贴图即可(每六帧一次就够了:PMREM 开销很大)。
  • 只有一个投射阴影的太阳, 使用 4096 分辨率的贴图,其视锥体根据视野范围设置并以相机目标为中心,再对齐到整像素位置,避免相机移动时阴影闪烁。根据场景缩放的 normalBias 可消除阴影痤疮,同时避免阴影悬浮。
  • 长焦镜头: 视野为 38。在高屏幕上,启动代码会增大垂直视野,使水平视野与 16:9 屏幕相匹配;手机上也能看到完整主体,而不是被裁切的画面。
  • 像素比上限为 2。 3x 手机渲染的像素数是 2x 的 2.25 倍,却没有可见收益。

光照

env.js 中的每个预设都会同步调整天空、太阳、半球光、雾、曝光和云。调整前请阅读 references/lighting.md。简要说明如下:

  • 低角度的太阳(5 到 10 度)最能让场景显得精致:长阴影、暖色的立面和渐变天空。将光源设置在绘制的太阳上方几度,这样立面仍然清晰可见。
  • 夜晚主要是缺少光照。将太阳强度保持在 0.15 左右,让窗户和灯具通过自发光材质与辉光效果照亮场景,并尽量少添加真实光源。点光源和聚光灯使用物理单位(坎德拉),并设置 decay: 2。如果将衰减设为 1.4,再随意猜测强度,单盏喷泉灯就会让半个场景过曝。
  • 每盏暗光源仍会产生阴影渲染开销。强度为零时隐藏光源(visible = false)。

几何图案

详情和代码请参阅 references/geometry.md。最常用的图案如下:

  • sweep(profile, path, { closed, y }):沿 XZ 平面上的路径扫掠由 [向外偏移量, 高度] 对组成的 2D 轮廓,并在拐角处进行斜接。适用于飞檐、檐部、路缘、道路边缘、台阶、踢脚线、画轨。闭合路径会自动判断绕行方向,因此“向外”始终指向外侧。
  • lathe([[r, y], ...]):适用于带有柱身收分的柱子、栏杆柱、瓮、穹顶、灯柱、车轮和瓶子。
  • Kit:只需定义一次部件,使用 add 添加矩阵,再用 build 为每个部件构建一个 InstancedMesh。每个实例都可设置颜色,从而以零成本实现变化(叶片的绿色、砖块色调)。
  • canvasTex(w, h, draw):使用设定种子的 RNG 在代码中绘制纹理。适用于石材斑点、草地、碎石、标牌和窗格网格。无需下载,无许可问题,每次加载的结果都相同。
  • 对于重复次数不足以使用实例化的静态几何体,如果它们共用一种材质,可将其合并(BufferGeometryUtils.mergeGeometries)。

着色器补丁

使用 onBeforeCompile 扩展内置材质,而不是从头编写着色器;这样就能直接使用灯光、阴影和雾效。references/shaders.md 提供了经过测试的补丁,涵盖:随风摆动、朝上表面的积雪、季节性植被色调、夜间亮起的窗户、水面波纹。

容易忽略的一条规则:移动顶点的补丁也必须修改阴影渲染阶段。 为网格指定一个 customDepthMaterial(使用 RGBADepthPacking 的 MeshDepthMaterial),并让它携带相同的 onBeforeCompile,就像 scene.js 为树木所做的那样。否则,树叶会随风摆动,阴影却静止不动。

性能

以 1440x900 分辨率下的笔记本电脑 GPU 为目标:每帧低于 10 ms,绘制调用少于 300 次,三角形少于 200 万个。references/performance.md 介绍了如何测量和优化。按收益从高到低排列:

  1. 对重复部件使用实例化(Kit)。通常瓶颈是绘制调用,而不是三角形数量。
  2. 设置质量档位:high(DPR 最高为 2、GTAO、4096 阴影)、balanced(DPR 1.5)、fast(DPR 1、无 GTAO、2048 阴影)。启动模板会在慢帧持续三秒后自动降低一个档位,且录制时不会降低。
  3. 不要渲染静止内容:如果没有动画且摄像机静止,就跳过 composer.render()。
  4. 对小型、远处和扁平物体关闭 castShadow。

摄像机

  • 为每个值得查看的视图定义命名的观察点(位置加注视目标)。按钮、深层链接、静帧和录制都使用这些观察点。
  • 观察点之间的飞行会在中点处升高,并采用缓入缓出(main.js 中的 flyTo)。直接线性插值会穿过建筑物,感觉也很机械。
  • 限制 OrbitControls:将 maxPolarAngle 设为略小于水平角度,设置合理的最小和最大距离,并开启阻尼。
  • 启用 prefers-reduced-motion 时,飞行会改为直接跳转,且不会有任何自动移动。

录制

?record=1 会隐藏 UI,并从 window.__recordFrame(t) 开始按页面时钟计时执行脚本化导览。任何延迟操作都必须使用 main.js 中的 later(secs, fn),而不是 setTimeout。使用 frame-capture 技能录制(<frame-capture> 是该技能的安装位置):

python3 <frame-capture>/scripts/record.py "http://127.0.0.1:8000/?record=1" tour.mp4 --seconds 20 --ready "window.__ready === true"

完成前检查

  • 在笔记本电脑尺寸和手机上,检查每个观察点在每种灯光预设下的表现(site-check)。
  • 不得出现阴影粉刺、环绕观察时闪烁的阴影边缘,或表面交接处的深度冲突(将共面贴花偏移 1 到 2 cm)。
  • 不得有物体悬空或下沉:从低角度观察点检查每个物体与地面的交接处。
  • 帧耗时和绘制调用均符合预算。
  • 如果主题是真实地点、物体或品牌,应将页面标注为非官方研究作品,且不要使用徽标。

评论

支持 Markdown