3D场景中的圆形天空顶

本文介绍了如何在3D场景中使用圆形天空顶代替天空盒以解决雾效问题和边界可见性。通过数学方法创建半球体的顶点,利用三角形带构建球体表面,并探讨了纹理映射的挑战,提出使用球面映射以减少纹理拉伸和接缝问题。
摘要由CSDN通过智能技术生成

引言

  如果我们希望在场景里添加一个天空,我们可以仅仅只把背景清除为淡蓝色,不过我相信你会认为那样做太普通了。一般来说,那些让你从窗户或洞孔中向外张望的室内游戏使用的是天空盒。只要使用好的纹理,天空盒将提供让人信服的画面;由于纹理伸展在一个巨大的多边形上,低质量的纹理将很容易被注意到。在户外场景中使用天空盒会引发一些问题,例如使用雾,某些雾的设置可能会引发一些问题。如果雾被设置在观察者的旁边,天空盒将减淡甚至消失。另一个可能发生的更烦人的问题是雾会聚积在天空盒的顶点处,从而将天空盒的多边形暴露无遗。下面的图1显示了在天空盒下使用雾所引发的两个问题.小心地调整雾化参数或者细分天空盒的每一个面可以减少这些问题,但这样会大大影响性能。 

图1. 天空盒的边界被暴露    天空盒几乎无法看见

  在户外场景中使用圆形天空顶取代的天空盒的优点是:由于以更多的顶点构成天空顶,雾将被更平均地渲染。你也可以通过实时改变某些个别顶点的颜色创建一些很酷的效果,例如在一天不同时间里模拟真实的日照。我们也可以使用多纹理,添加个别缓缓移动过天空的云的纹理。

从哪里开始?

  天空顶可以描述为一个半球,图2展示了一个线框模型,我们的天空顶看起来就像那个样子。 

图2.天空盒的侧景

  由此,我们应该以寻找在3D中渲染一个半球的方法而开始,首先,请看创建一个半球的数学方法,方程: 

   x2 + y2 + z2 = r2 

  描述了一个球心在笛卡尔坐标系原点,半径为r的球体。我们可以把它写成下面的方程: 

   f(p) = x2 + y2 + z2 - r2 = 0 

  在上面的方程中,p是圆上一点。使用上面的方程处理球体可能有些棘手,因此我们转向使用球面坐标系,在球面坐标方式下,球体上的一点将由下面的方程决定: 

   p = (px, py, pz) = f(ρ, φ) = (fx(ρ, φ), fy(ρ, φ), fz(ρ, φ)) 

  在这个方程中,ρ(phi [fai])称为纬度,而φ(theta)称为经度。那么,球面坐标系下球体的方程如下: 

   fx(ρ, φ) = r sin(ρ) cos(φ) 
   fy(ρ, φ) = r sin(ρ) sin(φ) 
   fz(ρ, φ) = r cos(ρ) 

  其中,r为球体半径,我们将使用这个方程,因为只要给出一个点的纬度和经度,就可以求出该点的x, y, z 值。对于一个球来说,ρ的取值范围是-90°到90°,φ的取值范围是0°到360°,即: 

   -π/2 <= ρ <=π/2 
   0 <= φ <= 2π 

  上面是一个完整的球体的取值,我们并不需要,但有必要了解。我们会继续渲染出一个完整的球体,然后,我们会看到怎样将它缩减到我们所需要的形状,不过你或许已经知道了我们将要怎样做。 

  现在我们已经知道了怎样获取球体上一个点的坐标,我们再制定一点算法规则,使我们有足够的点来渲染球体。首先,我们需要一点额外信息,球面上有无限多个点,我们当然不需要所有的这些点来渲染一个球体,实际上,只要有两百多个点,我们就能渲染出一个优美的球体(已被公认,可能更少,不过就不会好看了)。φ的取值范围是0°到360°,有无穷多个取值,所以,我们要做的就是取一个值,称为Dφ (dtheta),这个值包括了一定的数量,如此我们就可以从0 到2π间反复取值,沿XZ平面得到 2π/ Dφ个点。比方说对于取值为30°的一个Dφ,我们将得到360° / 30° = 12个点,Dφ取得越小,我们就能得到越多的点(当你实际渲染一个球体时要小心,如果你选择的Dφ太小,你的球体将由巨大数量的顶点所组成,从而影响程序性能)。 

  算法规则的伪码如下: 

for (ρ从 -π/2 到 π/2, ρ += dρ) 

    for (φ 从 0 到2π, φ += Dφ) 
    { 
        px = r * sin(ρ) * cos(φ) 
        py = r * sin(ρ) * sin(φ) 
        pz = r * cos(ρ) 
    } 

  注意:使用三角函数时一定要小心,在我们的例子中是sin和cos,它们使用的是弧度,而在我的算法中,ρ和φ使用的是角度,这样我们能够使用一个for循环而没有由于浮点错误的问题。在代码中,你将看到,在调用sin和cos函数时我对这些值进行了转换。 

  现在我们所得到的是一些在3D空间里分散的点&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值