地球的渲染方法:
渲染地球其中的重中之重是椭球体的曲面细分算法和着色算法。流行的有三种细分算法,用于产生近似地球表面的三角形:
1 基于单位球的简单的表面细分算法,这种方法经常会在计算机图形学课程看到。
2 基于立方体的椭球的曲面细分算法。
3 基于大地测量网格(经纬度)的曲面细分算法(Geographic-Grid Tessellation)。
我们的着色算法起始于简单的片段着色和用低分辨率的卫星图片进行纹理映射。我们比较了在片段着色器中生成法线和纹理坐标和预先生成法线和纹理坐标这两种方法的优缺点,还介绍了一种通过使用GPU射线投射来渲染地球仪的方法。
一:曲面细分算法
GPU主要渲染三角形, 所以要渲染一个基于椭球的地球,我们要计算出近似椭球表面的三角形,然后送到GPU中进行渲染,在这里,我们介绍第三种椭球的曲面细分算法(Geographic-Grid Tessellation)。也许最直观的椭圆曲面细分算法是使用Geographic-Grid Tessellation。 该算法有两个步骤:
1: 首先计算分布在椭球上的一组点。这可以用嵌套的循环来完成, 在φ ∈ [0, π] 和 θ ∈ [0, 2π]范围内选择合适的迭代粒度。回想一下,φ与纬度相似,θ与经度相似。大多数应用对于φ和θ使用不同的粒度,因为它们的范围是不同的。 使用下面等式,将每个网格点从球面坐标转换为笛卡尔坐标:
x = a cos θ sin φ,
y = b sin θ sin φ,
z = c cos φ.
这里,(a,b,c)是椭球的半径,如果a,b,c的值是(1,1,1),那么就是单位球。由于sin(0)= sinπ= 0,北极(φ= 0)和南极(φ=π)被视为在for循环之外的特殊情况。 每个点使用一个点(0,0,±c)。 算法的实现如下面代码所示。 请注意,Math.Cos(theta)和Math.Sin(theta)可以计算一次并存储在查找表中。
List<Vector3d> positions
positions.Add( newVector3d(0, 0, ellipsoid.Radii.Z));
for(int i=1; i<numberOfStackPartitions; ++i)
{
doublephi = Math.PI* (((double)i)/ numberOfStackPartitions);
doublecosPhi = Math.Cos(phi);
doublesinPhi = Math.Sin(phi);
for(int j=0; j<numberOfSlicePartitions; ++j)
{
doubletheta= (2.0 * Math.PI) * (((double)j)/numberOfSlicePartitions);
doublecosTheta=Math.Cos(theta);
doublesinTheta=Math.Sin(theta);
positions.Add(newVector3d( ellipsoid.Radii.X * cosTheta * sinPhi,
ellipsoid.Radii.Y * sinTheta * sinPhi,
ellipsoid.Radii.Z * cosPhi));
}
}
positions.Add(newVector3d( 0, 0, −ellipsoid.Radii.Z));
未完待续。。。
渲染地球其中的重中之重是椭球体的曲面细分算法和着色算法。流行的有三种细分算法,用于产生近似地球表面的三角形:
1 基于单位球的简单的表面细分算法,这种方法经常会在计算机图形学课程看到。
2 基于立方体的椭球的曲面细分算法。
3 基于大地测量网格(经纬度)的曲面细分算法(Geographic-Grid Tessellation)。
我们的着色算法起始于简单的片段着色和用低分辨率的卫星图片进行纹理映射。我们比较了在片段着色器中生成法线和纹理坐标和预先生成法线和纹理坐标这两种方法的优缺点,还介绍了一种通过使用GPU射线投射来渲染地球仪的方法。
一:曲面细分算法
GPU主要渲染三角形, 所以要渲染一个基于椭球的地球,我们要计算出近似椭球表面的三角形,然后送到GPU中进行渲染,在这里,我们介绍第三种椭球的曲面细分算法(Geographic-Grid Tessellation)。也许最直观的椭圆曲面细分算法是使用Geographic-Grid Tessellation。 该算法有两个步骤:
1: 首先计算分布在椭球上的一组点。这可以用嵌套的循环来完成, 在φ ∈ [0, π] 和 θ ∈ [0, 2π]范围内选择合适的迭代粒度。回想一下,φ与纬度相似,θ与经度相似。大多数应用对于φ和θ使用不同的粒度,因为它们的范围是不同的。 使用下面等式,将每个网格点从球面坐标转换为笛卡尔坐标:
x = a cos θ sin φ,
y = b sin θ sin φ,
z = c cos φ.
这里,(a,b,c)是椭球的半径,如果a,b,c的值是(1,1,1),那么就是单位球。由于sin(0)= sinπ= 0,北极(φ= 0)和南极(φ=π)被视为在for循环之外的特殊情况。 每个点使用一个点(0,0,±c)。 算法的实现如下面代码所示。 请注意,Math.Cos(theta)和Math.Sin(theta)可以计算一次并存储在查找表中。
List<Vector3d> positions
positions.Add( newVector3d(0, 0, ellipsoid.Radii.Z));
for(int i=1; i<numberOfStackPartitions; ++i)
{
doublephi = Math.PI* (((double)i)/ numberOfStackPartitions);
doublecosPhi = Math.Cos(phi);
doublesinPhi = Math.Sin(phi);
for(int j=0; j<numberOfSlicePartitions; ++j)
{
doubletheta= (2.0 * Math.PI) * (((double)j)/numberOfSlicePartitions);
doublecosTheta=Math.Cos(theta);
doublesinTheta=Math.Sin(theta);
positions.Add(newVector3d( ellipsoid.Radii.X * cosTheta * sinPhi,
ellipsoid.Radii.Y * sinTheta * sinPhi,
ellipsoid.Radii.Z * cosPhi));
}
}
positions.Add(newVector3d( 0, 0, −ellipsoid.Radii.Z));
未完待续。。。
作者:zg260 发表于2017/8/10 23:38:09 原文链接
阅读:0 评论:0 查看评论