GltfLoader.js 中解析扩展的部分
jsfunction parse(loader, frameState) {
const gltf = loader.gltf;
const extensions = gltf.extensions;
// 检查是否存在高斯泼溅扩展
if (defined(extensions) && defined(extensions.KHR_gaussian_splatting)) {
loader._hasGaussianSplatting = true;
}
// 继续解析其他数据...
}
在加载图元顶点属性时,专门检测和处理高斯泼溅所需的特殊属性:
在loadVertexAttribute函数中
jsfunction 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函数中
jsfunction 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;
}
对于高斯泼溅数据,有专门的处理函数:
jsfunction 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;
});
}
高斯泼溅需要特殊的深度排序算法来正确渲染半透明效果:
jsfunction 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处理过程中
jsfunction 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;
// ...设置其他混合参数
}
}
1、扩展识别:
解析GLTF时识别KHR_gaussian_splatting扩展
设置标志表示模型包含高斯泼溅数据
2、特殊属性加载:
加载高斯泼溅特有的属性:SCALE、ROTATION、OPACITY
处理可能的SPZ压缩数据格式
3、图元标记:
将包含高斯泼溅数据的图元标记为isGaussianSplatPrimitive
设置点渲染模式
4、纹理生成:
处理顶点属性数据
生成专用的高斯泼溅纹理
创建用于索引的附加属性
5、深度排序:
计算模型视图矩阵
使用特殊的基数排序算法
更新索引数据
6、着色器生成:
添加高斯泼溅特有的着色器代码
设置纹理采样器和相关变量
配置特殊的渲染状态(混合模式、背面剔除等)
7、渲染命令生成:
创建适用于高斯泼溅的绘制命令
确保正确的深度测试和混合设置
本文作者:幽灵
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 幽灵AI 许可协议。转载请注明出处!