ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CesiumJS 体素渲染:让体积数据在浏览器里跑满帧

CesiumJS 体素渲染:让体积数据在浏览器里跑满帧 CesiumJS 体素渲染让体积数据在浏览器里跑满帧【免费下载链接】cesiumAn open-source JavaScript library for world-class 3D globes and maps :earth_americas:项目地址: https://gitcode.com/GitHub_Trending/ce/cesium问题锚定256×256×128 的地质体积数据怎么展示才不掉帧你手头有一份 256×256×128 的地质勘探网格文件每个格点都存着密度和温度现在要在浏览器里显示出来还能旋转、缩放。CesiumJS 体素渲染是目前开源社区做 3D 体积数据可视化的一条现成路径——几行代码就能把体积挂进 3D Tiles 场景用户能看清内部结构帧率也守得住。下面先讲清楚原理再接一个最小可跑通的场景最后谈帧率怎么保。原理拆解体素与表面网格的区别以及 3D Tiles 怎么装体积数据此处插入项目内体素 vs 表面网格对比效果图表面网格只记录物体的“外壳”顶点、面片、法线你看到的永远只是外面一层。体素则是把物体内部填满的小格子每个格点存自己的数值——密度、温度、浓度——最终屏幕上的颜色由沿光线的累积效果决定。所以“山体内部是什么”这种问题表面渲染回答不了体素渲染可以。CesiumJS 通过 3D Tiles 体素扩展来承载这类体积数据tileset 在 content 节点里声明体素内容引擎负责加载、分级和光线追踪。仓库里真实示例 tileset 的一小段长这样{ content: { uri: tiles/{level}/{x}/{y}/{z}.gltf, extensions: { 3DTILES_content_voxels: { dimensions: [2, 4, 3], class: voxel } } } }三个字段的作用一句话说明白dimensions决定每个方向上有多少格点瓦片的bounds包围盒把体积放进世界坐标系定位shapebox、cylinder、ellipsoid则限定光线只在什么边界内采样。光线追踪部分说白了就是三步从相机发一条光线沿线步进采样每过一个点把颜色累积起来。剥掉引擎细节主干逻辑是// 伪代码一条光线在体积内的完整旅程 function traceRay(origin, direction) { let color new Color(0, 0, 0, 0); // 累积颜色 for (let d stepSize; d maxDist; d stepSize) { const p add(origin, mul(direction, d)); // 当前采样点 if (!isInsideShape(p)) break; // 出了形状边界终止 const s textureSample(p); // 读取该格点的属性 color blend(color, s, d); // 按透明度累积 } return color; }动手路径三行代码挂上体素图元加载一份 tileset.json环境准备很轻把仓库拿下来它的 sandcastle gallery 里就备好了 voxels、voxel-picking、voxels-in-3d-tiles 三个体素示例和配套数据按仓库说明跑起本地服务即可本文不展开编译过程。git clone https://gitcode.com/GitHub_Trending/ce/cesium最省事的路径是加载一份现成的 3D Tiles 体素 tilesetconst viewer new Cesium.Viewer(cesiumContainer); // 1. 指向带 3DTILES_content_voxels 扩展的 tileset const provider await Cesium.Cesium3DTilesVoxelProvider.fromUrl( SampleData/Cesium3DTiles/Voxel/VoxelBox3DTiles/tileset.json, ); // 2. 创建体素图元并挂到场景 const primitive new Cesium.VoxelPrimitive({ provider }); primitive.nearestSampling true; // 最近邻采样适合离散标量场 viewer.scene.primitives.add(primitive); // 3. 相机直接对准体积 viewer.camera.flyToBoundingSphere(primitive.boundingSphere, { duration: 0 });跑起来就是上图这样的场景一个半透明体积挂在 3D Tiles 场景里旋转能看到内部数值变化。在这个基础上有三点值得知道多属性通道在 tileset 的 schema 里声明多个属性密度、温度、速度再通过自定义着色器逐个取出来映射成颜色和透明度仓库里的 VoxelMultiAttribute3DTiles 样本就是这么配的。形状切换创建 provider 时用VoxelShapeType选边界形状BOX / CYLINDER / ELLIPSOID地质块体一般选盒体大气柱状数据选圆柱云团或行星效应选椭球。采样与拾取stepSize控制光线步进大小scene.pickVoxel能在点击时读回被拾取格点的坐标和属性值做数据反查很顺手。性能与调优让 256³ 体积数据跑满 60fps体积渲染的帧率基本由“每个像素采样多少次”决定常见分档如下相机距离采样策略帧率影响近小stepSize步数多单像素采样成本高最容易被吃掉帧率中默认步数质量与开销平衡默认选择远大步长 粗级 tileset单像素采样少帧率最稳远档位里的“粗级 tileset”正是 3D Tiles 体素扩展自带的机制用implicitTiling和availableLevels声明细分层级远处加载低分辨率网格相机靠近时引擎自动切到细网格。体积数据的 LOD 就这样做出来了——数据分层采样密度跟着分层。另一大开销是采空区域。用八叉树把空块标记出来整棵子树都能直接跳过function makeNode(block) { // 整块为空 - 标记成空节点遍历时省掉 return block.every((v) v.alpha 0) ? EMPTY : { samples: block }; } function castRay(origin, dir, node) { if (node EMPTY) return null; // 关键跳过整棵子树一次都不采 if (node.samples) return stepInside(node.samples); return firstHit(node.children, castRay, origin, dir); }重点在“为什么跳过”一条光线不穿过这棵子树那么细的采样都白做省下的开销与这块体积的规模同量级。内存侧三句话带过把大体积拆成瓦片做流式加载相机走到哪取到哪属性网格用压缩纹理格式存放减少上传和带宽占用已解码的瓦片复用切换层级时按 LRU 淘汰。等 WebGPU 体积渲染成为默认方案后后两件事会更关键因为体积数据的第一瓶颈往往是显存带宽而不是算力。落地与展望体素渲染已经在用的两个地方地质勘探是目前最成熟的落点。地震或电阻率勘探的数据通常以二进制网格文件交付转成本地 tileset、把标量映射成色谱后场景里就多出一块半透明“地质块体”旋转时矿体边界和断层面直接可见点一下pickVoxel还能读出该点密度值工程师拿它和测井曲线快速对位比翻二维切片直观得多。医学成像则是天然契合。一个 CT 序列本身就是 512×512×N 的网格降采样转成体积 tileset 后以椭球体积挂进 CesiumJS调整stepSize相当于改变二维切片的“厚度”在平滑度和帧率之间找平衡再配合人体三维模型病灶相对体表的位置比单看一张切片清楚。WebGPU 给这块带来了两个实在的收益数万条光线可以在计算着色器里并行求值硬件光线追踪加速WebGPU 1.1 已引入 RT 原语又能接管边界求交。也就是说同一份体积数据采样步数更多、雾更厚、实时光照加上帧率依然稳下一代 WebGPU 体积渲染的工程形态会和上文这套 3D Tiles 管线非常接近。接下来可以做的先跑一遍仓库里的 voxels-in-3d-tiles 示例感受一下帧率和色谱效果再把自己的一份数据集转成带 3DTILES_content_voxels 扩展的 tileset.json最后调stepSize和采样层级把帧率守稳为止。【免费下载链接】cesiumAn open-source JavaScript library for world-class 3D globes and maps :earth_americas:项目地址: https://gitcode.com/GitHub_Trending/ce/cesium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表