工作缓冲区格式
工作缓冲区格式定义可用数据流及资源复制方式。可定制复制操作,变换单元并写入额外逐组件数据。
此功能基于渲染架构。
管线概览
数据从资源通过复制进入工作缓冲区:
复制逐组件执行,可通过 setWorkBufferModifier() 分别定制。
定制复制
在各 gsplat 组件调用 setWorkBufferModifier(),指定复制方式。
修改函数
修改代码必须实现三个函数:
| 函数 | 用途 |
|---|---|
modifySplatCenter(inout vec3 center) | 修改位置 |
modifySplatRotationScale(vec3 originalCenter, vec3 modifiedCenter, inout vec4 rotation, inout vec3 scale) | 修改旋转和缩放 |
modifySplatColor(vec3 center, inout vec4 color) | 修改颜色并写额外流 |
modifySplatCenter 始终先执行,可采样额外流、保存共享全局变量,或执行三个函数共用的工作。
基本示例
entity.gsplat.setWorkBufferModifier({
glsl: `
void modifySplatCenter(inout vec3 center) {
// Offset all splats upward
center.y += 1.0;
}
void modifySplatRotationScale(vec3 originalCenter, vec3 modifiedCenter,
inout vec4 rotation, inout vec3 scale) {}
void modifySplatColor(vec3 center, inout vec4 color) {
// Tint splats red
color.rgb *= vec3(1.0, 0.5, 0.5);
}
`,
wgsl: `
fn modifySplatCenter(center: ptr<function, vec3f>) {
(*center).y += 1.0;
}
fn modifySplatRotationScale(originalCenter: vec3f, modifiedCenter: vec3f,
rotation: ptr<function, vec4f>, scale: ptr<function, vec3f>) {}
fn modifySplatColor(center: vec3f, color: ptr<function, vec4f>) {
*color = vec4f((*color).rgb * vec3f(1.0, 0.5, 0.5), (*color).a);
}
`
});
添加额外流
默认有位置、颜色、旋转和缩放,可额外保存自定义逐单元数据:
// Add a stream to store component IDs (R32U = unsigned int)
app.scene.gsplat.format.addExtraStreams([
{ name: 'splatId', format: pc.PIXELFORMAT_R32U }
]);
常用格式:
- PIXELFORMAT_R32U:单个无符号整数,例如组件 ID。
- PIXELFORMAT_RGBA8:四字节,例如打包数据。
- PIXELFORMAT_RGBA16F:四半浮点,例如自定义属性。
- PIXELFORMAT_RGBA32F:四浮点,例如高精度数据。
添加后不可移除,工作格式忽略 GSPLAT_STREAM_INSTANCE 存储选项。
写额外流
各流生成 write{StreamName}(),例如 splatId 生成 writeSplatId()。
每个 setWorkBufferModifier 都必须写入格式中的全部额外流。所有组件共享格式,因此修改器必须一致。
entity.gsplat.setWorkBufferModifier({
glsl: `
uniform uint uComponentId;
void modifySplatCenter(inout vec3 center) {}
void modifySplatRotationScale(vec3 originalCenter, vec3 modifiedCenter,
inout vec4 rotation, inout vec3 scale) {}
void modifySplatColor(vec3 center, inout vec4 color) {
// Write component ID to the splatId stream
writeSplatId(uvec4(uComponentId, 0u, 0u, 0u));
}
`,
wgsl: `
uniform uComponentId: u32;
fn modifySplatCenter(center: ptr<function, vec3f>) {}
fn modifySplatRotationScale(originalCenter: vec3f, modifiedCenter: vec3f,
rotation: ptr<function, vec4f>, scale: ptr<function, vec3f>) {}
fn modifySplatColor(center: vec3f, color: ptr<function, vec4f>) {
writeSplatId(vec4u(uniform.uComponentId, 0u, 0u, 0u));
}
`
});
传入 uniform
组件通过 setParameter、getParameter、deleteParameter 管理值:
// Set a uniform
entity.gsplat.setParameter('uComponentId', componentIndex);
// Get a uniform value
const id = entity.gsplat.getParameter('uComponentId');
// Delete a uniform
entity.gsplat.deleteParameter('uComponentId');
支持:
- int、float、uint 数值。
- vec2、vec3、vec4、mat4 等数组。
- Texture。
- StorageBuffer。
读取源数据
复制修改器可通过数据格式生成的函数读取原数据,例如默认格式:
- loadDataColor() 返回 vec4 颜色。
- loadDataCenter() 返回 xyz 位置与 w 额外值。
- loadDataScale() 返回 vec4 缩放。
- loadDataRotation() 返回 vec4 四元数。
读取其他索引
各函数有 WithIndex 变体:
// GLSL - Read neighbor splat data
vec4 neighborCenter = loadDataCenterWithIndex(neighborIndex);
读取同一其他索引多个属性时,setSplat() 更改当前索引:
// GLSL - Read multiple attributes from another splat
setSplat(otherIndex);
vec3 otherPos = getCenter();
vec4 otherColor = getColor();
详见数据格式:着色器访问。
读取 SOG 盲数据
SOG v3 可包含盲数据,即由应用定义含义的逐单元字段。组件复制修改器可通过以下接口读取:
getBlind_<name>():返回当前字段。u8 到 u32 返回 uint,WGSL 为 u32;f16、f32、unorm8、unorm16 返回 float,WGSL 为 f32。SOG_BLIND_<name>:资源含字段时定义,让同一修改器兼容有无该字段的资源。
name 将非字母、数字、下划线字符替换为下划线,合并连续并去掉首尾。part-id 对应 getBlind_part_id()。
以下修改器为 logo 等于 1 的单元上色:
- GLSL
- WGSL
void modifySplatCenter(inout vec3 center) {}
void modifySplatRotationScale(vec3 originalCenter, vec3 modifiedCenter, inout vec4 rotation, inout vec3 scale) {}
void modifySplatColor(vec3 center, inout vec4 color) {
#ifdef SOG_BLIND_logo
if (getBlind_logo() == 1u) {
color.rgb = vec3(1.0, 0.65, 0.15);
}
#endif
}
fn modifySplatCenter(center: ptr<function, vec3f>) {}
fn modifySplatRotationScale(originalCenter: vec3f, modifiedCenter: vec3f, rotation: ptr<function, vec4f>, scale: ptr<function, vec3f>) {}
fn modifySplatColor(center: vec3f, color: ptr<function, vec4f>) {
#ifdef SOG_BLIND_logo
if (getBlind_logo() == 1u) {
*color = vec4f(1.0, 0.65, 0.15, (*color).a);
}
#endif
}
entity.gsplat.setWorkBufferModifier({ glsl: glslModifier, wgsl: wgslModifier });
盲数据来自资源,不属于工作缓冲区。要在绘制阶段使用,复制时需写入额外流。
Blind Data 示例读取 logo 标志以让标志发亮,并用 edge 距离驱动其他区域色相波。View 可显示字段本身。
实时示例
LOD Instances 演示:
- 添加 splatId 流。
- 复制时写组件 ID。
- 通过 setParameter 传值。