• (五)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;
            }
        }
    }
    
    
     
  • 相关阅读:
    合肥程序员欢迎进QQ群49313181同城程序员职业交流群
    新一代程序员的思考
    ThinkPHP开发系列一框架搭建
    ASP.NET MVC4+EF系列之五 架构介绍
    ASP.NET MVC4+EF系列之阶段源码一
    gcc g++ Linux下动态库_静态库 指定路径问题
    [转]accept() 产生的Socekt端口是多少?
    阿里云计算资深总监唐洪:飞天大规模分布式计算系统解析
    [转] C++中##(两个井号)和#(一个井号)用法
    deep learning 深度学习
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/12630384.html
Copyright © 2020-2023  润新知