高斯泼溅数据处理
GSplatProcessor 通过自定义着色器在 GPU 处理数据,从源纹理流读取并写入目标,支持绘画、选择、删除和变换。
备注
此功能基于渲染架构。
概览
位置、旋转、缩放和颜色保存在纹理流,可通过数据格式添加自定义流。
处理器允许:
- 用生成的加载函数读取源流。
- 用生成的写函数写入目标流。
- 在 GPU 并行处理全部单元。
适用于:
- 按笔刷位置绘画。
- 标记选择或删除。
- 变换数据。
- 自定义逐单元效果。
基本用法
1. 创建处理器
指定源、目标和逐单元处理代码:
const processor = new pc.GSplatProcessor(
app.graphicsDevice,
{ component: entity.gsplat }, // source
{ component: entity.gsplat, streams: ['customColor'] }, // destination
{
processGLSL: `
uniform vec4 uBrushSphere; // xyz = position, w = radius
uniform vec4 uBrushColor;
void process() {
vec3 center = getCenter();
float dist = distance(center, uBrushSphere.xyz);
if (dist < uBrushSphere.w) {
writeCustomColor(uBrushColor);
} else {
writeCustomColor(vec4(0.0));
}
}
`,
processWGSL: `
uniform uBrushSphere: vec4f;
uniform uBrushColor: vec4f;
fn process() {
let center = getCenter();
let dist = distance(center, uniform.uBrushSphere.xyz);
if (dist < uniform.uBrushSphere.w) {
writeCustomColor(uniform.uBrushColor);
} else {
writeCustomColor(vec4f(0.0));
}
}
`
}
);
2. 设置参数并执行
设置 uniform,再执行处理:
// Set uniforms for the processing shader
processor.setParameter('uBrushSphere', [x, y, z, radius]);
processor.setParameter('uBrushColor', [1, 0, 0, 1]);
// Execute the processing pass
processor.process();
构造函数
new pc.GSplatProcessor(device, source, destination, options)
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
device | GraphicsDevice | 图形设备 |
source | GSplatProcessorBinding | 源绑定 |
destination | GSplatProcessorBinding | 目标绑定 |
options.processGLSL | string | WebGL 必需的 GLSL |
options.processWGSL | string | WebGPU 必需的 WGSL |
GSplatProcessorBinding
{
resource?: GSplatResourceBase, // Direct resource reference
component?: GSplatComponent, // Component (resource resolved automatically)
streams?: string[] // Stream names to bind
}
使用实例流 GSPLAT_STREAM_INSTANCE 时,必须指定 component,访问对应纹理。
源未指定 streams 时,自动绑定格式流,提供 getCenter、getColor、getRotation、getScale。源目标不同资源时,可读取源全部流;同一资源时,正在写的流不可读。
目标必须提供 streams,指定写哪些流。
不同资源大小
源和目标可有不同单元数。process() 对每个目标单元执行一次,当前目标索引为 splat.index:
void process() {
uint destIndex = splat.index; // Current destination splat index
// Calculate which source splat to read from
uint sourceIndex = destIndex * 2; // Example: sample every other splat
setSplat(sourceIndex);
vec3 srcPos = getCenter();
// Write to destination
writePosition(vec4(srcPos, 1.0));
}
也可用 WithIndex 直接读取任意源单元,不改变当前上下文。
因此支持:
- 从大源复制到小目标,降采样。
- 根据采样源生成目标。
- 不同单元数之间映射。
着色器函数
内置 uniform
自动提供:
| Uniform | 类型 | 说明 |
|---|---|---|
srcNumSplats | uint | 源单元数 |
dstNumSplats | uint | 目标单元数 |
splat.index >= dstNumSplats 的填充像素自动跳过。
读取源
未指定源流时提供:
| 函数 | 返回 | 说明 |
|---|---|---|
getCenter() | vec3 | 位置,必须先调用 |
getColor() | vec4 | 颜色 |
getRotation() | vec4 | 四元数 |
getScale() | vec3 | 缩放 |
读取其他索引
默认读自身,通过 setSplat(index) 切换:
// GLSL - Read from neighbor splat
setSplat(neighborIndex);
vec3 neighborPos = getCenter();
vec4 neighborColor = getColor();
各加载函数也有 WithIndex 直接访问变体:
// GLSL - Read specific stream from another index
vec4 otherCenter = loadDataCenterWithIndex(neighborIndex);
适合比较或合并多个单元的算法。
写入目标
每目标流生成 write{StreamName}(value)。
例如 customColor 生成 writeCustomColor(vec4 value)。
API
setParameter(name, value)
设置 uniform。
// Scalar
processor.setParameter('uRadius', 0.5);
// Vector (as array)
processor.setParameter('uBrushPos', [x, y, z]);
// Texture
processor.setParameter('uBrushTex', brushTexture);
getParameter(name)
读取已设参数。
deleteParameter(name)
删除参数。
process()
执行通道,读源写目标。
destroy()
释放全部 GPU 资源,使用结束时调用。
blendState
设置混合状态,适合叠加绘画等累积效果:
processor.blendState = pc.BlendState.ADDBLEND;
用途
绘画
为笔刷半径内单元上色:
void process() {
vec3 center = getCenter();
float dist = distance(center, uBrushPos.xyz);
if (dist < uBrushRadius) {
float falloff = 1.0 - (dist / uBrushRadius);
writeCustomColor(uBrushColor * falloff);
} else {
writeCustomColor(vec4(0.0));
}
}
选择
选择 AABB 内单元:
void process() {
vec3 center = getCenter();
bool inside = all(greaterThan(center, uSelectionMin)) &&
all(lessThan(center, uSelectionMax));
writeSelection(inside ? vec4(1.0) : vec4(0.0));
}
删除与可见性
标为不可见:
void process() {
vec3 center = getCenter();
float visible = distance(center, uDeletePos) > uDeleteRadius ? 1.0 : 0.0;
writeVisible(vec4(visible));
}
实时示例
- Paint:笔刷绘画。
绘画示例
- Editor:选择、删除和克隆。
编辑器示例