(五)CommandBuffer基本应用

1.前言

CommandBuffer为渲染命令缓冲区,我们将一些列渲染指令添加到CommandBuffer中,在需要执行时通过Camera或者Graphics类进行执行,进而实现对渲染流程的控制。同时可以实时生成我们需要的临时效果。本文完整代码在最后。

2.基本方法

目前只介绍CommandBuffer最基本的几个方法。首先定义一个CommandBuffer的实例:

cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" }; 

2.1 DrawRenderer

2.1.1 ToScreen

示例代码如下:

    public void DrawRenderer()
    {
        cmdBuffer.Clear(); cmdBuffer.DrawRenderer(cubeRenderer, cmdMat); } 

入口参数cubeRenderer为一个立方体网格,cmdMat为一个unlit/texture的材质,相当于用cmdMat材质,对cubeRenderer的显示效果进行了重新生成。并将结果直接显示在屏幕上,位置为原cubeRenderer位置。

2.1.2 ToTarget

示例代码如下:

    public void DrawRendererToTarget()
    {
        cmdBuffer.Clear(); cmdBuffer.SetRenderTarget(target); cmdBuffer.ClearRenderTarget(true, true, clearColor); cmdBuffer.DrawRenderer(cubeRenderer, cmdMat); } 

此方法相当于在将2.1.1的计算结果绘制到一个RenderTexture类型的target上,将此Target可以赋值给其他对象上,如RawImage等。

2.2 DrawMesh

此方法表示绘制一个Mesh

2.2.1 ToScreen

示例代码如下:

    public void DrawMesh()
    {
        cmdBuffer.Clear(); cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat); } 

表示将mesh根据cmdMat材质定义的效果绘制到屏幕上,如果不需要坐标变换则采用 Matrix4x4.identity矩阵。

2.2.2 ToTarget

示例代码:

    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等。

3.使用方法

根据2.定义CommandBuffer指令,然后就可以进行调用了。调用时可以使用Camera也可以使用Graphics类,此文采用Camera来调用,Graphics类的调用后续会讲,稍微复杂一点。

        cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" }; mainCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmdBuffer); 

上述代码表示将此指令添加到Camera的执行序列中,即当渲染完不透明物体时执行此指令。此指令渲染的结果可能绘制到屏幕上,也可能绘制到一个RenderTexture上。

4.完整代码

4.1 使用代码

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(); } } 

4.2 Mesh代码


```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; } } return triangles; } } protected Vector2[] Uvs { get { Vector2[] uvs = new Vector2[triCount + 1]; uvs[0] = new Vector2(0.5f, 0.5f); float angleDelta = 2 * Mathf.PI / triCount; for (int i = 0; i < triCount; i++) { float angle = angleDelta * i; float x = Mathf.Cos(angle) * 0.5f + 0.5f; float y = Mathf.Sin(angle) * 0.5f + 0.5f; uvs[i + 1] = new Vector2(x, y); } return uvs; } } } 
 

猜你喜欢

转载自www.cnblogs.com/llstart-new0201/p/12315715.html