CommandBuffer为渲染命令缓冲区,我们将一些列渲染指令添加到CommandBuffer中,在需要执行时通过Camera或者Graphics类进行执行,进而实现对渲染流程的控制。同时可以实时生成我们需要的临时效果。本文完整代码在最后。
目前只介绍CommandBuffer最基本的几个方法。首先定义一个CommandBuffer的实例:
cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" };
示例代码如下:
    public void DrawRenderer()
    {
        cmdBuffer.Clear();
        cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
    }
入口参数cubeRenderer为一个立方体网格,cmdMat为一个unlit/texture的材质,相当于用cmdMat材质,对cubeRenderer的显示效果进行了重新生成。并将结果直接显示在屏幕上,位置为原cubeRenderer位置。
示例代码如下:
    public void DrawRendererToTarget()
    {
        cmdBuffer.Clear();
        cmdBuffer.SetRenderTarget(target);
        cmdBuffer.ClearRenderTarget(true, true, clearColor);
        cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
    }
此方法相当于在将2.1.1的计算结果绘制到一个RenderTexture类型的target上,将此Target可以赋值给其他对象上,如RawImage等。
此方法表示绘制一个Mesh
示例代码如下:
    public void DrawMesh()
    {
        cmdBuffer.Clear();
        cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
    }
表示将mesh根据cmdMat材质定义的效果绘制到屏幕上,如果不需要坐标变换则采用 Matrix4x4.identity矩阵。
示例代码:
    public void DrawMeshToTarget()
    {
        cmdBuffer.Clear();
        cmdBuffer.SetRenderTarget(target);
        cmdBuffer.ClearRenderTarget(true, true, clearColor);
        cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
    }
此方法相当于在将2.2.1的计算结果绘制到一个RenderTexture类型的target上,将此Target可以赋值给其他对象上,如RawImage等。
根据2.定义CommandBuffer指令,然后就可以进行调用了。调用时可以使用Camera也可以使用Graphics类,此文采用Camera来调用,Graphics类的调用后续会讲,稍微复杂一点。
        cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" };
        mainCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmdBuffer);
上述代码表示将此指令添加到Camera的执行序列中,即当渲染完不透明物体时执行此指令。此指令渲染的结果可能绘制到屏幕上,也可能绘制到一个RenderTexture上。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
public enum CameraCmdBuffer
{
        DRAW_RENDERER,
        DRAW_RENDERER_TARGET,
        DRAW_MESH,
        DRAW_MESH_TARGET
}
public class Graphics05CmdBufferCamera : MonoBehaviour
{
    public Camera mainCamera;
    public Material cmdMat;
    public Renderer cubeRenderer;
    public RenderTexture target;
    public Color clearColor = Color.red;
    public int triCount = 6;
    public float radius = 5;
    private CommandBuffer cmdBuffer;
    private Mesh mesh;
    public void DrawRenderer()
    {
        cmdBuffer.Clear();
        cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
    }
    public void DrawRendererToTarget()
    {
        cmdBuffer.Clear();
        cmdBuffer.SetRenderTarget(target);
        cmdBuffer.ClearRenderTarget(true, true, clearColor);
        cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
    }
    public void DrawMesh()
    {
        cmdBuffer.Clear();
        cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
    }
    public void DrawMeshToTarget()
    {
        cmdBuffer.Clear();
        cmdBuffer.SetRenderTarget(target);
        cmdBuffer.ClearRenderTarget(true, true, clearColor);
        cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
    }
    private void Start()
    {
        cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" };
        mainCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmdBuffer);
        if (mesh==null)
        {
            mesh = Graphics00Mesh.Instance.GetMesh(triCount, radius);
        }
    }
    private void OnValidate()
    {
        mesh = Graphics00Mesh.Instance.GetMesh(triCount, radius);
    }
    private void OnDisable()
    {
        mainCamera.RemoveAllCommandBuffers();
    }
}
```go
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Graphics00Mesh
{
    [Range(3, 100)]
    public int triCount = 6;
    public float radius = 5;
    public bool showHalf = false;
    private static Graphics00Mesh instance;
    public static Graphics00Mesh Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Graphics00Mesh();
            }
            return instance;
        }
    }
    public Mesh GetMesh(int triCount,float radius)
    {
        this.triCount = triCount;
        this.radius = radius;
        Mesh mesh = new Mesh();
        mesh.name = MeshName;
        mesh.vertices = Vertices;
        mesh.triangles = Triangles;
        mesh.uv = Uvs;
        return mesh;
    }
    protected string MeshName
    {
        get
        {
            return "Circle Mesh";
        }
    }
    protected Vector3[] Vertices
    {
        get
        {
            Vector3[] vertices = new Vector3[triCount + 1];
            vertices[0] = Vector3.zero;
            float angleDelta = 2 * Mathf.PI / triCount;
            for (int i = 0; i < triCount; i++)
            {
                float angle = angleDelta * i;
                float x = radius * Mathf.Cos(angle);
                float y = radius * Mathf.Sin(angle);
                vertices[i + 1] = new Vector3(x, y, 0);
            }
            return vertices;
        }
    }
    protected int[] Triangles
    {
        get
        {
            int[] triangles = new int[triCount * 3];
            for (int i = 0; i < triCount; i++)
            {
                if (showHalf)
                {
                    if (i % 2 == 0) continue;
                }
                triangles[i * 3] = 0;
                triangles[i * 3 + 2] = i + 1;
                if (i + 2 > triCount)
                {
                    triangles[i * 3 + 1] = 1;
                }
                else
                {
                    triangles[i * 3 + 1] = i + 2;
                }