高级计算着色器
多数计算着色器只需计算着色器所述简化语法:在 WGSL 声明资源,引擎自动反射。
本页介绍仍完全受支持的手动绑定组控制。自行提供 computeBindGroupFormat 及可选的 computeUniformBufferFormats 描述资源,并在 WGSL 中写出 @group/@binding 索引。适用于:
- 精确控制绑定布局。
- 与固定绑定位置的引擎或应用缓冲区互操作。
- 混合显式绑定和反射资源。
备注
手动绑定组并未弃用。已有手写 computeBindGroupFormat 的着色器继续原样工作,可按需迁移,也可保持不变。
绑定组格式
computeBindGroupFormat 定义可用资源。提供它时,WGSL 中必须写出匹配的显式绑定索引。可以绑定多种资源:
const shader = new pc.Shader(device, {
name: 'MyComputeShader',
shaderLanguage: pc.SHADERLANGUAGE_WGSL,
cshader: shaderCode,
computeBindGroupFormat: new pc.BindGroupFormat(device, [
// Resource bindings go here
])
});
存储缓冲区
存储缓冲区允许读写大量数据:
// Read-write storage buffer
new pc.BindStorageBufferFormat('particles', pc.SHADERSTAGE_COMPUTE)
// Read-only storage buffer
new pc.BindStorageBufferFormat('spheres', pc.SHADERSTAGE_COMPUTE, true)
WGSL 中按如下方式访问:
@group(0) @binding(0) var<storage, read_write> particles: array<f32>;
@group(0) @binding(1) var<storage, read> spheres: array<vec4f>;
存储纹理
存储纹理允许直接写入纹理:
new pc.BindStorageTextureFormat('outTexture', pc.PIXELFORMAT_RGBA8, pc.TEXTUREDIMENSION_2D)
WGSL 中:
@group(0) @binding(0) var outputTexture: texture_storage_2d<rgba8unorm, write>;
// Writing to the texture
textureStore(outputTexture, vec2i(global_id.xy), color);
输入纹理
输入纹理提供只读纹理数据,最后一个参数控制是否包含采样器:
// Texture without sampler (for textureLoad)
new pc.BindTextureFormat('inputTexture', pc.SHADERSTAGE_COMPUTE, undefined, undefined, false)
// Texture with sampler (for textureSampleLevel)
new pc.BindTextureFormat('inputTexture', pc.SHADERSTAGE_COMPUTE, undefined, undefined, true)
包含采样器时,WGSL 名称为纹理名加 _sampler 后缀:
// Without sampler - use textureLoad for direct texel access
@group(0) @binding(0) var inputTexture: texture_2d<f32>;
let color = textureLoad(inputTexture, position, 0);
// With sampler - use textureSampleLevel for filtered sampling
@group(0) @binding(0) var inputTexture: texture_2d<f32>;
@group(0) @binding(1) var inputTexture_sampler: sampler;
let color = textureSampleLevel(inputTexture, inputTexture_sampler, uv, 0.0);
备注
计算着色器必须显式指定 mip 层级(LOD),因此使用 textureSampleLevel 而非 textureSample。
Uniform 缓冲区
传入 uniform 数据时,先定义缓冲区格式:
const uniformBufferFormat = new pc.UniformBufferFormat(device, [
new pc.UniformFormat('tint', pc.UNIFORMTYPE_VEC4),
new pc.UniformFormat('time', pc.UNIFORMTYPE_FLOAT),
new pc.UniformFormat('count', pc.UNIFORMTYPE_UINT)
]);
然后将其与绑定组一同放入着色器定义:
const shader = new pc.Shader(device, {
name: 'ComputeShader',
shaderLanguage: pc.SHADERLANGUAGE_WGSL,
cshader: shaderCode,
// Assign the uniform buffer format
computeUniformBufferFormats: {
ub: uniformBufferFormat
},
// Include uniform buffer in bind group
computeBindGroupFormat: new pc.BindGroupFormat(device, [
new pc.BindUniformBufferFormat('ub', pc.SHADERSTAGE_COMPUTE),
// ... other bindings
])
});
WGSL 中:
struct ub_compute {
tint: vec4f,
time: f32,
count: u32
}
@group(0) @binding(0) var<uniform> ubCompute: ub_compute;
@compute @workgroup_size(1, 1, 1)
fn main(@builtin(global_invocation_id) global_id: vec3u) {
let t = ubCompute.time;
let c = ubCompute.count;
}
混合反射与手动资源
调用者提供的 computeBindGroupFormat 可与简化反射语法共存:
computeBindGroupFormat描述的资源使用指定绑定,位于组 0。- 简化语法声明、未写
@group/@binding的资源仍自动反射,放入索引为 1 的独立绑定组。 - 显式写出
@group/@binding的 WGSL 声明保持不变。
如果不提供 computeBindGroupFormat,反射资源改放入组 0,参见计算着色器。
无论手动绑定还是反射,均通过 setParameter 按名称赋值。
示例
以下示例使用手写绑定组格式:
直方图
纹理生成
间接派发