专栏首页腾讯位置服务UE4/Unity绘制地图基础元素-面和体

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

前言

基于UE4/Unity绘制地图基础元素-线(上篇)

基于UE4/Unity绘制地图基础元素-线(下篇)

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

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

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

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

绘制多边形区域面

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

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

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

绘制多边形建筑体

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

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

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

奇怪的建筑体Z-fighting问题

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

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

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

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

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

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

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

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

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

简单多边形的判定与修复

根据简单多边形的定义,很容易想到采用暴力解法进行判定:一个

边形有
条边,每条边只需要和其他的
条不相邻边判断是否相交即可达到目的,其时间复杂度为
,对于仅需要进行一遍数据清洗的静态数据来说已经足够。但对于需要实时处理的动态数据来说,其需要遍历所有组合,尤其对于可能仅存在少量相交点的情况,冗余计算太多,因此可以引入时间复杂度更低的相交判定算法进行处理。

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

小结

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

作者:程序员阿Tu

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

来源:知乎

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 基于UE4/Unity绘制地图基础元素-线(上篇)

    这篇文章是使用游戏引擎探索地图可视化的开篇。传统的地图渲染通常是在iOS/Android/Web平台进行的,为了探究更酷炫的地图展示,会记录基于UE4/Unit...

    腾讯位置服务
  • 基于UE4/Unity绘制地图 - 确定展示区域

    地图可以看成是一个巨型的开放世界游戏场景,因此为了便于数据存储和查找,传统的做法是将地球根据墨卡托投影转换为平面地图,再将地图分级分块进行切片,通过索引获取到对...

    腾讯位置服务
  • 基于UE4/Unity绘制地图基础元素-线(下篇)

    上篇中记录了绘制线的基本流程,而下篇主要是对绘制线中遇到的性能和效果问题进行阐述。在绘制完一条线并且希望给其加上描边样式时,会遇到不可避免的闪烁问题。而在绘制大...

    腾讯位置服务
  • GDC 2018进行时丨Oculus公布Santa Cruz更多细节,高通发布骁龙845移动VR开发套件

    VRPinea
  • 移植了OVRLipSync到UE4

    逍遥剑客
  • 在Lua中实现对UE4 C++代码的自动补全

    本文介绍了在Emmylua插件的支持下,如何获取到UE4的反射信息,并如何生成Emmylua格式的Lua注释代码来支持自动补全和跳转。

    阿苏勒
  • Unity-Optimizing Unity UI(UGUI优化)01 导航、Unity UI的基础概念与原理

    摘要: 通过Unity UI优化用户的界面驱动是一门艺术,以下将讨论基本的概念、算法和在Unity UI相关代码

    祝你万事顺利
  • 新手小白如何用C++制作经典游戏DNF?

    十年前,那时候的网吧还不叫网咖,那时候没有王者荣耀也没有英雄联盟,那时候梦幻西游刚推出珍宝阁系统,那时候巫妖王的灵魂还封闭在冰封王座。

    诸葛青云
  • 7.24 VR扫描:Knight 75万美元资助VR艺术项目;inXile正开发全新MMORPG VR游戏

    据Knight Foundation的Chris Barr透露,基金会正面向将VR应用于艺术领域的组织、技术专家等征集想法与理念。据悉,被选定的项目将获得75万...

    VRPinea

扫码关注云+社区

领取腾讯云代金券