编辑
2025-05-16
cesium
0

目录

在Cesium的GLTF加载流程中,高斯泼溅数据是通过扩展机制处理的。根据源码分析,下面详细说明GLTF中高斯泼溅数据的解析、处理和渲染流程。
高斯泼溅扩展的识别与解析
高斯泼溅顶点属性处理
图元标记为高斯泼溅类型
特殊处理函数
创建高斯泼溅纹理
高斯泼溅深度排序
高斯泼溅渲染着色器生成
总结:GLTF高斯泼溅处理流程
在Cesium的GLTF加载流程中,高斯泼溅数据是通过扩展机制处理的。根据源码分析,下面详细说明GLTF中高斯泼溅数据的解析、处理和渲染流程。

高斯泼溅扩展的识别与解析

GltfLoader.js 中解析扩展的部分

js
function parse(loader, frameState) { const gltf = loader.gltf; const extensions = gltf.extensions; // 检查是否存在高斯泼溅扩展 if (defined(extensions) && defined(extensions.KHR_gaussian_splatting)) { loader._hasGaussianSplatting = true; } // 继续解析其他数据... }

高斯泼溅顶点属性处理

在加载图元顶点属性时,专门检测和处理高斯泼溅所需的特殊属性:

在loadVertexAttribute函数中

js
function loadVertexAttribute(loader, accessorId, semanticInfo, primitive, ...) { const semantic = semanticInfo.semantic; // 处理高斯泼溅特有的属性 if (loader._hasGaussianSplatting) { if (semantic === VertexAttributeSemantic.SCALE || semantic === VertexAttributeSemantic.ROTATION || semantic === VertexAttributeSemantic.OPACITY) { // 加载特殊属性 attribute = createAttribute(gltf, accessorId, semanticInfo.name, semantic); // 确保正确设置属性类型 if (semantic === VertexAttributeSemantic.SCALE) { attribute.type = AttributeType.VEC3; } else if (semantic === VertexAttributeSemantic.ROTATION) { attribute.type = AttributeType.VEC4; } else if (semantic === VertexAttributeSemantic.OPACITY) { attribute.type = AttributeType.SCALAR; } } } return attribute; }

图元标记为高斯泼溅类型

在处理图元时,根据扩展信息标记图元的类型: 在loadPrimitive函数中

js
function loadPrimitive(loader, gltfPrimitive, hasInstances, frameState) { const primitive = new ModelComponents.Primitive(); // 设置基本属性 primitive.attributes = []; primitive.primitiveType = gltfPrimitive.mode; // 处理顶点属性 // ... // 检查是否启用了高斯泼溅 if (loader._hasGaussianSplatting) { // 标记为高斯泼溅图元 primitive.isGaussianSplatPrimitive = true; primitive.needsGaussianSplatTexture = true; // 设置扩展信息 primitive.extensions = { KHR_gaussian_splatting: { enabled: true } }; // 确保图元类型为点 primitive.primitiveType = PrimitiveType.POINTS; } return primitive; }

特殊处理函数

对于高斯泼溅数据,有专门的处理函数:

js
function finalizeSpzAttribute(attribute, vertexBufferLoader, loadBuffer, loadTypedArray) { // 解压SPZ格式数据 // SPZ是一种针对高斯泼溅优化的数据压缩格式 // 计算属性的最小/最大值 const findMinMaxXY = (flatArray) => { // 计算缩放或旋转属性的最小/最大值 // 用于优化渲染和剔除 }; if (attribute.semantic === VertexAttributeSemantic.SCALE) { // 处理缩放属性 findMinMaxXY(attribute.typedArray); } // 标记属性已完成处理 attribute.buffer = vertexBufferLoader.buffer; attribute.byteOffset = vertexBufferLoader.byteOffset; attribute.byteStride = vertexBufferLoader.byteStride; }

创建高斯泼溅纹理

在模型处理中专门为高斯泼溅生成纹理:

js
// 在模型更新过程中 function processModelPipelineStages(model, frameState) { // 检查是否有高斯泼溅图元 const nodes = model.sceneGraph.components.nodes; for (let i = 0; i < nodes.length; i++) { const primitives = nodes[i].primitives; for (let j = 0; j < primitives.length; j++) { const primitive = primitives[j]; // 如果是高斯泼溅图元且需要生成纹理 if (primitive.isGaussianSplatPrimitive && primitive.needsGaussianSplatTexture) { generateGaussianSplatTexture(primitive, frameState); } } } } // 生成高斯泼溅纹理 function generateGaussianSplatTexture(primitive, frameState) { // 标记纹理生成状态 primitive.gaussianSplatTexturePending = true; // 从顶点属性中提取数据 const positions = ModelUtility.getAttributeBySemantic( primitive, VertexAttributeSemantic.POSITION).typedArray; const scales = ModelUtility.getAttributeBySemantic( primitive, VertexAttributeSemantic.SCALE).typedArray; const rotations = ModelUtility.getAttributeBySemantic( primitive, VertexAttributeSemantic.ROTATION).typedArray; const colors = ModelUtility.getAttributeBySemantic( primitive, VertexAttributeSemantic.COLOR).typedArray; // 调用纹理生成器 const promise = GaussianSplatTextureGenerator.generateFromAttrs({ attributes: { positions: new Float32Array(positions), scales: new Float32Array(scales), rotations: new Float32Array(rotations), colors: new Uint8Array(colors), }, count: primitive.attributes[0].count, }); // 处理纹理生成结果 promise.then((splatTextureData) => { // 创建纹理对象 const splatTex = new Texture({ context: frameState.context, source: { width: splatTextureData.width, height: splatTextureData.height, arrayBufferView: splatTextureData.data, }, pixelFormat: PixelFormat.RGBA_INTEGER, pixelDatatype: PixelDatatype.UNSIGNED_INT, sampler: Sampler.NEAREST, }); // 创建索引属性 const count = primitive.attributes[0].count; const attribute = new ModelComponents.Attribute(); attribute.name = "_SPLAT_INDEXES"; attribute.typedArray = new Uint32Array([...Array(count).keys()]); attribute.componentDatatype = ComponentDatatype.UNSIGNED_INT; attribute.type = AttributeType.SCALAR; attribute.count = count; // 更新图元 primitive.attributes.push(attribute); primitive.gaussianSplatTexture = splatTex; primitive.hasGaussianSplatTexture = true; primitive.needsGaussianSplatTexture = false; primitive.gaussianSplatTexturePending = false; }); }

高斯泼溅深度排序

高斯泼溅需要特殊的深度排序算法来正确渲染半透明效果:

js
function updateGaussianSplatting(model, frameState) { // 找到高斯泼溅图元 let gaussianPrimitive; // ...查找代码 if (!defined(gaussianPrimitive) || !gaussianPrimitive.hasGaussianSplatTexture) { return; } // 计算模型视图矩阵 Matrix4.multiply( frameState.camera.viewMatrix, model.modelMatrix, scratchSplatMatrix ); // 获取位置和索引属性 const posAttr = ModelUtility.getAttributeBySemantic( gaussianPrimitive, VertexAttributeSemantic.POSITION ); const idxAttr = gaussianPrimitive.attributes.find(a => a.name === "_SPLAT_INDEXES"); // 根据视角排序高斯点 const promise = GaussianSplatSorter.radixSortIndexes({ primitive: { positions: new Float32Array(posAttr.typedArray), modelView: Float32Array.from(scratchSplatMatrix), count: idxAttr.count, }, sortType: "Index", }); // 处理排序结果 promise.then((sortedData) => { // 更新索引属性 idxAttr.typedArray = sortedData; // 重建渲染命令 model.resetDrawCommands(); }); }

高斯泼溅渲染着色器生成

最后,为高斯泼溅创建特殊的着色器程序:

在PrimitiveRenderResources处理过程中

js
function processGaussianSplatPrimitive(primitiveRenderResources, primitive, frameState) { const shaderBuilder = primitiveRenderResources.shaderBuilder; if (primitive.isGaussianSplatPrimitive) { // 添加高斯泼溅着色器代码 shaderBuilder.addDefine("HAS_GAUSSIAN_SPLATTING"); // 添加纹理采样器 shaderBuilder.addUniform("sampler2D", "u_gaussianSplatTexture"); primitiveRenderResources.uniformMap.u_gaussianSplatTexture = function() { return primitive.gaussianSplatTexture; }; // 添加顶点着色器代码 shaderBuilder.addVertexLines([ "attribute float a_splat_index;", "varying vec2 v_gaussian_uv;", "// 更多顶点着色器代码..." ]); // 添加片元着色器代码 shaderBuilder.addFragmentLines([ "uniform sampler2D u_gaussianSplatTexture;", "varying vec2 v_gaussian_uv;", "// 高斯泼溅渲染代码..." ]); // 禁用背面剔除 primitiveRenderResources.renderStateOptions.cull.enabled = false; // 设置混合模式 primitiveRenderResources.renderStateOptions.blending.enabled = true; // ...设置其他混合参数 } }

总结:GLTF高斯泼溅处理流程

1、扩展识别:

  • 解析GLTF时识别KHR_gaussian_splatting扩展
  • 设置标志表示模型包含高斯泼溅数据

2、特殊属性加载:

  • 加载高斯泼溅特有的属性:SCALE、ROTATION、OPACITY
  • 处理可能的SPZ压缩数据格式

3、图元标记:

  • 将包含高斯泼溅数据的图元标记为isGaussianSplatPrimitive
  • 设置点渲染模式

4、纹理生成:

  • 处理顶点属性数据
  • 生成专用的高斯泼溅纹理
  • 创建用于索引的附加属性

5、深度排序:

  • 计算模型视图矩阵
  • 使用特殊的基数排序算法
  • 更新索引数据

6、着色器生成:

  • 添加高斯泼溅特有的着色器代码
  • 设置纹理采样器和相关变量
  • 配置特殊的渲染状态(混合模式、背面剔除等)

7、渲染命令生成:

  • 创建适用于高斯泼溅的绘制命令
  • 确保正确的深度测试和混合设置
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:幽灵

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 幽灵AI 许可协议。转载请注明出处!