跳到主要内容

间接绘制

间接绘制是一种 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 引擎类和方法:

实时示例​

Indirect Draw 示例完整演示了实例数量随动画变化的间接绘制。

间接绘制示例