ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OpenMontage threejs-geometry 技能深度指南:Three.js 几何体创建、BufferGeometry 与实例化渲染实战

OpenMontage threejs-geometry 技能深度指南:Three.js 几何体创建、BufferGeometry 与实例化渲染实战 OpenMontage threejs-geometry 技能深度指南Three.js 几何体创建、BufferGeometry 与实例化渲染实战【免费下载链接】OpenMontageWorlds first open-source, agentic video production system. 12 production pipelines, 100 tools, 700 agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage本篇指南以 OpenMontage 仓库中.agents/skills/threejs-geometry/SKILL.md为骨架系统讲解 Three.js 几何体的完整技术栈从内置几何体、路径型与文字几何体到底层BufferGeometry自定义顶点数据、边线与点云、实例化渲染再到几何合并与性能优化。结合仓库中tools/graphics/threejs_world.py与world-runtime.js的真实实现读者将掌握在 Agent 驱动的 3D 世界生成、数据可视化与动画项目中高效创建、修改和渲染 3D 网格的完整实战方案。快速上手从几何体到可见网格Three.js 中几何体Geometry描述的是物体的形状数据顶点、法线、UV、索引它本身不可见只有当它与材质Material组合成网格Mesh并加入场景后才会被渲染。这是理解整个几何体体系的第一原则。import * as THREE from three; // 内置几何体直接传入尺寸参数即可创建 const box new THREE.BoxGeometry(1, 1, 1); const sphere new THREE.SphereGeometry(0.5, 32, 32); const plane new THREE.PlaneGeometry(10, 10); // 创建网格几何体 材质 const material new THREE.MeshStandardMaterial({ color: 0x00ff00 }); const mesh new THREE.Mesh(box, material); scene.add(mesh);仓库中tools/graphics/templates/threejs_world/world-runtime.js的buildLandmark函数即完全遵循这一模式——它通过addMesh辅助函数把BoxGeometry、CylinderGeometry、ConeGeometry、TorusGeometry、OctahedronGeometry与MeshStandardMaterial组合出 arch拱门、tower塔、ruin废墟、crystal水晶、settlement聚落、ring环等六类地标建筑可见几何体 材质 网格是仓库所有 3D 产出的通用基石。内置几何体全家桶基础形状Basic Shapes内置几何体构造函数的第一个参数通常是主要尺寸随后是细分段数segments与角度区间参数。细分段数直接决定网格平滑度与顶点数量// BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments) // 后三个分段参数用于增加顶点密度如做形变目标时 new THREE.BoxGeometry(1, 1, 1, 1, 1, 1); // SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) // phi 是赤道方向角绕 Y 轴theta 是极方向角从北极到南极 new THREE.SphereGeometry(1, 32, 32); // 完整球体32×32 为质量与性能的良好折中 new THREE.SphereGeometry(1, 32, 32, 0, Math.PI * 2, 0, Math.PI); // 完整球体显式写出全部角度 new THREE.SphereGeometry(1, 32, 32, 0, Math.PI); // 半球phiLength π即赤道切一半 // PlaneGeometry(width, height, widthSegments, heightSegments) new THREE.PlaneGeometry(10, 10, 1, 1); // CircleGeometry(radius, segments, thetaStart, thetaLength) new THREE.CircleGeometry(1, 32); new THREE.CircleGeometry(1, 32, 0, Math.PI); // 半圆 // CylinderGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded) new THREE.CylinderGeometry(1, 1, 2, 32, 1, false); // 标准圆柱 new THREE.CylinderGeometry(0, 1, 2, 32); // 圆锥radiusTop 0 new THREE.CylinderGeometry(1, 1, 2, 6); // 六棱柱radialSegments 6 // ConeGeometry(radius, height, radialSegments, heightSegments, openEnded) new THREE.ConeGeometry(1, 2, 32, 1, false); // TorusGeometry(radius, tube, radialSegments, tubularSegments, arc) new THREE.TorusGeometry(1, 0.4, 16, 100); // TorusKnotGeometry(radius, tube, tubularSegments, radialSegments, p, q) // p、q 为纽结参数如 2,3 是经典三叶纽结 new THREE.TorusKnotGeometry(1, 0.4, 100, 16, 2, 3); // RingGeometry(innerRadius, outerRadius, thetaSegments, phiSegments) new THREE.RingGeometry(0.5, 1, 32, 1);仓库实战佐证在world-runtime.js中树木的树干使用CylinderGeometry(0.16, 0.23, 1.75, 6)6 段径向细分形成低多边形树干树冠使用ConeGeometry(0.92, 2.4, 7)7 段形成棱锥状树冠塔楼使用CylinderGeometry(0.52, 0.68, 2.4, 8)正是通过径向段数控制多边形风格的典型用法。进阶形状Advanced Shapes// CapsuleGeometry(radius, length, capSegments, radialSegments) // 胶囊体 圆柱体 两端半球帽length 为中间圆柱段高度 new THREE.CapsuleGeometry(0.5, 1, 4, 8); // DodecahedronGeometry(radius, detail)正十二面体 new THREE.DodecahedronGeometry(1, 0); // IcosahedronGeometry(radius, detail)正二十面体 // detail 0 时恰好 20 个三角面detail 越大越接近球体每次细分翻 4 倍面数 new THREE.IcosahedronGeometry(1, 0); new THREE.IcosahedronGeometry(1, 1); // 80 面明显更圆滑 new THREE.IcosahedronGeometry(1, 2); // 320 面接近低精度球体 // OctahedronGeometry(radius, detail)正八面体 new THREE.OctahedronGeometry(1, 0); // TetrahedronGeometry(radius, detail)正四面体 new THREE.TetrahedronGeometry(1, 0); // PolyhedronGeometry(vertices, indices, radius, detail)任意多面体 // vertices 为顶点坐标扁平数组每 3 个浮点一个顶点indices 为三角形索引 const vertices [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1]; const indices [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1]; new THREE.PolyhedronGeometry(vertices, indices, 1, 0);仓库实战佐证world-runtime.js用DodecahedronGeometry(0.72, 0)作为岩石粗糙多面体质感用OctahedronGeometry(0.72, 0)作为水晶与晶簇用OctahedronGeometry(0.32, 0)作为地标顶部的发光装饰。低 detail 多面体天然具备硬朗、结晶、低多边形的视觉语言是环境散射中性价比极高的几何选择。路径型形状Path-Based Shapes// LatheGeometry(points[], segments, phiStart, phiLength)绕 Y 轴旋转二维轮廓生成三维体 // 适合花瓶、酒杯等旋转对称物体points 必须从底部到顶部排列 const points [ new THREE.Vector2(0, 0), new THREE.Vector2(0.5, 0), new THREE.Vector2(0.5, 1), new THREE.Vector2(0, 1), ]; new THREE.LatheGeometry(points, 32); // ExtrudeGeometry(shape, options)沿法线方向挤压 2D Shape const shape new THREE.Shape(); shape.moveTo(0, 0); shape.lineTo(1, 0); shape.lineTo(1, 1); shape.lineTo(0, 1); shape.lineTo(0, 0); const extrudeSettings { steps: 2, // 深度方向细分步数 depth: 1, // 挤压深度 bevelEnabled: true, // 是否启用倒角 bevelThickness: 0.1, // 倒角厚度外扩量 bevelSize: 0.1, // 倒角尺寸沿面方向 bevelSegments: 3, // 倒角圆滑段数 }; new THREE.ExtrudeGeometry(shape, extrudeSettings); // TubeGeometry(path, tubularSegments, radius, radialSegments, closed) // 沿任意曲线路径生成管道path 需为 Curve 子类实例 const curve new THREE.CatmullRomCurve3([ new THREE.Vector3(-1, 0, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(1, 0, 0), ]); new THREE.TubeGeometry(curve, 64, 0.2, 8, false);从源码结构看world-runtime.js中的相机飞行路径cameraAt函数正是基于camera_path关键帧做 smoothstep 插值若需要曲线化的镜头轨迹TubeGeometry/CatmullRomCurve3同样可用于生成可视化的路径引导线与仓库中threejs-world-generation技能体系一脉相承。文字几何体Text GeometryTextGeometry不在 Three.js 核心包中需要从 examples 目录导入且必须先异步加载字体 JSONhelvetiker_regular.typeface.json为经典默认字体import { FontLoader } from three/examples/jsm/loaders/FontLoader.js; import { TextGeometry } from three/examples/jsm/geometries/TextGeometry.js; const loader new FontLoader(); loader.load(fonts/helvetiker_regular.typeface.json, (font) { const geometry new TextGeometry(Hello, { font: font, // 必需FontLoader 加载的字体对象 size: 1, // 字号 depth: 0.2, // 厚度旧版本中该参数名为 height升级时需注意 curveSegments: 12, // 曲线贝塞尔细分段数越大越圆滑 bevelEnabled: true, bevelThickness: 0.03, bevelSize: 0.02, bevelSegments: 5, }); // 居中先计算包围盒再调用 center()将几何体移动到原点 geometry.computeBoundingBox(); geometry.center(); const mesh new THREE.Mesh(geometry, material); scene.add(mesh); });BufferGeometry一切几何体的底层基座Three.js r125 之后所有内置几何体都继承自BufferGeometry——数据以**类型化数组typed arrays**存储可直接上传 GPU性能远优于旧版基于对象的 Geometry。理解BufferGeometry是自定义网格、顶点动画与大规模场景优化的必经之路。自定义 BufferGeometry 的完整示例const geometry new THREE.BufferGeometry(); // 顶点position每个顶点 3 个浮点x, y, z共 4 个顶点组成一个四边形 const vertices new Float32Array([ -1, -1, 0, // vertex 0 1, -1, 0, // vertex 1 1, 1, 0, // vertex 2 -1, 1, 0, // vertex 3 ]); geometry.setAttribute(position, new THREE.BufferAttribute(vertices, 3)); // 索引index索引化几何体顶点可被多个三角形复用显著降低内存 // 注意 Uint16Array 上限为 65535 个顶点更大网格需用 Uint32Array const indices new Uint16Array([ 0, 1, 2, // triangle 1 0, 2, 3, // triangle 2 ]); geometry.setIndex(new THREE.BufferAttribute(indices, 1)); // 法线normal光照计算必需每个顶点 3 个浮点 const normals new Float32Array([0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1]); geometry.setAttribute(normal, new THREE.BufferAttribute(normals, 3)); // UVuv纹理坐标每个顶点 2 个浮点u, v const uvs new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]); geometry.setAttribute(uv, new THREE.BufferAttribute(uvs, 2)); // 逐顶点颜色color需配合 material.vertexColors true 才生效 const colors new Float32Array([ 1, 0, 0, // red 0, 1, 0, // green 0, 0, 1, // blue 1, 1, 0, // yellow ]); geometry.setAttribute(color, new THREE.BufferAttribute(colors, 3)); // Use with: material.vertexColors trueBufferAttribute 的类型与 itemSize 速查BufferAttribute的第二个参数itemSize声明每个顶点占用几个浮点决定 GPU 如何解析数组new THREE.BufferAttribute(array, itemSize); // 类型化数组选型 new Float32Array(count * itemSize); // 顶点、法线、UV浮点精度 new Uint16Array(count); // 索引顶点数 ≤ 65535 new Uint32Array(count); // 索引更大网格WebGL2 必需 new Uint8Array(count * itemSize); // 颜色0-255 整数范围内存减半 // 各属性 itemSize 速查 // position: 3 (x, y, z) // normal: 3 (x, y, z) // uv: 2 (u, v) // color: 3 (r, g, b) 或 4 (r, g, b, a) // index: 1仓库实战佐证world-runtime.js生成地形时正是手动构造BufferGeometry——先new THREE.PlaneGeometry(size, size, resolution, resolution)获取顶点缓冲然后遍历position属性用position.getX(index)/position.getZ(index)读取坐标、position.setY(index, heightAt(x, z))写入程序化高度场最后以Float32Array构造color属性做逐顶点区域混色。这一套读顶点 → 改写 → 设置新属性的流程正是本文档BufferGeometry章节的教科书级应用。运行时修改 BufferGeometryconst positions geometry.attributes.position; // 修改单个顶点 positions.setXYZ(index, x, y, z); // 读取顶点 const x positions.getX(index); const y positions.getY(index); const z positions.getZ(index); // 关键修改后必须置 needsUpdate trueGPU 才会重新上传数据 positions.needsUpdate true; // 位置变化后重新计算法线否则光照会失真 geometry.computeVertexNormals(); // 重新计算包围盒与包围球影响视锥剔除与 Raycaster 精度 geometry.computeBoundingBox(); geometry.computeBoundingSphere();交错缓冲InterleavedBuffer进阶将位置与 UV 等属性打包进同一个数组stride 为每顶点总浮点数通过 offset 指定各属性起点。缓存更连续对大网格有内存与带宽收益const interleavedBuffer new THREE.InterleavedBuffer( new Float32Array([ // pos.x, pos.y, pos.z, uv.u, uv.v每个顶点 5 个浮点 -1, -1, 0, 0, 0, 1, -1, 0, 1, 0, 1, 1, 0, 1, 1, -1, 1, 0, 0, 1, ]), 5, // stride每顶点浮点数 ); geometry.setAttribute(position, new THREE.InterleavedBufferAttribute(interleavedBuffer, 3, 0)); // size 3, offset 0 geometry.setAttribute(uv, new THREE.InterleavedBufferAttribute(interleavedBuffer, 2, 3)); // size 2, offset 3EdgesGeometry 与 WireframeGeometry轮廓与线框两者都用于可视化几何体结构但语义不同// EdgesGeometry只提取硬边相邻面夹角超过阈值的边适合描边风格 const edges new THREE.EdgesGeometry(boxGeometry, 15); // 15 阈值角度度 const edgeMesh new THREE.LineSegments( edges, new THREE.LineBasicMaterial({ color: 0xffffff }), ); // WireframeGeometry所有三角形的全部边形成完整线框 const wireframe new THREE.WireframeGeometry(boxGeometry); const wireMesh new THREE.LineSegments( wireframe, new THREE.LineBasicMaterial({ color: 0xffffff }), );仓库实战佐证threejs_world工具定义了render_mode的三种枚举值cinematic / semantic / wireframe见tools/graphics/threejs_world.py中_RENDER_MODES其中 wireframe 模式在world-runtime.js中通过MeshBasicMaterial({ wireframe: true })实现其核心目的正是几何结构诊断——_report中diagnostic_passes明确写道wireframe: explicit terrain and asset geometry pass。这说明线框渲染不是装饰而是生产流程中验证地形拓扑与资产接触关系的必备调试手段。Points点云渲染Points将每个顶点渲染为屏幕上的一个点适合粒子、星云、散点图等无需三角面的效果。关键属性是sizeAttenuation——控制点大小是否随距离衰减const geometry new THREE.BufferGeometry(); const positions new Float32Array(1000 * 3); for (let i 0; i 1000; i) { positions[i * 3] (Math.random() - 0.5) * 10; positions[i * 3 1] (Math.random() - 0.5) * 10; positions[i * 3 2] (Math.random() - 0.5) * 10; } geometry.setAttribute(position, new THREE.BufferAttribute(positions, 3)); const material new THREE.PointsMaterial({ size: 0.1, sizeAttenuation: true, // 点大小随距离减小远小近大更具空间感 color: 0xffffff, }); const points new THREE.Points(geometry, material); scene.add(points);Lines线几何体三兄弟// Line按顺序连接所有点折线 const points [ new THREE.Vector3(-1, 0, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(1, 0, 0), ]; const geometry new THREE.BufferGeometry().setFromPoints(points); const line new THREE.Line( geometry, new THREE.LineBasicMaterial({ color: 0xff0000 }), ); // LineLoop首尾闭合的环 const loop new THREE.LineLoop(geometry, material); // LineSegments每 2 个点为一对独立线段不连续适合网格线、坐标系轴 const segmentsGeometry new THREE.BufferGeometry(); segmentsGeometry.setAttribute( position, new THREE.BufferAttribute( new Float32Array([ -1, 0, 0, 0, 1, 0, // segment 1 0, 1, 0, 1, 0, 0, // segment 2 ]), 3, ), ); const segments new THREE.LineSegments(segmentsGeometry, material);InstancedMesh批量渲染同一几何体当场景中有成百上千个相同几何体树木、岩石、粒子时逐个创建 Mesh 会产生海量 draw call。InstancedMesh用一个几何体 一份材质 一个矩阵数组一次 draw call 渲染全部实例是环境散射与群集渲染的行业标准方案const geometry new THREE.BoxGeometry(1, 1, 1); const material new THREE.MeshStandardMaterial({ color: 0x00ff00 }); const count 1000; const instancedMesh new THREE.InstancedMesh(geometry, material, count); // 用临时 Object3D 组装每个实例的变换矩阵 const dummy new THREE.Object3D(); const matrix new THREE.Matrix4(); for (let i 0; i count; i) { dummy.position.set( (Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20, ); dummy.rotation.set(Math.random() * Math.PI, Math.random() * Math.PI, 0); dummy.scale.setScalar(0.5 Math.random()); dummy.updateMatrix(); // 把 position/rotation/scale 合成矩阵 instancedMesh.setMatrixAt(i, dummy.matrix); } // 关键批量写入后标记 GPU 更新 instancedMesh.instanceMatrix.needsUpdate true; // 可选逐实例颜色需要额外实例颜色缓冲 instancedMesh.instanceColor new THREE.InstancedBufferAttribute( new Float32Array(count * 3), 3, ); for (let i 0; i count; i) { instancedMesh.setColorAt( i, new THREE.Color(Math.random(), Math.random(), Math.random()), ); } instancedMesh.instanceColor.needsUpdate true; scene.add(instancedMesh);运行时更新单个实例与拾取// 更新单个实例先取出矩阵修改后再写回并标记 const matrix new THREE.Matrix4(); instancedMesh.getMatrixAt(index, matrix); // Modify matrix... instancedMesh.setMatrixAt(index, matrix); instancedMesh.instanceMatrix.needsUpdate true; // 射线拾取Raycaster 命中后通过 instanceId 定位具体实例 const intersects raycaster.intersectObject(instancedMesh); if (intersects.length 0) { const instanceId intersects[0].instanceId; }仓库实战佐证world-runtime.js的makeInstanced函数完整复刻了这一模式——它把scatterPoints计算出的每个散布点通过dummy.updateMatrix()写入InstancedMesh并mesh.instanceMatrix.needsUpdate true用于岩石、树木树干 树冠两组实例与水晶的批量散布。threejs_world工具的_report中environment_instances统计项正是对这类实例数量的汇总其输入约束将单区域散射上限设为 1200见_normalize_spec中scatter的 clamp 范围确保实例化渲染始终在可控的 GPU 预算内。InstancedBufferGeometry超越变换与颜色的自定义实例属性进阶InstancedBufferGeometry允许为每个实例声明任意自定义属性如偏移、速度、自定义尺寸需配合自定义 Shader 使用const geometry new THREE.InstancedBufferGeometry(); geometry.copy(new THREE.BoxGeometry(1, 1, 1)); // 添加逐实例属性每个实例 3 个浮点偏移量 const offsets new Float32Array(count * 3); for (let i 0; i count; i) { offsets[i * 3] Math.random() * 10; offsets[i * 3 1] Math.random() * 10; offsets[i * 3 2] Math.random() * 10; } geometry.setAttribute(offset, new THREE.InstancedBufferAttribute(offsets, 3)); // 在 Shader 中使用 // attribute vec3 offset; // vec3 transformed position offset;几何体工具集BufferGeometryUtilsBufferGeometryUtils是官方 examples 提供的工具模块用于合并、清洗与优化几何体import * as BufferGeometryUtils from three/examples/jsm/utils/BufferGeometryUtils.js; // 合并多个几何体要求所有几何体拥有相同的属性集合不同则需先补齐 const merged BufferGeometryUtils.mergeGeometries([geo1, geo2, geo3]); // 合并并保留 groups用于多材质 Mesh[material1, material2] const merged BufferGeometryUtils.mergeGeometries([geo1, geo2], true); // 计算切线法线贴图渲染的必需预处理 BufferGeometryUtils.computeTangents(geometry); // 交错化属性把 position/normal/uv 打包为 InterleavedBuffer提升缓存局部性 const interleaved BufferGeometryUtils.interleaveAttributes([ geometry.attributes.position, geometry.attributes.normal, geometry.attributes.uv, ]);高频实用模式居中几何体geometry.computeBoundingBox(); geometry.center(); // 平移顶点使包围盒中心落在原点等比缩放到单位尺寸geometry.computeBoundingBox(); const size new THREE.Vector3(); geometry.boundingBox.getSize(size); const maxDim Math.max(size.x, size.y, size.z); geometry.scale(1 / maxDim, 1 / maxDim, 1 / maxDim); // 最长边缩放到 1克隆并变换const clone geometry.clone(); clone.rotateX(Math.PI / 2); clone.translate(0, 1, 0); clone.scale(2, 2, 2);形变目标Morph TargetsMorph 目标允许 GPU 在多个顶点姿态间平滑插值常用于表情动画、呼吸起伏等低成本形变。几何体的每个 morph 目标需要与基础几何体顶点数完全一致// 基础几何体分段数 4×4×4提供足够的顶点密度 const geometry new THREE.BoxGeometry(1, 1, 1, 4, 4, 4); // 创建形变目标复制 position 数组后修改 const morphPositions geometry.attributes.position.array.slice(); for (let i 0; i morphPositions.length; i 3) { morphPositions[i] * 2; // 拉伸 X morphPositions[i 1] * 0.5; // 压扁 Y } geometry.morphAttributes.position [ new THREE.BufferAttribute(new Float32Array(morphPositions), 3), ]; const mesh new THREE.Mesh(geometry, material); mesh.morphTargetInfluences[0] 0.5; // 50% 混合介于基础形态与目标形态之间性能优化清单优先使用索引化几何体setIndex复用顶点内存与顶点着色器负载双降合并静态网格场景中不再移动的物体用mergeGeometries合并减少 draw call大量重复对象用 InstancedMesh千级实例仅需一次 draw call按需选择细分段数段数越多越平滑但顶点数与填充率成本同步上升及时释放资源geometry.dispose()让 GPU 释放缓冲避免内存泄漏。// 常见细分段数参考以球体为例 new THREE.SphereGeometry(1, 32, 32); // 良好质量默认推荐 new THREE.SphereGeometry(1, 64, 64); // 高质量近景特写 new THREE.SphereGeometry(1, 16, 16); // 性能模式远景/批量 // 用完后释放 geometry.dispose();在 OpenMontage 中如何实战这套几何体技能本技能文档隶属于 OpenMontage 的 Agent 技能体系.agents/skills/下与threejs-fundamentals、threejs-materials、threejs-shaders、threejs-lighting、threejs-interaction等组成完整的 Three.js 技能栈其上层入口是skills/creative/3d-world-generation.md描述的三维世界生成能力。仓库中的实际落地路径为能力路由Agent 通过threejs_world工具tools/graphics/threejs_world.py执行operation: build将结构化world_spec世界尺寸、地形分辨率、区域、地标、相机路径标准化并校验工作区产出工具会把模板目录tools/graphics/templates/threejs_world/world-runtime.js、index.html、world.css与规格 JSONworld.json、world-spec.js物化为可编辑的 Three.js 工作区几何体落地运行时模板使用本文介绍的内置几何体PlaneGeometry地形、CylinderGeometry/ConeGeometry树木、DodecahedronGeometry岩石、OctahedronGeometry水晶、BoxGeometry/TorusGeometry地标、BufferGeometry逐顶点高度场、逐顶点颜色与InstancedMesh环境散射质量验证测试套件 tests/tools/test_threejs_world.py 通过operation: validate断言terrain_triangles、region_count等统计项并验证两次build产出哈希一致Determinism.SEEDED确定性输出确保几何体生成可复现、可回归。这种技能文档定义能力 → 工具执行产出 → 模板运行时消费几何体 → 测试锁定契约的四层结构正是 OpenMontage 将 Three.js 几何体知识工程化、让 AI 编码助手可直接复用的完整闭环。相关技能导航threejs-fundamentals.agents/skills/threejs-fundamentals/SKILL.md场景搭建、相机、渲染器与 Object3D 层次结构threejs-materials.agents/skills/threejs-materials/SKILL.md网格材质选型与属性threejs-shaders.agents/skills/threejs-shaders/SKILL.md自定义顶点与片元着色器操作。掌握本文的几何体创建与优化手段后即可顺畅衔接上述技能从能画出形状进阶到能用 1000 个实例填满整个三维世界。【免费下载链接】OpenMontageWorlds first open-source, agentic video production system. 12 production pipelines, 100 tools, 700 agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进