间接绘制
间接绘制是一种 GPU 驱动的渲染技术:绘制调用参数(例如顶点数、实例数等)存储在 GPU 缓冲区内存中,而不是由 CPU 直接指定。计算着色器因而可以动态生成或修改渲染参数,实现更高效的 GPU 驱动渲染工作流。
此功能目前仅 WebGPU 支持(可通过 GraphicsDevice.supportsIndirectDraw 检查),其他平台会忽略它,将网格实例按普通绘制调用渲染。
间接绘制的工作原理
传统渲染中,CPU 为每次绘制调用指定顶点数和实例数等参数。间接绘制将这些参数存入 GPU 缓冲区,由 GPU 在渲染时读取。因此可以实现:
- GPU 驱动剔除:计算着色器决定渲染哪些对象。
- 动态实例数量:程序化控制绘制多少个实例。
- 降低 CPU 开销:减少 CPU 与 GPU 同步。
- 复杂渲染效果:支持 GPU 驱动 LOD 选择等高级技术。
基本用法
配置间接绘制
间接绘制需要在间接绘制缓冲区中分配槽位,并将其赋给网格实例。注意:每帧都必须重新分配槽位。
// Get a fresh slot every frame
const indirectSlot = app.graphicsDevice.getIndirectDrawSlot();
// Configure the mesh instance to use indirect rendering
// First parameter: camera component (or null for all cameras)
// Second parameter: the allocated slot
meshInstance.setIndirect(null, indirectSlot);
配置缓冲区大小
控制每帧间接绘制调用的最大数量:
// Set maximum indirect draw calls per frame (default: 1024)
app.graphicsDevice.maxIndirectDrawCount = 2048;
理解间接绘制缓冲区
间接绘制缓冲区是保存绘制调用参数的存储缓冲区,由图形设备自动管理:
- 通过
app.graphicsDevice.indirectDrawBuffer访问。 - 大小由
maxIndirectDrawCount属性控制。 - 每个槽位包含
indexCount、instanceCount、firstIndex、baseVertex和firstInstance。
配合计算着色器
间接绘制与生成绘制参数的计算着色器结合时最强大。getIndirectMetaData() 方法返回计算着色器所需的关键网格信息:
// Get mesh metadata needed for indirect rendering
// Returns Int32Array [count, base, baseVertex, 0]
const meshMetaData = meshInstance.getIndirectMetaData();
// Create compute shader to control rendering parameters
const compute = new pc.Compute(device, shader, 'IndirectDrawCompute');
compute.setParameter('indirectMetaData', meshMetaData);
compute.setParameter('indirectDrawBuffer', app.graphicsDevice.indirectDrawBuffer);
compute.setParameter('indirectSlot', indirectSlot);
// Dispatch compute shader to generate draw parameters
device.computeDispatch([compute], 'GenerateIndirectDraw');
API 参考
详细 API 文档参见以下 PlayCanvas 引擎类和方法:
MeshInstance.setIndirect():将网格实例配置为间接渲染。GraphicsDevice.supportsIndirectDraw:检查设备是否支持间接绘制。GraphicsDevice.getIndirectDrawSlot():在间接绘制缓冲区中分配槽位。GraphicsDevice.indirectDrawBuffer:访问间接绘制缓冲区。GraphicsDevice.maxIndirectDrawCount:控制每帧间接绘制调用上限。
实时示例
Indirect Draw 示例完整演示了实例数量随动画变化的间接绘制。
间接绘制示例