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

原文地址:https://www.cnblogs.com/llstart-new0201/p/12315719.html