Cesium中用到的图形技术——Horizon Culling
译者注:本文翻译自Cesium官方博文《Horizon Culling》,by KEVIN RING。
在开发像Cesium这样的虚拟数字地球时,我们需要能够快速确定场景中的对象(例如地形图块,卫星,建筑物,车辆等)何时不可见,因此不需要渲染。当然,我们进行视锥体裁剪。但是,另一种重要的剔除类型是地平线剔除。

在上图中,观看者可以看到绿点。 红点不可见,因为它们在视锥面之外,用粗白线表示。 蓝点位于视锥中,但由于地球遮挡住,因此观看者看不到。 换句话说,它在地平线之下。 “地平线剔除”是一个简单的想法,您无需渲染从当前查看器位置观察到的位于地平线以下的对象。 听起来很简单,但细节变得棘手,特别是因为它需要非常快。 Cesium会对每个渲染帧进行数百次此测试,以测试地形图块的可见性。 不过,这是一项重要的测试。 在上图中的配置中,覆盖整个地球的地形图块位于视锥中。 但是,其中有一半以上不在地平线范围内,不需要渲染。
几年前,Deron Ohlarik写了两篇有关地平线剔除的出色文章。 此后,我们对他的技术进行了扩展,我想在这里分享。 尽管它仅适用于地形图之类的静态数据,但我们发现它非常有用,因为它比以前的技术更快,更准确。 精度的提高来自对地球的椭球模型的视界剔除,而不是球面近似。
我首先要提到,这项技术的功劳完全归功于我的同事弗兰克·斯通纳(Frank Stoner)。 我所做的唯一贡献就是在他做了艰辛的工作后,在Cesium中实现了它,并在此处进行了编写。
地平线针对球体剔除一个点
如Ohlarik所述,出于水平剔除的目的,我们可以为静态对象(例如地形图块)计算边界球,该边界球是如此紧密以至于它仅仅是一个点。 如果该点在地平线以下,那么我们可以确保整个图块也在地平线以下。 我们的新技术仅限于针对椭球体选出一个点,因此我们假设此“遮挡点”已被计算出来。 有关如何完成此操作的详细信息,请参见后续博客文章。
我保证我们会针对普通的椭球体实施视界剔除,而我会兑现这一诺言,但让我们首先使用一个简单的单位球体进行视界剔除。 然后,我将证明我们可以轻松地将其概括为任意的椭球体。 考虑下图:

在此图中,蓝色圆圈是我们的单位球面。 从摄影机位置延伸并与球体相切的线代表地平线。黑色垂直线代表所有地平线点。在我们的单位球面上,地平线点位于平面上并形成一个圆。从摄像机位置到所有地平线点的向量形成一个无限锥。
球体的部分及其周围的空间以灰色阴影表示代表地平线以下的区域。从摄像机位置看不到阴影区域中的任何点。直观地说,如果该点位于由切向量形成的无限锥内,则该点位于地平线下方,并且位于包含所有地平线点的平面之后。
平面测试
首先,让我们进行一项代价很小的测试,以确定一个点在平面的哪一侧。 考虑下图:

我们知道向量\(\vec{VC}\)和\(\vec{VH}\)分别是相点到目标点和相点到椭球中心点的向量。同时,由于这里使用的是单位球,向量\(\vec{HC}\)是一个单位向量,根据勾股定理:
\]
\]
接下来,我们注意到三角形△VCH和△HCP是相似三角形。他们共享一个位于C点的角并且都有一个直角,因此:
\]
\]
\]
因此,从视点到平面的距离为:
\]
如果\(\vec{VT}\)在\(\vec{VC}\)上的投影小于\(\lVert \vec{VP} \rVert\),那么目标点就在平面之前。换句话说,目标点在视平面之后的条件是:
\]
两边同时乘以\(\lvert \vec{VC} \rvert\):
\]
综上所述,要确定目标点是否在视线平面之后,可以使用视点到目标点的矢量,与视点到椭球体的中心的矢量的点积。 如果该值大于从观察者到椭球中心的向量的模的平方减一,则目标点在平面后面。不需要开平方或三角函数操作。
圆锥测试
如果目标点在视平面前面,那么该目标点绝对不会被球体遮挡,此时工作就完成了。但是,如果它在视平面后方,能否被遮挡是不确定的。如果目标点也在,视点与所有地平线点连接而形成的无限锥体内,则它被遮挡。如果它在那个圆锥体之外,那么它不会被遮挡。那么我们如何通过圆锥测试点呢?
让我们再次看一下图,这次是角度∠HVC标记为α,∠TVC标记为β:

可以看到,如果点T要在圆锥体内,那么:
\]
对于\(0<=θ<=π\),有:
\]
角α是直角三角形△VCH的一部分,所以我们通过三角函数,重写不等式的右边:
\]
根据点积的定义,有:
\]
\]
\]
\]
为了求平方根的操作,两边都进行平方:
\]
通过对两边进行平方,针对对顶圆锥,我们能有效地测试目标点,其中第二个锥体从观察者指向远离椭圆体。然而,这不会影响我们的结果,因为观察者后面的目标点肯定在地平线前面。视平面前面的任何点都不能被地平线剔除,因此不需要第二个锥体测试。
现在我们站在哪里?\(\vec{VC}\)和\(\vec{VT}\)很容易从我们已知的椭球中心、目标点和观察者位置计算出来。\(\vec{VH}\)不是那么明显。但是还记得在对视平面进行测试的部分吗?我们发现:
\]
这不仅容易计算,而且我们在确定点在平面的哪一侧的过程中已经这样做了。类似地,我们已经计算了\(\vec{VT}\cdot\vec{VC}\)。
所以我们最终的不等式,只需要一点更多的算术运算来评估,如下所示:
\]
如果此不等式成立,则目标点在锥体内部。如果它也在地平线后面,则目标点被遮挡。
推广到椭球
在我们漂亮的小单位球世界中,这一切都非常优雅。 我们如何将其推广到任意椭球体?我们的单位球面方程为:
\]
而椭球的方程为:
\]
其中a,b和c分别是椭圆体沿x,y和z轴的半径。
给定一个以原点为中心的椭球、一个观察者位置和一个目标位置,我们可以对所有坐标应用缩放变换,以创建一个等效的问题,其中椭球实际上是一个单位球体。 执行缩放操作的矩阵如下所示:
\begin{matrix}
\frac{1}{a} & 0 & 0\\
0 & \frac{1}{b} & 0 \\
0 & 0 & \frac{1}{c}
\end{matrix}
\right)
\]
我们将此缩放坐标系称为椭球缩放空间,并发现它对于解决椭球上的各种问题很有用。
可以在SIGGRAPH 2010上展示的海报GPU Ray Casting of Virtual Globes的第2节中找到对该主题的更严密的处理。
代码
我认为把所有的数学都写出来很重要,但这一切都归结为一些简单的代码。每次相机位置改变时,我们执行:
// Ellipsoid radii - WGS84 shown here
var rX = 6378137.0;
var rY = 6378137.0;
var rZ = 6356752.3142451793;
// Vector CV
var cvX = cameraPosition.x / rX;
var cvY = cameraPosition.y / rY;
var cvZ = cameraPosition.z / rZ;
var vhMagnitudeSquared = cvX * cvX + cvY * cvY + cvZ * cvZ - 1.0;
然后,对于我们希望测试遮挡剔除的每个点:
// Target position, transformed to scaled space
var tX = position.x / rX;
var tY = position.y / rY;
var tZ = position.z / rZ;
// Vector VT
var vtX = tX - cvX;
var vtY = tY - cvY;
var vtZ = tZ - cvZ;
var vtMagnitudeSquared = vtX * vtX + vtY * vtY + vtZ * vtZ;
// VT dot VC is the inverse of VT dot CV
var vtDotVc = -(vtX * cvX + vtY * cvY + vtZ * cvZ);
var isOccluded = vtDotVc > vhMagnitudeSquared &&
vtDotVc * vtDotVc / vtMagnitudeSquared > vhMagnitudeSquared;
在 Cesium 中,我们预先计算缩放空间位置,而不是在每次测试之前进行,如上所示。
预览
使用这种技术在Cesium中进行地形剔除,与我们之前使用最小半径边界球剔除的技术相比,我们可以避免绘制大约15%的瓦片,否则我们会在普通场景中绘制。令人高兴的是,新测试对每个图块的执行速度也更快!
到目前为止,我们绕过的一个细节是我们如何从我们的地形图块和其他静态几何体生成“被遮挡物”测试点。目前,我们正在根据(错误但保守的)假设计算每个瓦片的被遮挡点,即使用由椭圆体的最小半径形成的球体来执行遮挡。通过对被遮挡点使用更准确的计算,我们应该能够剔除更多的图块。
更新:这在后续文章中有更详细的介绍。
然而,虽然椭球是用于地平线剔除的方便且相当准确的表面,但我们必须始终牢记,真实地形通常位于椭球下方。如果我们改进被遮挡点的计算,我们必须注意,相对于椭球更准确的地平线剔除最终不会剔除相对于真实地形实际上仍然可见的瓦片。在渲染水下地形时,这尤其可能成为一个问题。
Cesium中用到的图形技术——Horizon Culling的更多相关文章
- Web项目开发中用到的缓存技术
在WEB开发中用来应付高流量最有效的办法就是用缓存技术,能有效的提高服务器负载性能,用空间换取时间.缓存一般用来 存储频繁访问的数据 临时存储耗时的计算结果 内存缓存减少磁盘IO 使用缓存的2个主要原 ...
- SQL on Hadoop中用到的主要技术——MPP vs Runtime Framework
转载声明 本文转载自盘点SQL on Hadoop中用到的主要技术,个人觉得该文章对于诸如Impala这样的MPP架构的SQL引擎和Runtime Framework架构的Hive/Spark SQL ...
- ShadowGun 图形技术分析
https://zhuanlan.zhihu.com/p/27966138 ShadowGun虽然是2011年的移动平台的游戏demo,但是里面的很多优化技巧到现在来看都是很值得学习的,毕竟是上过西瓜 ...
- Excel催化剂开源第46波-按行列排列多个图形技术要点
此篇对应功能出自:第10波-快速排列工作表图形对象 - 简书 https://www.jianshu.com/p/eab71f2969a6 在Excel的对象模型中,列的宽度不是一般所期待的和行高一样 ...
- vue + cesium开发(4) 绘制图形
在官方例子中每个图形都是一个entity,官方例子提供了显示正方形.圆形.锥形.图片等多种案例! // 初始花 var viewer = new Cesium.Viewer("cesiumC ...
- 盘点SQL on Hadoop中用到的主要技术
转载自:http://sunyi514.github.io/2014/11/15/%E7%9B%98%E7%82%B9sql-on-hadoop%E4%B8%AD%E7%94%A8%E5%88%B0% ...
- 3D游戏图形技术解析(7)——视差映射贴图(Parallax Mapping)【转】
http://www.cnblogs.com/taotaobujue/articles/2781371.html 视差映射贴图(Parallax Mapping) ● 传统纹理贴图的弊端 纹理贴图大家 ...
- 浅析DirectX11技术带给图形业界的改变(一) 浅析DirectX11技术带给图形业界的改变【转】
浅析DirectX11技术带给图形业界的改变(一) 浅析DirectX11技术带给图形业界的改变 前言:2009年10月23日,微软高调发布了其最新一代操作系统——Windows7,这款操作系统相对于 ...
- HMS Core图形图像技术展现最新功能和应用场景,加速构建数智生活
[2022年7月15日,杭州]HUAWEI Developer Day(华为开发者日,简称HDD)杭州站拉开帷幕.在数字经济不断发展的今天,开发者对图形图像的开发需求更加深入和多样化,从虚拟环境重构到 ...
- OpenGL基础图形编程
一.OpenGL与3D图形世界1.1.OpenGL使人们进入三维图形世界 我们生活在一个充满三维物体的三维世界中,为了使计算机能精确地再现这些物体,我们必须能在三维空间描绘这些物体.我们又生活在一个充 ...
随机推荐
- Rockchip rk3588 U-Boot详解 (三)
Rockchip rk3588 U-Boot详解 (三) 专栏总目录 1.1 Environment-Variables ENV(Environment-Variables)是U-Boot支持的一种全 ...
- Godot - 通过C#实现类似Unity协程
参考博客Unity 协程原理探究与实现 Godot 3.1.2版本尚不支持C#版本的协程,仿照Unity的形式进行一个协程的尝试 但因为Godot的轮询函数为逐帧的_Process(float del ...
- Springboot+Mybatis+Mybatisplus 框架中增加自定义分页插件和sql 占位符修改插件
一.Springboot简介 springboot 是当下最流行的web 框架,Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程 ...
- C++常见算法&数据结构模版
各种常见算法 & 数据结构模板 1. 最长不下降子序列(LIS) 1.1 \(O(n^2)\) 做法 点击查看代码 for (int i = 1;i <= n;i++) { cin &g ...
- [ABC321C] 321-like Searcher
Problem 题目简述 给你一个 \(K\),求出 \([1 \sim K]\) 区间内有多少个 321-like Number. 321-like Number 的定义: 每一位上的数字从左到右严 ...
- Gson替换掉多漏洞的FastJson
添加依赖: <!-- gson --> <dependency> <groupId>com.google.code.gson</groupId> < ...
- 使用OSS搭建私有云内网yum仓库的方法
版权声明:原创作品,谢绝转载!否则将追究法律责任. ----- 作者:kirin 使用OSS搭建私有云内网yum仓库的方法 文字&图片内容已脱敏 #.前几天接到一个搭建内网yum源的任务.刚接 ...
- 不会这5个Excel函数,别说你会做数据分析?
当涉及数据分析时,Excel是一个非常有用的工具,而掌握一些核心函数将大大提高你在数据处理和分析方面的能力.以下是我对五个重要的Excel函数的详细介绍: 1. VLOOKUP 函数 VLOOKUP ...
- 解密Prompt系列20. LLM Agent之再谈RAG的召回多样性优化
几个月前我们就聊过RAG的经典方案解密Prompt系列14. LLM Agent之搜索应用设计.前几天刚看完openAI在DevDay闭门会议上介绍的RAG相关的经验,有些新的感悟,借此机会再梳理下R ...
- MybatisPlus最新代码生成器(version3.5.1+),自定义文件模板
1.导入依赖(我这里用的是gradle构建工具,maven也一样啦~) plugins { id 'java' id 'org.springframework.boot' version '2.7.3 ...