Unity中UGUI的 OnPopulateMesh函数与VertexHelper类

news2024/7/6 18:32:13

Graphics类

当一个UGUI的UI元素生成顶点数据时会调用Graphics类中的 OnPopulateMesh(VertexHelper vh函数,我们可以在这个函数中修改顶点的数据或者获取顶点的数据。

UGUI中与显示相关的控件,例如Image、Text、RawImage等都继承自MaskableGraphic类,MaskableGraphic类继承自Graphic类

控件在画面中的形状、颜色、法线等信息都是由Graphics类中的OnPopulateMesh函数所控制
每当改变了顶点或者纹理后,会调用OnPopulateMesh函数
其中需要的输入参数VertexHelper是一个顶点辅助类,保存着生成Mesh的基本信息


绘制UGUI还可以通过Mesh,但一般不怎么使用
就跟一个3D物体能显示出来因为它的MeshRender和MeshFilter,2D Sprite能显示出来因为它的SpriteRender,UGUI元素也是一样,每个UI元素都有一个CanvasRender组件

    CanvasRenderer render;
    Vector3[] vertices;
    int[] triangles;
 
    void Update()
    {
        Mesh mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
 
        render = GetComponent<CanvasRenderer>();
        render.SetMesh(mesh);
    }

鼠标画线功能

 使用UGUI中的重写了 OnPopulateMesh( VertexHelper vh )  这个方法,然后用来绘制,改一下,可以用来实现鼠标画线的功能。详细参考:

Unity 画线OnPopulateMesh函数VertexHelper_Peter_Gao_的博客-CSDN博客


 

 VertexHelper的类结构

OnPopulateMesh( VertexHelper vh ) 函数中 UI元素的顶点数据会填充这个参数 VertexHelper数据结构,我们可以修改这个数据结构里面的数据从而影响到顶点的一些属性。VertexHelper类的属性和方法:

在这里插入图片描述

VertexHelper类的绘制基本图形方法


AddVert:添加顶点(第一个添加的顶点索引为0,第二个添加的顶点为1,依次.....)
AddTriangle:绘制三角形(GPU绘制时会按照输入的顶点下标的顺序绘制一个三角形)
currentIndexCount:VertexHelper结构中有几个顶点索引(重合的顶点被计为2个顶点,例如一个三角形最少有3个顶点,一个正方形最少有6个顶点)
currentVertCount:VertexHelper结构中有几个顶点(AddVert添加了几个顶点就有几个)
PopulateUIVertex:获取某个索引的顶点数据
SetUIVertex:设置某个索引的顶点数据
AddUIVertexQuad:把AddVert和AddTriangle封装到一个函数中
AddUIVertexStream:把AddVert和AddTriangle封装到一个函数中

绘制三角形

我们用AddVert和AddTriangle绘制一个三角形
在这里插入图片描述
我们创建一个脚本TestVertexHelper.cs并继承Graphic,因为OnPopulateMesh函数定义在Graphic中

using UnityEngine.UI;
using UnityEngine;
 
public class Test : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        base.OnPopulateMesh(vh);
 
        vh.Clear();
        vh.AddVert(new Vector3(0, 0), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.black, Vector2.zero);
 
        vh.AddTriangle(0, 1, 2);
    }
}

首先我们用AddVert添加了三个顶点,三个顶点的关系如上图,然后用AddTriangle添加三角形,参数是三角形顶点的索引。GPU在绘制的时候会按照顶点0->顶点1->顶点2来绘制一个三角形

绘制正方形

我们用AddVert和AddTriangle绘制一个正方形

在这里插入图片描述

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加四个顶点
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        //添加两个三角形
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
    }
}

我们首先用AddVert添加了四个顶点,顶点的顺序如图;然后用AddTriangle添加了两个三角形,其中vh.AddTriangle(0, 1, 2)表示用顶点0,1,2来绘制一个三角形,vh.AddTriangle(2, 3, 0)表示用顶点2,3,0来绘制一个三角形。
属性currentIndexCount 和currentVertCount

currentVertCount表示VertexHelper结构中有几个顶点

currentIndexCount表示VertexHelper结构中有几个顶点索引

我们来打印一下刚才绘制的正方形的信息

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加四个顶点
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        //添加两个三角形
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
 
        Debug.Log("currentIndexCount " + vh.currentIndexCount);
        Debug.Log("currentVertCount " + vh.currentVertCount);
    }
}

在这里插入图片描述

我们看到顶点索引有四个,顶点有六个

顶点索引有四个(0,1,2,3)这个好理解,但是我们用AddVert添加了四个顶点,这里怎么显示有六个呢?因为unity会把三角形交界处的顶点分成两个。即三角形(0,1,2)和三角形(2,3,0)重合的顶点0,2会被分成两个顶点来处理。

其它函数

PopulateUIVertex函数

返回指定索引的顶点数据,返回的顶点数据会填充UIVertex数据结构

例子:

我们使用PopulateUIVertex函数获取索引为2的顶点数据,然后打印出来

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加四个顶点
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        //添加两个三角形
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
 
        UIVertex vertex = new UIVertex();
        vh.PopulateUIVertex(ref vertex, 2);
        Debug.Log("color " + vertex.color + " position " + vertex.position + " uv0 " + vertex.uv0);
    }
}

在这里插入图片描述

我们看到这个数据,和我们设置的第三个顶点的数据是一样的

SetUIVertex函数

设置一个顶点的数据

我们上面把第三个顶点的颜色设置为了黑色(vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero)?,我们通过SetUIVertex函数把第三个顶点(索引为2的顶点,索引从0开始)的三色设置为黄色

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加四个顶点
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        vh.AddVert(new Vector3(100, 0), Color.blue, Vector2.zero);
        //添加两个三角形
        vh.AddTriangle(0, 1, 2);
        vh.AddTriangle(2, 3, 0);
 
        //得到第三个顶点(顶点索引为2,从0开始)的颜色
        UIVertex vertex = new UIVertex();
        vh.PopulateUIVertex(ref vertex, 2);
        //设置颜色为黄色
        vertex.color = Color.yellow;
        vh.SetUIVertex(vertex, 2);
    }
}

在这里插入图片描述
我们看到索引为2的顶点变成了黄色

AddUIVertexQuad(UIVertex[] verts)函数

增加一个长方形

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        UIVertex[] verts = new UIVertex[4];
        verts[0].position = new Vector3(0, 0);
        verts[0].color = Color.red;
        verts[0].uv0 = Vector2.zero;
 
        verts[1].position = new Vector3(0, 100);
        verts[1].color = Color.green;
        verts[1].uv0 = Vector2.zero;
 
        verts[2].position = new Vector3(100, 100);
        verts[2].color = Color.black;
        verts[2].uv0 = Vector2.zero;
 
        verts[3].position = new Vector3(100, 0);
        verts[3].color = Color.blue;
        verts[3].uv0 = Vector2.zero;
 
        vh.AddUIVertexQuad(verts);
    }
}

在这里插入图片描述

我们看到这个方法和绘制两个三角形产生的效果是一样的

public void AddUIVertexStream(List verts, List indices);

这个方法向VertexHelper中批量增加顶点数据,第一个参数为顶点数据,第二个参数为构成图元的顶点索引目录

假如我们要绘制两个三角形,加入我们有两个三角形,顶点索引分别为(0,1,2),(2,3,0),那么我们的indices应该定义为

List indices = new List() { 0, 1, 2, 2, 3, 0 };

public class TestVertexHelper : Graphic
{
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear();
List verts = new List();

    UIVertex vert0 = new UIVertex();
    vert0.position = new Vector3(0, 0);
    vert0.color = Color.red;
    vert0.uv0 = Vector2.zero;
    verts.Add(vert0);

    UIVertex vert1 = new UIVertex();
    vert1.position = new Vector3(0, 100);
    vert1.color = Color.green;
    vert1.uv0 = Vector2.zero;
    verts.Add(vert1);

    UIVertex vert2 = new UIVertex();
    vert2.position = new Vector3(100, 100);
    vert2.color = Color.black;
    vert2.uv0 = Vector2.zero;
    verts.Add(vert2);

    UIVertex vert3 = new UIVertex();
    vert3.position = new Vector3(100, 0);
    vert3.color = Color.blue;
    vert3.uv0 = Vector2.zero;
    verts.Add(vert3);

    List<int> indices = new List<int>() { 0, 1, 2, 2, 3, 0 };
    vh.AddUIVertexStream(verts, indices);
}

效果:

在这里插入图片描述

void AddUIVertexTriangleStream(List verts)函数

这个方法向VertexHelper中批量增加三角形顶点数据,参数的长度必须是三的倍数

public class TestVertexHelper : Graphic
{
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        List<UIVertex> verts = new List<UIVertex>();
 
        UIVertex vert0 = new UIVertex();
        vert0.position = new Vector3(0, 0);
        vert0.color = Color.red;
        vert0.uv0 = Vector2.zero;
        verts.Add(vert0);
 
        UIVertex vert1 = new UIVertex();
        vert1.position = new Vector3(0, 100);
        vert1.color = Color.green;
        vert1.uv0 = Vector2.zero;
        verts.Add(vert1);
 
        UIVertex vert2 = new UIVertex();
        vert2.position = new Vector3(100, 100);
        vert2.color = Color.black;
        vert2.uv0 = Vector2.zero;
        verts.Add(vert2);
 
        vh.AddUIVertexTriangleStream(verts);
    }
}

在这里插入图片描述

GetUIVertexStream(List stream)函数

获取当前VertexHelper中的所有顶点的信息

public class TestVertexHelper : Graphic
{
 
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //添加三个顶点
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.green, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.black, Vector2.zero);
        //添加三角形
        vh.AddTriangle(0, 1, 2);
        //得到所有顶点的信息
        List<UIVertex> stream = new List<UIVertex>();
        vh.GetUIVertexStream(stream);
        foreach (UIVertex v in stream) {
            Debug.Log("color " + v.color + " position " + v.position + " uv0 " + v.uv0);
        }
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/826051.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

正则替换windows文件名禁用的特殊字符

背景&#xff1a; windows文件名中不能出现以下提示的特殊字符&#xff0c;因此需要提前替换处理。 解决&#xff1a; // 替换\/:*?"<>|为空 fileName.replaceAll("[\\\\/:*?\"<>|]", "");

Boost开发指南-3.9object_pool

object_pool object_pool是用于类实例&#xff08;对象&#xff09;的内存池&#xff0c;它的功能与pool类似&#xff0c;但会在析构时对所有已经分配的内存块调用析构函数&#xff0c;从而正确地释放资源。 object_pool位于名字空间boost&#xff0c;为了使用object_pool组件…

千元级入门单板吉他推荐,SAGA萨伽SF700、VEAZEN费森VZ200、布鲁克V12、恩雅X1PRO全方面评测对比,哪一款更值得购买!

很多吉他初学者的预算不多&#xff0c;就想要选购平价又好用的吉他&#xff0c;这个想法是很正确的。初学者要注意的是这种平价且高性价比的吉他需要仔细挑选&#xff0c;太便宜的合板吉他保证不了原材料的品质和制作工艺要求&#xff0c;音准手感都无法保证&#xff0c;那么这…

云主机秘钥泄露及利用

前言&#xff1a; 云平台作为降低企业资源成本的工具&#xff0c;在当今各大公司系统部署场景内已经成为不可或缺的重要组成部分&#xff0c;并且由于各类应用程序需要与其他内外部服务或程序进行通讯而大量使用凭证或密钥&#xff0c;因此在漏洞挖掘过程中经常会遇到一类漏洞&…

时间复杂度、空间复杂度实践练习(力扣OJ)

目录 文章目录 前言 题目一&#xff1a;轮转数组 思路一&#xff1a; 思路二&#xff1a; 思路三&#xff1a; 题目二&#xff1a;消失的数字 思路一&#xff1a; 思路二&#xff1a; 思路三&#xff1a; 题目三&#xff1a;移除元素 思路&#xff1a; 总结 前言 想要编写高效的…

2023年第四届“华数杯”数学建模思路 - 案例:随机森林

## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林&#xff1f; 随机森林属于 集成学习 中的 Bagging&#xff08;Bootstrap AGgregation 的简称&#xff09; 方法。如果用图来表示他们之…

【技术分享】SSD20X USB摄像头使用

本文主要介绍基于Purple Pi R1演示如何配置USB摄像头&#xff0c;此方法适用于SSD201/202全系列产品。 Purple Pi R1主板&#xff0c;是基于 SigmaStar SSD201 SoC&#xff08;ARM Cortex A7 内核&#xff09;兼容树莓派的开发板&#xff0c;主频高达1.2GHz&#xff0c;256KB …

HR如何提高自己的薪资?或许是一个好选择!

从助理到总监&#xff0c;随着级别的提升&#xff0c;薪资也水涨船高&#xff0c;从4K涨到了24K。值得注意的是&#xff0c;从助理到主管&#xff0c;薪资涨幅较小&#xff0c;而从主管到总监&#xff0c;尤其是经理到总监&#xff0c;薪资有很大的突破。 各行业HR人员薪资水平…

Hutool BeanUtils.copyProperties的四种用法 空不拷贝/忽略拷贝/空不和忽略拷贝/全拷贝

关注公众号&#xff1a;”奇叔码技术“ 回复&#xff1a;“java面试题大全”或者“java面试题” 即可领取资料 一、Hutool BeanUtils.copyProperties的四种用法 空不拷贝/忽略拷贝/空不和忽略拷贝/全拷贝 1、第一种用法&#xff1a; BeanUtils.copyProperties(三个参数) 不为空…

数组指针

数组指针的定义 1.数组指针是指针还是数组&#xff1f; 指针。 int a 10;int* p &a;//指向整型数据的指针 char b w;char* q &b;//指向字符变量的指针 所以数组指针应该是指向数组的指针。 2.数组指针应该怎么定义&#xff1f; int arr[10] { 0 };int(*p)[10] …

【python爬虫】获取某一个网址下面抓取所有的a 超链接下面的内容

import requests as rq from bs4 import BeautifulSoup as bs import re# rooturl是传的是我需要查询和抓取的一个网址&#xff0c;可以是html js 等 def gethtml(rooturl, encoding"utf-8"):#默认解码方式utf-8response rq.get(rooturl)response.encoding encodin…

Dockerfile构建httpd镜像(yum方式)

Dockerfile构建httpd镜像&#xff08;yum方式&#xff09; 1、建立工作目录 [rootdocker ~]# mkdir httpd [rootdocker ~]# cd httpd 2、编写Dockerfile文件 [rootdocker httpd]# vim Dockerfile FROM centos:7 MAINTAINER Crushlinux <crushlinux163.com>RUN yum -…

2023最新AI艺术二维码制作软件教程【软件工具+教程】下载

2023最新AI艺术二维码傻瓜式生成教程&#xff0c;不需要市面上繁琐的安装步骤和显卡的配置要求&#xff01;我看了一眼市面上的要么只有视频教程&#xff0c;无工具纯纯牛马用来扯淡了。 要么就是安装繁琐&#xff0c;配置要求还高&#xff01; 这期教程教大家怎么傻瓜式制作…

java在idea开发工具中测试Spring Boot上线后临时变量是否可用

上文 java Spring Boot上线运维 启动jar时控制台调整零时变量 我们亲手在项目部署之后 调试了临时变量 但是 目前就还有一个问题 这些指令一般是运维人员去操作的 但是 我们作为开发人员 要保证这些临时变量都是可操作的 或者 不能操作也要提前说清楚 毕竟项目是你写的 你也要负…

QT充当客户端模拟浏览器等第三方客户端对https进行双向验证

在 ssl单向证书和双向证书校验测试及搭建流程 文章中&#xff0c;已经做了基于https的单向认证和双向认证&#xff0c;&#xff0c;&#xff0c; 在进行双向认证时&#xff0c;采用的是curl工具或浏览器充当客户端去验证。 此次采用QT提供的接口去开发客户端向服务器发送请求&a…

安装skywalking并集成到微服务项目

文章目录 一、前言二、介绍1. 架构 三、安装skywalking服务端四、启动skywalking服务端五、微服务项目开发注册中心网关服务商品服务订单服务支付服务测试 六、下载java客户端七、微服务集成skywalking客户端1. idea启动2. 命令行启动3. 集成效果 八、skywalking客户端配置1. 配…

Java版本spring cloud + spring boot企业电子招投标系统源代码 tbms

&#xfeff;功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&…

Nginx特性应用及载装

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力在同类型的网页服务器中表现较好&#xff0c;中国大陆使用nginx的网站有&#xff1a;网易、腾讯、阿里等。 …

19.Netty源码之粘包/拆包

本节课开始我们将学习 Netty 通信过程中的编解码技术。 编解码技术这是实现网络通信的基础&#xff0c;让我们可以定义任何满足业务需求的应用层协议。 在网络编程中&#xff0c;我们经常会使用各种网络传输协议&#xff0c;其中 TCP 是最常用的协议。 我们首先需要了解的是 TC…

手机pdf转换成word免费版?看看这几个转换方法

手机pdf转换成word免费版&#xff1f;在当今信息化的时代&#xff0c;PDF文档已经成为公文交流、资料分享、学术论文等领域中最常用的文件格式之一。然而&#xff0c;PDF文档的固化特性也使其在文本编辑、内容修改等方面存在不便。因此&#xff0c;将PDF文档转换为Word文档已成…