一、命令缓冲区 CommandBuffer
根据渲染模式的不同,Unity的渲染流水线如下:
其中蓝色的部分就是 CommandBuffer 可插入的部分,CommandBuffer 本质上就是做一个插入操作,以实现在 Unity 的某个渲染步骤完成后,执行你的额外操作
其中:
- 可以通过 Camera.AddCommandBuffer 命令插入到 Camera Rendering 渲染队列,插入点为 CameraEvent enum. 枚举中的内容
- 可以通过 Light.AddCommandBuffer 命令插入到 Light Rendering 渲染队列,它的插入点枚举是 Rendering.LightEvent
一个例子:如果你想将在天空盒渲染完后插入你的操作,那么对应的代码就是
var cam = Camera.current;
buf = new CommandBuffer();
buf.name = "bufName123";
//……
cam.AddCommandBuffer(CameraEvent.AfterSkybox, buf);
不过需要注意的是:针对 GPU 的不同,CommandBuffer 能插入的生命周期可能会有略微不同,部分可能不支持
二、Unity 生命周期渲染部分

渲染相关的生命周期介绍:
- OnPreCull: 在相机剔除不可见对象前调用此函数
- OnBecameVisible/OnBecameInvisible: 当挂有渲染组件的对象于相机可见/不可见时调用此函数(例如进入/离开摄像机视野)
- OnWillRenderObject: 如果对象可见,在物体渲染之前会调用此函数
- OnPreRender: 在相机开始渲染场景之前调用此函数
- OnRenderObject: 在完成所有常规场景渲染后调用此函数,此时可使用 GL 类或 Graphics.DrawMeshNow 绘制自定义几何图形
- OnPostRender: 在相机完成场景渲染后调用此函数
- OnRenderImage:在相机完成渲染后调用此函数,可以在此修改摄影机的最终图像(后处理)
- OnGUI: 响应 GUI 事件,如果一帧有多个 GUI 事件就会响应多次
- OnDrawGizmos 用于在场景视图中绘制小图示(Gizmos)以实现可视化目的
为什么要讲这个,因为后面对于不同的效果实现,需要在正确的生命周期下完成 CommandBuffer 的相关操作
注意:部分生命周期需要专业版的 Unity 才提供
三、最简单的 CommandBuffer 例子
代码如下,其中 CommandBuffer 中使用的 Shader 输出纯绿色
- CommandBuffer.DrawRenderer:使用指定的材质,绘制目标对象
using UnityEngine;
using UnityEngine.Rendering;
[ExecuteInEditMode]
//加上ExecuteInEditMode后,下面的代码在编辑模式中就会运行,无需每次测试都要play了
public class GreenCube: MonoBehaviour
{
public Shader shader;
private Material material;
CommandBuffer buffer;
private void OnEnable()
{
buffer = new CommandBuffer();
material = new Material(shader);
//CommandBuffer.DrawRenderer:使用指定的材质,绘制目标对象
buffer.DrawRenderer(GetComponent<Renderer>(), material);
Camera.main.AddCommandBuffer(CameraEvent.AfterForwardOpaque, buffer);
}
public void OnDisable()
{
if (Camera.main)
Camera.main.RemoveCommandBuffer(CameraEvent.AfterForwardOpaque, buffer);
Object.DestroyImmediate(material);
}
}
这个脚本挂在你要渲染的 Cube 下,这个 Cube 就会额外执行你的渲染指令:
可以看到,Game视图中的正方体已经是绿的了
在 FrameDebug 中也可以看到:Cube 被渲染了两次,第二次就是 CommandBuffer 中我们自己的额外渲染命令
参考资料: