shader基础入门(2)(VertexHelper)

VertexHelper(顶点帮助器/顶点辅助类/顶点助手)

官方资料版本:2019.1

使用需要继承:using UnityEngine.UI;

描述

可以帮助为 UI 生成网格的实用程序类。

此类实现 IDisposable 以帮助进行内存管理。

属性

currentIndexCount       VertexHelper获取的数量指标设置。

currentVertCount        当前的顶点缓冲。

公共方法

AddTriangle                添加一个三角形的缓冲区。

AddUIVertexQuad       在流中添加一个四边形。

AddUIVertexStream    添加自定义 UIVertex 流和相应的索引。

AddUIVertexTriangleStream        添加一个流的三角形列表。

AddVert                        添加一个顶点到流中。

Clear                            清除所有顶点的流。

Dispose                        清理分配的内存。

FillMesh                        填充给定的流数据网格。

GetUIVertexStream       从流中创建一个流的UI顶点(在三角形中)

PopulateUIVertex          用流的索引 i 中的数据填充 UIVertex。

SetUIVertex                   在给定的索引中设置一个UIVertex 

官方示例代码

using UnityEngine;
using UnityEngine.UI;

public class ExampleClass : MonoBehaviour
{
    Mesh m;

    void Start()
    {
        Color32 color32 = Color.red;
        using (var vh = new VertexHelper())
        {
            vh.AddVert(new Vector3(0, 0), color32, new Vector2(0f, 0f));
            vh.AddVert(new Vector3(0, 100), color32, new Vector2(0f, 1f));
            vh.AddVert(new Vector3(100, 100), color32, new Vector2(1f, 1f));
            vh.AddVert(new Vector3(100, 0), color32, new Vector2(1f, 0f));

            vh.AddTriangle(0, 1, 2);
            vh.AddTriangle(2, 3, 0);
            vh.FillMesh(m);
        }
    }
}

以上代码解析:

            vh.AddVert(new Vector3(0, 0), color32, new Vector2(0f, 0f));
            vh.AddVert(new Vector3(0, 100), color32, new Vector2(0f, 1f));
            vh.AddVert(new Vector3(100, 100), color32, new Vector2(1f, 1f));
            vh.AddVert(new Vector3(100, 0), color32, new Vector2(1f, 0f));

这里是生成4个网格点,(世界坐标点,颜色(一般为Color.white),uv坐标)

            vh.AddTriangle(0, 1, 2);
            vh.AddTriangle(2, 3, 0);

这里是根据上面添加好的点,以及uv的渲染面

这样一个平面就出来了 

如果想要显示出来还需要进一步添加代码

方向指引(没测试):大概是这些东西

         Mesh mesh = new Mesh();
        vh.FillMesh(mesh);
        GetComponent<MeshFilter>().mesh = mesh;

----------------------------------------------------------------------------

使用此函数绘制圆柱和圆锥?

先看圆柱:

 unity默认圆柱是由4个面组成的,其中侧面为两个面,这里展示绘制的是一个面

首先绘制顶

 在unity中认为圆的中心点为坐标(0,0),其中要在圆上取点绘制三角形,取点越多,我们绘制的三角形越圆,与球体概念一致

所以最小的圆是等边三角形

一般在进行绘制计算不会使用,这算极端数据

绘制也需要由三角形组成下图为单个三角形绘制,绘制出一个,然后分区域依次绘制,画出圆形,通过计算我们就能获得三角形三个顶点的坐标,然后通过AddVert绘制

 接着获取顶点坐标,绘制其他面

圆柱代码如下

 public int n = 16;
    public float r =3;

    // Start is called before the first frame update
    void Start()
    {
        Mesh mesh = new Mesh();
        VertexHelper vh= new VertexHelper();

        //每个角的弧度=圆的弧度/角的个数;
        float ang=(2*Mathf.PI)/n;

        //添加圆心
        vh.AddVert(new Vector3(0,1,0),Color.white,new Vector2(0.5f,0.5f));
        //循环计算其他顶点
        for (int i = 0; i < n; i++)
        {
            float x = Mathf.Sin(ang * i) * r;
            float y = Mathf.Cos(ang * i) * r;

            float uvx = (x + r) / (2 * r);
            float uvy = (y + r) / (2 * r);
            //正面
            vh.AddVert(new Vector3(x,1,y),Color.white,new Vector2(uvx,uvy));

        }

        //计算绘制(可以使用一个循环完成)
        for (int i = 0; i < n; i++)
        {
            if (i == 0)
            {
                vh.AddTriangle(0, n, 1);
            }
            else 
            {
                vh.AddTriangle(0, i, i+1);
            }
        }

        //第二个面(底盖)
        //圆心+圆的周围和已经用掉的顶点,不能重复使用
        int next = 1 + n;
        //添加圆心
        vh.AddVert(new Vector3(0,-1,0),Color.white,new Vector2(0.5f,0.5f));
        //循环计算其他顶点
        for (int i = 0; i < n; i++)
        {
            float x = Mathf.Sin(ang * i) * r;
            float y = Mathf.Cos(ang * i) * r;

            float uvx = (x + r) / (2 * r);
            float uvy = (y + r) / (2 * r);
            //反面
            vh.AddVert(new Vector3(x, -1, y), Color.white, new Vector2(uvx, uvy));
        }

        //计算绘制(因为底面故逆时针绘制)
        //所有下标+next保证不再重复使用
        for (int i = 0; i < n; i++)
        {
            if (i == 0)
            {
                vh.AddTriangle(0+next, 1 + next, n + next);
            }
            else
            {
                vh.AddTriangle(0 + next, i+1 + next, i + next);
            }
        }

        //第三个面(侧面)
        next = (1 + n) * 2;
        //循环计算其他顶点
        for (int i = 0; i < n+1; i++)
        {
            float x = Mathf.Sin(ang * i) * r;
            float y = Mathf.Cos(ang * i) * r;

            //int是整数,在进行除法计算只会返回0或者1
            float uvx = (float)i / (float)n;
            if (i==n) 
            {
                x = Mathf.Sin(ang * 0) * r;
                y = Mathf.Cos(ang * 0) * r;
            }

            //下面的顶点
            vh.AddVert(new Vector3(x,-1,y),Color.white,new Vector2(uvx,0));
            //上面顶点
            vh.AddVert(new Vector3(x, 1, y), Color.white, new Vector2(uvx, 1));

        }

        //多少面绘制多少次
        //所有下标+next保证使用不重复
        //圆是顺时针绘制,为了在外侧显示,故要逆时针绘制
        for (int i = 0; i < n; i++)
        {
            vh.AddTriangle(i*2+next,(i+1)*2+1+next,i*2+1+next);
            vh.AddTriangle(i*2+next,(i+1)*2+next,(i+1)*2+1+next);
        }



        //顶点助手数据赋值
        vh.FillMesh(mesh);

        //自动计算法线
        mesh.RecalculateBounds();

        //mesh赋值给过滤器
        GetComponent<MeshFilter>().mesh = mesh;


    }

-------------------------

在此基础代码上绘制圆锥

将顶改为1个点,让顶圆半径为0

 代码如下

 public int n = 16;
    public float r = 3;

    // Start is called before the first frame update
    void Start()
    {
        Mesh mesh = new Mesh();
        VertexHelper vh = new VertexHelper();

        //每个角的弧度=圆的弧度/角的个数;
        float ang = (2 * Mathf.PI) / n;

        //添加圆心
        vh.AddVert(new Vector3(0, 1, 0), Color.white, new Vector2(0.5f, 0.5f));
        //循环计算其他顶点
        for (int i = 0; i < n; i++)
        {
            //-----------这里顶的r都改为0了-------
            float x = Mathf.Sin(ang * i) * 0;
            float y = Mathf.Cos(ang * i) * 0;

            float uvx = (x) / (2 * 0);
            float uvy = (y) / (2 * 0);
            //正面
            vh.AddVert(new Vector3(x, 1, y), Color.white, new Vector2(uvx, uvy));

        }

        //计算绘制(可以使用一个循环完成)
        for (int i = 0; i < n; i++)
        {
            if (i == 0)
            {
                vh.AddTriangle(0, n, 1);
            }
            else
            {
                vh.AddTriangle(0, i, i + 1);
            }
        }

        //第二个面(底盖)
        //圆心+圆的周围和已经用掉的顶点,不能重复使用
        int next = 1 + n;
        //添加圆心
        vh.AddVert(new Vector3(0, -1, 0), Color.white, new Vector2(0.5f, 0.5f));
        //循环计算其他顶点
        for (int i = 0; i < n; i++)
        {
            float x = Mathf.Sin(ang * i) * r;
            float y = Mathf.Cos(ang * i) * r;

            float uvx = (x + r) / (2 * r);
            float uvy = (y + r) / (2 * r);
            //反面
            vh.AddVert(new Vector3(x, -1, y), Color.white, new Vector2(uvx, uvy));
        }

        //计算绘制(因为底面故逆时针绘制)
        //所有下标+next保证不再重复使用
        for (int i = 0; i < n; i++)
        {
            if (i == 0)
            {
                vh.AddTriangle(0 + next, 1 + next, n + next);
            }
            else
            {
                vh.AddTriangle(0 + next, i + 1 + next, i + next);
            }
        }

        //第三个面(侧面)
        next = (1 + n) * 2;
        //循环计算其他顶点
        for (int i = 0; i < n + 1; i++)
        {
            float x = Mathf.Sin(ang * i) * r;
            float y = Mathf.Cos(ang * i) * r;

            //int是整数,在进行除法计算只会返回0或者1
            float uvx = (float)i / (float)n;
            if (i == n)
            {
                x = Mathf.Sin(ang * 0) * r;
                y = Mathf.Cos(ang * 0) * r;
            }

            //下面的顶点
            vh.AddVert(new Vector3(x, -1, y), Color.white, new Vector2(uvx, 0));
            //上面顶点------这里改了一个参数,让它顶绘制连接到一个点形成一个圆锥形
            
            vh.AddVert(Vector3.up, Color.white, new Vector2(uvx, 1));

        }

        //多少面绘制多少次
        //所有下标+next保证使用不重复
        //圆是顺时针绘制,为了在外侧显示,故要逆时针绘制
        for (int i = 0; i < n; i++)
        {
            vh.AddTriangle(i * 2 + next, (i + 1) * 2 + 1 + next, i * 2 + 1 + next);
            vh.AddTriangle(i * 2 + next, (i + 1) * 2 + next, (i + 1) * 2 + 1 + next);
        }



        //顶点助手数据赋值
        vh.FillMesh(mesh);

        //自动计算法线
        mesh.RecalculateBounds();

        //mesh赋值给过滤器
        GetComponent<MeshFilter>().mesh = mesh;


    }

猜你喜欢

转载自blog.csdn.net/qq_46043095/article/details/128596802