• (七)Graphics DrawMesh


    1.前言

    本文承接上一节,主要讲一下如何用graphics绘制一个Mesh以及将绘制结果绘制到一个RenderTexture上。代码在文末。

    2.Graphics DrawMesh

    代码中所用材质shader为Unlit/Texture。

    2.1 ToScreen

    以下为绘制到屏幕上的示例代码:

        private void DrawToScreen()
        {
            drawBuffer.Clear();
            drawBuffer.ClearRenderTarget(true, true, clearColor);
            Graphics.ExecuteCommandBuffer(drawBuffer);
    
            drawBuffer.DrawMesh(Graphics00Mesh.Instance.GetMesh(triCount, radius), Matrix4x4.identity, mat);
            Graphics.ExecuteCommandBuffer(drawBuffer);
        }
    

    此时方法只能在OnPostRender中调用,所以网格顶点数据即为实际数据。在OnpostRender中调用时,相当于在借助Camera在渲染流程中进行渲染Mesh,所以坐标点就是真是位置。如果看不到效果,可能是因为绘制的Mesh不在Camera的视锥体内,尝试调节mesh的位置,可以找到。此方法与这一篇方法类似。

    2.2 ToTarget

    此节将Mesh绘制到一个RenderTexture上。示例代码如下:

        private void DrawToTarget()
        {
            GL.PushMatrix();
            Graphics.SetRenderTarget(target);
            GL.LoadPixelMatrix(0, target.width, 0, target.height);
    
            drawBuffer.Clear();
            drawBuffer.ClearRenderTarget(true, true, clearColor);
            Graphics.ExecuteCommandBuffer(drawBuffer);
    
            drawBuffer.DrawMesh(Graphics00Mesh.Instance.GetMesh(triCount, radius), Matrix4x4.identity, mat);
            Graphics.ExecuteCommandBuffer(drawBuffer);
            
            GL.PopMatrix();
        }
    

    此方法可以在update中使用。

    2.2.1 注意事项一

    由于此方法是直接绘制到二维RenderTexture上,所以要进行坐标变换,且要先设置Target后LoadPixelMatrix。

    2.2.2 注意事项二

    由于坐标要转换到像素坐标,所以mesh顶点只显示大于0的部分,本例中Mesh的中心是(0,0,0),所以会只显示四分之一,跟这一篇2.3节一样。
    而且如果Mesh的顶点数据过小,可能看不到。以本例圆形mesh为例,如果半径为1,那么在屏幕上只有一个像素大小,所以是看不到的,此时可以设置为100或者更大。

    3.完整代码

    3.1 Mesh代码

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

    3.2 示例代码

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Rendering;
    
    public class Graphics07DrawMeshToTarget : MonoBehaviour
    {
        public DrawLocation location = DrawLocation.ONGUI;
        public bool toTarget = false;
        public Color clearColor = Color.blue;
        public Material mat;
        public RenderTexture target;
        public int triCount = 10;
        public float radius = 20;
    
        CommandBuffer drawBuffer;
    
        void Draw()
        {
            if (toTarget)
            {
                DrawToTarget();
            }
            else
            {
                DrawToScreen();
            }
        }
    
        private void DrawToScreen()
        {
            drawBuffer.Clear();
            drawBuffer.ClearRenderTarget(true, true, clearColor);
            Graphics.ExecuteCommandBuffer(drawBuffer);
    
            drawBuffer.DrawMesh(Graphics00Mesh.Instance.GetMesh(triCount, radius), Matrix4x4.identity, mat);
            Graphics.ExecuteCommandBuffer(drawBuffer);
        }
    
        private void DrawToTarget()
        {
            GL.PushMatrix();
            Graphics.SetRenderTarget(target);
            GL.LoadPixelMatrix(0, target.width, 0, target.height);
    
            drawBuffer.Clear();
            drawBuffer.ClearRenderTarget(true, true, clearColor);
            Graphics.ExecuteCommandBuffer(drawBuffer);
    
            drawBuffer.DrawMesh(Graphics00Mesh.Instance.GetMesh(triCount, radius), Matrix4x4.identity, mat);
            Graphics.ExecuteCommandBuffer(drawBuffer);
            
            GL.PopMatrix();
        }
    
        private void Start()
        {
            drawBuffer = new CommandBuffer() { name = "DrawMesh buffer" };
        }
    
        private void OnGUI()
        {
            if (location != DrawLocation.ONGUI) return;
    
            if (Event.current.type.Equals(EventType.Repaint))
            {
                Draw();
            }
        }
    
        private void Update()
        {
            if (location != DrawLocation.UPDATE) return;
    
            Draw();
        }
    
        private void OnPostRender()
        {
            if (location != DrawLocation.POSTRENDER) return;
    
            Draw();
        }
    }
    
    
  • 相关阅读:
    python 模块基础介绍
    python 函数基础介绍
    性能测试总结与分享材料
    徒手撸一个简单的RPC框架
    【springcloud】一文带你搞懂API网关
    一次非常有意思的sql优化经历
    MySQL数据库之互联网常用分库分表方案
    后端开发应该掌握的Redis基础
    权限管理模块设计
    基于redis的分布式锁的分析与实践
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/12315719.html
Copyright © 2020-2023  润新知