(二)Graphics DrawMesh

1 Introduction

This article continues the previous section , mainly talking about how to draw a Mesh with graphics and draw the drawing result on a RenderTexture. The code is at the end of the text.

2. Graphics DrawMesh

The material shader used in the code is Unlit/Texture.

2.1 ToScreen

The following is sample code to draw to the screen:

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

At this time, the method can only be called in OnPostRender, so the grid vertex data is the actual data. When called in OnpostRender, it is equivalent to rendering Mesh in the rendering process with the help of Camera, so the coordinate point is the real position. If you can't see the effect, it may be because the drawn Mesh is not in the camera's frustum, try to adjust the position of the mesh, you can find it. This method is similar to this one .

2.2 ToTarget

This section draws the Mesh onto a RenderTexture. The sample code is as follows:

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

This method can be used in update.

2.2.1 Note 1

Since this method is directly drawn to the two-dimensional RenderTexture, coordinate transformation is required, and the Target must be set before LoadPixelMatrix.

2.2.2 Note 2

Since the coordinates are converted to pixel coordinates, only the part greater than 0 is displayed at the vertices of the mesh. In this example, the center of the Mesh is (0, 0, 0), so only a quarter will be displayed, just like Section 2.3 of this article .
And if the vertex data of the Mesh is too small, it may not be visible. Take the circular mesh in this example as an example. If the radius is 1, it will only be one pixel in size on the screen, so it cannot be seen. At this time, it can be set to 100 or larger.

3. Complete code

3.1 Mesh code

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 Sample code

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

Guess you like

Origin blog.csdn.net/ttod/article/details/130300191