跳到主要内容

工作缓冲区格式

工作缓冲区格式定义可用数据流及资源复制方式。可定制复制操作,变换单元并写入额外逐组件数据。

备注

此功能基于渲染架构。

管线概览​

数据从资源通过复制进入工作缓冲区:

复制逐组件执行,可通过 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 的单元上色:

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
}
entity.gsplat.setWorkBufferModifier({ glsl: glslModifier, wgsl: wgslModifier });

盲数据来自资源,不属于工作缓冲区。要在绘制阶段使用,复制时需写入额外流。

Blind Data 示例读取 logo 标志以让标志发亮,并用 edge 距离驱动其他区域色相波。View 可显示字段本身。

盲数据示例

实时示例​

LOD Instances 演示:

LOD 实例示例
  • 添加 splatId 流。
  • 复制时写组件 ID。
  • 通过 setParameter 传值。

另请参见​