shader基础入门(2)(VertexHelper)

14 篇文章 0 订阅
VertexHelper是一个Unity3D中的类,用于帮助生成UI元素的网格。它涉及到顶点、颜色和UV坐标的添加、三角形的定义以及网格的填充。通过示例代码展示了如何使用VertexHelper创建一个平面,并解释了如何扩展这个概念来绘制圆柱和圆锥。
摘要由CSDN通过智能技术生成

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;


    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

作孽就得先起床

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值