UE4/Unity绘制地图基础元素-面和体

摘要:
三角剖分在使用时有一个前置条件:使用对象必须为简单多边形,即多边形中的任何两条边仅可以在顶点处相交。对于非简单多边形,使用三角剖分只能得出较为满意的结果,但不能保证其正确性。

前言

绘制地图基础元素-线(上篇)

绘制地图基础元素-线(下篇)

搞定地图画线之后,接下来就是绘制面和体了:

面作为地图渲染的基本元素之一,在地图中可以代表各种形式的区域,例如海面、绿地等。面数据通常以离散点串形式存储,因此渲染时最关注的是如何将其展现为闭合的图形。

体可以理解为带有高度的面,在地图中代表各种建筑,通常是由其顶部面数据和高度数据处理得到。

本文记录了绘制面和体的流程以及解决闪烁问题的方案。

绘制多边形区域面

面数据通常以离散点串形式存储,面的绘制与线的绘制原理类似。渲染的基本单位是三角形,线是通过扩展线宽构造三角形后渲染,而面是通过将多边形拆分为多个三角形后渲染。

拆分为三角形的过程被称为三角剖分,常用的三角剖分算法是耳切法(Ear Clipping),比较成熟的方案是Mapbox的earcut,对于有 [公式] 个顶点的多边形,其时间复杂度为 [公式] ,值得注意的是,三角剖分的解可能是不唯一的,任何一种剖分方式都能够渲染得到面,但细小的三角形更容易使面中的同一像素绘制多次,造成过度绘制(Overdraw),因此根据多边形特征做一些剖分次序的调整可以作为一个优化点。

UE4/Unity绘制地图基础元素-面和体第1张

剖分完成的多边形区域,在指定了每一个顶点的颜色之后,就能绘制得到纯色的面。和道路线的Z-fighting问题类似,区域面也需要处理同一高度叠加显示的问题。同时,二维的道路线和区域面整体也处于同一个高度上,因此也需要统一考虑层级关系,将所有的道路线置于区域面之上。统一处理完成就可以得到二维的地图底板了。

UE4/Unity绘制地图基础元素-面和体第2张

绘制多边形建筑体

二维地图底板完成后,就轮到地图上的楼块建筑了。为了减少数据量,通常的存储方式是顶面点串和其对应的拔起高度,在渲染时增加顶点构成闭合体。

顶面渲染流程和闭合区域面一致,侧面则是根据楼高进行绘制,在每两个相邻顶点间渲染一个矩形从而构成闭合体的侧面,为了减少绘制次数通常只绘制朝向外侧的侧面,底面在正常视角下看不到,也可以酌情选择是否绘制。

UE4/Unity绘制地图基础元素-面和体第3张

建筑体的渲染只比区域面多了拔高产生的侧面,逻辑比较简单,处理得到所有三角形数据后,配置好顶点颜色即可完成渲染。

奇怪的建筑体Z-fighting问题

理论上来说,建筑体数据的顶面通常不会重合,因此在拔起渲染后不会出现Z-Fighting问题,但奇怪的是,渲染后仍然发现一些体存在侧面闪烁问题。通过全链路的排查,才查出是多边形数据的问题。

三角剖分在使用时有一个前置条件:使用对象必须为简单多边形,即多边形中的任何两条边仅可以在顶点处相交。下图(a)多边形为满足定义的简单多边形,图(b)多边形边01和23在非顶点处相交,因此是非简单多边形。

UE4/Unity绘制地图基础元素-面和体第4张

对于非简单多边形,使用三角剖分只能得出较为满意的结果,但不能保证其正确性。从下图四个顶点构成的非简单多边形的三角剖分结果可以看到,多边形渲染时会丢失顶点并且产生错误的三角形,无法还原数据真实情况。

UE4/Unity绘制地图基础元素-面和体第5张

按照这种想法对现有数据进行了边的相交检测,确实存在一小部分的多边形不是简单多边形。而体元素的立面拔起是按照原始数据在每一组相邻顶点间绘制矩形,因此会产生问题。以上述的非简单多边形(b)为例,边12拔起生成矩形1245,边23拔起生成矩形2364,两个侧面矩形在面1245上完全重合,当外立面贴上不同的纹理后就会产生Z-Fighting现象。同时,因为外立面仅仅绘制朝向外侧一面,面1245在对侧查看时会消失,产生非常诡异的效果。

UE4/Unity绘制地图基础元素-面和体第6张

针对这个问题,比较容易想到的解决方法主要是以下三个:

1、直接过滤,简单粗暴。

2、根据多边形计算外接矩形,减少细节

3、根据三角剖分结果剔除多余顶点,重新生成简单多边形

以上三个方案对于多边形的细节保留由少到多,但并不是完全还原真实数据。尤其对于一些复杂建筑,某一个面的错误会导致最终拼装得到的渲染结果错误。因此比较理想的方式是修复非简单多边形,将其分解为多个简单多边形,分别渲染还原细节。

简单多边形的判定与修复

根据简单多边形的定义,很容易想到采用暴力解法进行判定:一个 UE4/Unity绘制地图基础元素-面和体第7张 边形有 UE4/Unity绘制地图基础元素-面和体第8张 条边,每条边只需要和其他的 UE4/Unity绘制地图基础元素-面和体第9张 条不相邻边判断是否相交即可达到目的,其时间复杂度为 UE4/Unity绘制地图基础元素-面和体第10张 ,对于仅需要进行一遍数据清洗的静态数据来说已经足够。但对于需要实时处理的动态数据来说,其需要遍历所有组合,尤其对于可能仅存在少量相交点的情况,冗余计算太多,因此可以引入时间复杂度更低的相交判定算法进行处理。

对于一个非简单多边形,在分解为多个简单多边形后,绘制所有面积不为0的图形就可以了。这种方案可以最大限度还原原始数据,并且规避闪烁问题。

UE4/Unity绘制地图基础元素-面和体第11张

小结

解决了数据造成的闪烁问题后,就可以在建筑的侧面和顶面使用纯色或者纹理贴图进行装饰,搭配天空盒和一些纯色元素去装饰,已经可以简略模仿出城市的效果。但在当前的建筑拔起渲染方式下,只能通过贴图的形式去表达建筑细节,如果需要更精细的表达效果,例如玻璃窗体结构、楼顶设施等,需要增加额外的三角形去进行呈现。

UE4/Unity绘制地图基础元素-面和体第12张

作者:程序员阿Tu

链接:https://zhuanlan.zhihu.com/p/266870185

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

免责声明:文章转载自《UE4/Unity绘制地图基础元素-面和体》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇apt-get本地软件源搭建微服务 springboot 启动成功后没有注册到注册中心下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

记录一款Unity VR视频播放器插件的开发

效果图## 先上一个效果图: 背景 公司最近在做VR直播平台,VR开发我们用到了Unity,而在Unity中播放视频就需要一款视频插件,我们调研了几个视频插件,记录两个,如下: Unity视频插件调研 网上搜了搜,最流行的有以下两款Unity插件: AVPro 这个在Unity商店售价150$,最新release版本为1.6.15,功能包括: Power...

unity 之协程返回值

yield return null; // 下一帧再执行后续代码yield return 6;//(任意数字) 下一帧再执行后续代码yield break; //直接结束该协程的后续操作yield return asyncOperation;//等异步操作结束后再执行后续代码yield return StartCoroution(/*某个协程*/);//等...

ue4读取灰度图生成三维地形mesh

转自:https://www.cnblogs.com/gucheng/p/10116857.html 新建ue c++工程。 在Build.cs中添加"ProceduralMeshComponent"模块。 在 uproject中添加"ProceduralMeshComponent"模块。 创建材质,传入grass贴图 导入灰度图资源 创建继承自...

UE4渲染笔记

Lightmass 实时渲染光影效果对性能有很大影响,可利用lightmass预先生成光影贴图,然后在游戏中使用。将场景光照结果完全烘焙到模型贴图上,从而完完全全的假冒现实光照效果。文档上是 lightmass global illumination,可见生成的是全局光照贴图。 光源的移动性 静态照明仅使用光照贴图,阴影在游戏前烘焙。 固定光源的直接光照...

Unity中通过DoTween实现转盘效果

通过转盘的数量,来计算需要旋转到的角度我这里是有12个旋转的位置,故360/12=30,所以,以30度为一个单位,进行偏移计算.. 实现方式如下: DrawRotateScr脚本: /********************************************* * * Title: 大转盘的实现 * * Description...

【Unity优化】图形优化系列03:GPU优化

通常受限于:填充率、内存带宽、顶点处理 填充率 定义:GPU每秒输出到屏幕上的像素数(在游戏开发中,周期可细化到每帧)。 判别标准:降低分辨率,导致性能提升 优化方法: 1)优化片元着色器 2)使用消耗更低的官方着色器(比如用 Mobile 着色器替代 Standard 着色器) 3)如果需要 Standard 着色器,则尽可能少用其中的参数功能 4)优化...