GPU纹理驱动的秘密Human Atlas用一张DataTexture控制2234个结构位移与高亮【免费下载链接】human-atlasOpen-source 3D anatomy explorer: 2,234 selectable BodyParts3D meshes, system layers, search, and exploded views.项目地址: https://gitcode.com/gh_mirrors/hu/human-atlasHuman Atlas 是一个开源的 3D 解剖结构浏览器2,234 个可单独选择的解剖网格、15 个人体系统图层、3,432 个可搜索的命名概念。它的性能秘诀藏在 GPU 里——一张 1D 的 DataTexture数据纹理就同时驱动了全部 2,234 个结构的位移、显隐与高亮让浏览器以极少的绘制调用流畅渲染 228 万个三角形。这篇文章带你快速看懂这套状态纹理方案的完整设计思路。先理解瓶颈为什么不能给每个结构建一个 Mesh最直觉的做法是为每个解剖结构创建一个THREE.Mesh。但 Human Atlas 里有 2,234 个源网格这意味着每帧至少 2,234 次绘制调用draw callCPU 提交开销巨大2,288,268 个三角形分散在数千个对象里难以合并与缓存。Human Atlas 的解法是按系统合并几何体把同属一个人体的系统骨骼、肌肉、动脉、静脉……共 15 个的网格用mergeGeometries拼成一个大几何体每个系统只用 1 个材质、1 次绘制调用。相关逻辑见 app/scene.tsx 中的分块加载与合并流程。问题来了几何体合并之后如何还能分别控制每一个小结构——让它移动、隐藏、高亮答案是把每个结构的状态写成纹理中的一个像素。核心设计每个结构 一张 RGBA Float 纹理中的一个像素场景初始化时代码创建了两张 1 维纹理见 app/scene.tsxconst width T.MathUtils.ceilPowerOfTwo(atlas.parts.length); // 2234 → 2048 const partTexture new T.DataTexture(data, width, 1, T.RGBAFormat, T.FloatType); const selectionTexture new T.DataTexture(selectedData, width, 1);纹理的每个像素RGBA 四个通道恰好编码一个结构的全部状态通道含义类型R / G / B该结构相对原始位置的位移向量 (dx, dy, dz)floatA可见性开关1 显示 / 0 丢弃float第二张selectionTexture则只用红通道0 或 255表示是否被选中供片元着色器做高亮混合。 纹理宽度取 2,234 的上取整 2 的幂2048既满足 GPU 纹理规范又留出余量。这样改变 2,234 个结构的位置从更新 2,234 个对象属性降级为填一段连续的 Float32Array然后标记needsUpdate——CPU 端只是一次内存拷贝GPU 端零额外开销。着色器注入顶点位移与高亮是如何发生的合并后的几何体上每个顶点都带一个partIndex属性该顶点属于第几个结构见 app/scene.tsx。通过 Three.js 的onBeforeCompile钩子代码在不重写整个材质的情况下注入了三段关键逻辑app/scene.tsx顶点阶段——读取状态并位移用partIndex换算出 UV(partIndex 0.5) / stateWidth采样状态纹理把 RGB 位移加到顶点坐标上同时把可见性partVisible和高亮标志partSelected传给片元着色器片元阶段——隐不可见的三角形if (partVisible 0.5) discard;被隐藏的结构在像素层面直接丢弃片元阶段——选中高亮diffuseColor.rgb mix(diffuseColor.rgb, vec3(0.42, 0.85, 0.78), partSelected * 0.75);选中结构以青色青绿色覆盖 75% 的原色形成醒目的高亮。整个过程无需在 CPU 上修改任何几何缓冲动画帧里只需要重传那张小纹理。爆炸视图CPU 算布局GPU 执行位移拉一下Explode anatomy滑块2,234 个零件会像货架清单一样展开排布。这由两部分协作完成CPU 端app/explosion-layout.ts 中的createExplosionLayout只对当前可见的零件做行式装箱算出每个零件的目标格子坐标GPU 端动画循环把插值后的位移(dx, dy, dz)与可见性写回状态纹理app/scene.tsx顶点着色器在下一帧自动采样并生效。值得注意的是脏标记策略只有当可见性、选中集、隔离模式或爆炸比例真正变化时才重新计算布局与纹理app/scene.tsx静止时场景完全不触发这些昂贵步骤——旋转、缩放相机时依旧丝滑因为轨道控制与状态更新是解耦的。精准的点选合并渲染如何不影响拾取精度渲染合并了但点击选择仍需精确到单个结构。Human Atlas 为每个结构保留了独立的挑选网格pickers它只参与射线求交、不参与渲染app/scene.tsx并且共享了同一个位移数据点击判定用的包围盒直接加上状态纹理中的位移量app/scene.tsx所以爆炸状态下点选依然分毫不差。这套渲染合并 拾取分离的拆分是高性能大规模场景的常用模式。数据从哪里来模型数据打包为 15 个二进制分块public/models/body-0.bin…body-14.bin各带.gz压缩版由 app/model-download.ts 负责解码——它会自动判断服务器返回的是 gzip 流还是原始文件避免二次解压。清单文件 public/models/atlas.json 描述每个结构的偏移量、顶点数与包围盒。3 路并发拉取分块加载进度条由此而来app/scene.tsx。法线则被量化为 16 位短整型进一步压缩内存占用app/scene.tsx。关键文件地图文件作用app/scene.tsx渲染核心状态纹理、着色器注入、动画循环、点选拾取app/anatomy.ts15 个人体系统定义、结构目录与讲解文案app/explosion-layout.ts爆炸视图的行式装箱布局算法app/model-download.ts分块模型下载与 gzip 自动解码public/models/atlas.json结构清单2,234 个部件、15 个分块、228 万三角形public/ATTRIBUTION.mdBodyParts3D 4.0 数据源说明与 CC BY 4.0 许可一句话总结Human Atlas 把每个结构的状态从 CPU 对象属性迁移成了 GPU 纹理像素一张 2048×1 的 RGBA Float DataTexture 同时承载位移与可见性另一张 1 字节纹理承载高亮。着色器采样纹理即完成全部 2,234 个结构的动画——这就是它能用极少绘制调用流畅驱动整副人体解剖的秘密。这套状态纹理思路对任何需要批量控制大量实例的项目粒子系统、大规模实例渲染、编辑器中数千对象的选择态都极具参考价值。【免费下载链接】human-atlasOpen-source 3D anatomy explorer: 2,234 selectable BodyParts3D meshes, system layers, search, and exploded views.项目地址: https://gitcode.com/gh_mirrors/hu/human-atlas创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考