回想四叉树LOD地形(上)
为什么要用LOD地形?
这样一来。不管是CPU或者是GPU的开销都非常大,地形略微变大,机器要做的工作就要多非常多,实时程序随时变成播放幻灯片。
况且,假设地形比較大,那么在远处的地形三角形被投影到屏幕上时或许已经变成了几个像素点。甚至不可见了。
既然远处的地形对我们的视觉贡献不大。那么为什么还要辛辛苦苦地让硬件做那么多的无用功呢?
那就是LOD地形。LOD的全称是“Level Of Detail”(细节层级),主要的要求是:在近处的地形渲染得尽可能具体,在远处的地形渲染得尽可能简单。
通常。LOD地形除了“远粗近细”的功能外。一般还加上了“视锥体可见性剔除”功能,即仅仅考虑在视野范围内的地形三角形是否渲染,而绝不渲染在视野外的。这种“简化”+“剔除”机制能够大幅度减少机器的开销。听起来是挺有吸引力的,可是到底怎么实现呢?
地形是由 (2^n+1) X (2^n+1) 个顶点组成,当中n>0,n到底要多大?我认为跟n有关系的计算都不溢出就好。
左下图就是个9X9的地形样例。实际上的地形不会那么小。几百X几百甚至成千上万也不奇怪,这里仅仅是为了举例说明而已。另外。组成地形的基本单元也不再像龙书中那样使用一个个的独立三角形。而是使用三角形扇为地形基本单位,这里的三角形扇事实上也是由8个三角形组成,在渲染API中使用9个顶点和10个索引表示。
我们最好还是把这样组成的三角形扇称为一个地形结点。如右下图表示:
一个地形结点
说起来非常抽象。后面看代码就清楚了。
因为有些结点须要切割有些不须要。所以最后得到的结果不会像上面三幅图那么规则,或许像这样:
须要切割的结点将切割后得到的子结点压入第二条队列中,自己弹出第一条队列。不须要切割的结点直接弹出第一条队列并送入渲染API。
在第一条队列中全部结点都被处理完成后,两条队列交换身份,第二条队列变成第一条,然后反复之前处理步骤。直到两条队列中都没有结点为止。
由于有可能一个结点大得离谱但却远在天边。若该结点不切割又会造成地形细节大量损失;又或者一个结点小得可怜却近在眼前,本来已经能够表示足够的地形细节了但却依旧被切割了。所以。为了处理好这两种情况,我们还要考虑结点的大小。把两个因素放在一起考虑,由此得出潘大神的第一条评价公式:
这个公式表示,当结点离视点越来越远,且地形结点越来越小时。两者的比值超过C。地形结点就不须要切割。这个调节因子是要依据地形显示的结果来确定的。也就是要在地形系统实现后,在測试阶段进行该因子的调整。
比方左上图中。底下的平面代表简化后的地形结点,上面笼罩着的是实际的地形结点。
直观上,我们会发现有5个误差,在图中显示为结点边上的dh1、dh2、dh3、dh4以及中心处的dh0。为保证误差測量结果尽量准确。我们还要考虑大地形结点被切割成4个子地形结点后,每一个子节点的粗糙度。在右上图中表示为dh5、dh6、dh7、dh8。
那子节点的粗糙程度怎么算?我们仅仅须要反复地像计算大结点粗糙度那样即可了,非常easy发现这是个递归的过程。那假设一个地形结点已经切割到没有子节点时怎么办?那就忽略dh5~8,仅仅考虑前5个误差仅仅即可了。
这是由于将地形进行平滑处理之后。地形的粗糙度R降低了。直观上看。简化显示和实际显示的误差不会太大。于是“突”现象就不那么明显了。从公式上看,R值小,地形结点被简化的几率增高了。于是相对显示的三角形就少了。
这句话不理解没关系,先记住。该标志数组的作用是:在当前结点进行切割时提供四周结点的存在信息。若四周的结点都存在则当前结点能够切割,否则,仅仅要四周随意一个结点不存在。当前结点就不能切割。这一步推断是在前面的评价系统之后才运行的,也就是说,评价系统的推断优先于这一步推断,仅仅有两个阶段的推断都通过了,结点才干算真正地能够被切割。
怎样更新?当一个结点能够切割时。将自身相应的标志位设为1,同一时候将四个子结点相应的标志位也设为1。当一个结点不能切割时,将自身相应的标志位也设为1,但同一时候将四个子结点相应的标志位设为0。
我想大家一定会对“结点相应的标志位”这个说法非常不解,事实上在代码实现的时候。一个结点仅仅须要用中心顶点的索引以及所属级别来表示即可了,仅仅是送入渲染API时才转换成10个索引表示的三角形扇,到时看代码就知道了。非常抽象是吧?以下我来用9X9的样例演示一下。
一開始地形块太大,如果被评估为须要切割,那么标志数组修改就像以下左中两幅图:
话说回来,中间那幅图的大地形结点在切割时需不须要考虑四周的标志位?当然要,但是去哪找?道理同前。如今看看推断四周标志后不可分的情况。
所以,即使左方结点后来通过了评价系统的切割评估,但在查看四周结点标志时。发现右方结点不存在,所以左方结点切割失败。分析完成。
前面提到过。在地形进行切割时,地形结点能够用结点中心顶点所在的索引和结点所属的级别表示,在送到渲染API时再转换成10个顶点索引表示的三角形扇。嘿!我们就是要在结点转换成10个索引的过程中消除裂缝。
怎么做?请看下图:
我们从左图能够发现,高分辨率级别的结点(即小结点)的正右方的标志位是0,代表正右方同等级别的结点不存在,依据这一信息。我们就能够把中间那幅图中的三角形扇的4号结点给忽略,这就导致0、3、5结点能够组成一个大点的三角面,而不再须要分别显示0、3、4和0、4、5组成的三角形。这个操作就消除掉了由4号结点引起的高度差,T型裂缝就是这样被消除掉了。如右上图。也就是说,我们能够依据一个结点四周相邻同等级别的结点相应的标志位是否为1来确定中间节点四条边中点的顶点是否參与渲染,从而消除裂缝。
~四叉树LOD的回想就差点儿相同这样了。感觉有必要做个重要代码回想,还是改天有时间写个下篇吧。本文不作为个人技术的创新展示,仅仅是学习心得的分享,全部知识都来自大神们的研究成果。
关于潘李亮的论文和曾涛的代码实现,改天再补上链接,如今得歇息············
回想四叉树LOD地形(上)的更多相关文章
- [转]基于四叉树(QuadTree)的LOD地形实现
实现基于四叉树的LOD地形时,我遇到的主要问题是如何修补地形裂缝. 本段我将描述使用LOD地形的优势,我实现LOD地形的思路,实现LOD地形核心模块的详细过程,以及修补地形裂缝的思路. 首先,LOD地 ...
- Ogre代码学习之1——Ogre中地形lod的基础:deltaHeight的计算
Ogre的地形系统中的重要概念:高度差,英文HeightDeltas,表示某个完整细节中的顶点,在某个它被隐去的lod中被插值之后的高度和原始高度(即高度图中的高度)之差. DeltaHeight = ...
- CesiumJS 2022^ 原理[4] - 最复杂的地球皮肤 影像与地形的渲染与下载过程
目录 API 回顾 1. 对象层级关系 1.1. Scene 中特殊的物体 - Globe 1.2. 地球 Globe 与椭球 Ellipsoid 1.3. 瓦片四叉树 - QuadtreePrimi ...
- 【SSH2(实用文章)】--Struts2文件上传和下载的例子
回想一下,再上一篇文章Struts2实现机制,该步骤做一步一步来解决,这种决心不仅要理清再次Struts2用法.映射机制及其在深入分析.最后一个例子来介绍Struts2一种用法,这里将做一个有关文件上 ...
- Unity3D LOD Group
今天下了一个4.0破解版,然后看到一个Demo Level of Detail 就研究了一下 以前用的是Unity3.5 free版本,没有这个功能,真实泪奔....... As your s ...
- 记一次线上 OOM 和性能优化
大家好,我是鸭血粉丝(大家会亲切的喊我 「阿粉」),是一位喜欢吃鸭血粉丝的程序员,回想起之前线上出现 OOM 的场景,毕竟当时是第一次遇到这么 紧脏 的大事,要好好记录下来. 1 事情回顾 在某次周五 ...
- 🏆【Alibaba中间件技术系列】「Nacos技术专题」配置中心加载原理和配置实时更新原理分析(上)
官方资源 https://nacos.io/zh-cn/docs/quick-start.html Nacos之配置中心 动态配置管理是 Nacos的三大功能之一,通过动态配置服务,可以在所有环境中以 ...
- PVS BSP
作者:韦易笑链接:https://www.zhihu.com/question/38060533/answer/84432973来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 剖析虚幻渲染体系(14)- 延展篇:现代渲染引擎演变史Part 1(萌芽期)
目录 14.1 本篇概述 14.1.1 游戏引擎简介 14.1.2 游戏引擎模块 14.1.3 游戏引擎列表 14.1.3.1 Unreal Engine 14.1.3.2 Unity 14.1.3. ...
随机推荐
- position记录元素原始位置
position记录元素原始位置 css样式: li { width: 100px; height: 100px; margin: 10px 0 0 10px; background-color: # ...
- Hadoop MapReduce编程 API入门系列之多个Job迭代式MapReduce运行(十二)
推荐 MapReduce分析明星微博数据 http://git.oschina.net/ljc520313/codeexample/tree/master/bigdata/hadoop/mapredu ...
- poj3083 Children of the Candy Corn 深搜+广搜
这道题有深搜和广搜.深搜还有要求,靠左或靠右.下面以靠左为例,可以把简单分为上北,下南,左西,右东四个方向.向东就是横坐标i不变,纵坐标j加1(i与j其实就是下标).其他方向也可以这样确定.通过上一步 ...
- 关于生sql中的空值
在数据库中的空值无非就是两种形式的表示 一种是什么都没有,一种是以NuLL显示的 , 那么在C# 读取出来怎么判断呢, DtStatus.Rows[0]["FetchCode"]. ...
- 开源作品-PHP写的在线文件管理工具(单文件绿色版)-SuExplorer_PHP_3_0
前言:项目开发过程中,网站一般部署到远程服务器,所以文件管理就不能和本机操作一样方便.通常文件管理是用ftp下载到本地,修改后再上传,或者远程登录到服务器进行修改.但是这些操作都依赖于复杂的第三方软件 ...
- 数组、ArrayList、HashTable
相同点:都可以存储一组数据 不同点: 1)数组,必须要先分配空间,存储数据固定 2)ArrayList,存储数据可以自由扩展 3)HashTable与ArrayList一样,但是它是有意义的,键值对形 ...
- 洛谷P1120 小木棍 [数据加强版]搜索
玄学剪支,正好复习一下搜索 感觉搜索题的套路就是先把整体框架打出来,然后再一步一步优化剪枝 1.从maxv到sumv/2枚举长度(想一想,为什么) 2. 开一个桶,从大到小开始枚举 3. 在搜索中,枚 ...
- windows 端口号占用和解决方法
https://blog.csdn.net/qq_39657909/article/details/80378983
- vue自己写了一个div菜单,点击按钮展开,点击其他地方关闭这个div菜单
需求是通过点击body页面,在其他地方就关闭这个<div>菜单,给这个div一个id:problemList,但是点击我打开的按钮,不关闭. created () { document.o ...
- Spring Boot project with static content generates 404 when running jar
转自:http://stackoverflow.com/questions/21358403/spring-boot-project-with-static-content-generates-404 ...