将地球的卫星照片转换为球体纹理映射(OpenGL ES)

4
我们有5颗静止轨道卫星,分布在赤道周围(间距不完全相等,但差不多)每天拍摄地球的照片。每张照片的输出结果就是——意外!——一个从远处拍摄的球体照片。
我需要将这些照片重新组合成一个纹理贴图球体,但我不确定最佳方法。关键问题:
  1. 由于这些照片拍摄对象为球体,当您离中心越远时,它们会产生极大的畸变。
  2. 有许多“组”由5张照片组成,不同时间拍摄的。任何解决方案都需要编程实现,我不能手动完成:(
  3. 输出平台是iPad3:Open GL ES 2,纹理大小可达4096x4096-但不如桌面GPU强大。我不太擅长着色器(尽管我已经做了很多OpenGL预着色器)。
  4. 这些照片本身的分辨率很高,我不确定是否可以同时加载所有5个纹理。我还为行星表面加载了非常高分辨率的纹理(在卫星照片下面)。
我已经具备了:将单个矩形纹理映射到球体上(我的球体是标准网格包装成球体,顶点均匀分布在表面上),所以…我试图将5个球体照片转换为单个矩形贴图(但目前没有成功;虽然有人指向了一个“极坐标正弦变形”,看起来可能效果更好)。
我还考虑过用5张照片制作立方贴图,并聪明地决定读取哪张照片来提供给给定的像素,但我并不完全信服。
是否有更好的方法?我是否忽略了什么?或者有人已经实现了上述功能的具体方法吗?
1个回答

0

我会从中制作一个矩形纹理。

你需要两个2D纹理/数组,一个用于r,g,b颜色总和的平均值avg,另一个用于计数cnt。此外,我不确定是否应该使用OpenGL/GLSL,对我来说,C/C++会更好。

我会这样做:

  1. 清空目标纹理 (avg[][]=0, cnt[][]=0)
  2. 获取卫星位置/方向、时间

    从位置和方向创建转换矩阵,该矩阵将地球投影到与照片相同的方式。然后根据时间确定旋转偏移。

  3. 整个地球表面循环

    只需要两个嵌套循环 a - 旋转和 `b - 距赤道的距离。

  4. a,b 和变换矩阵 + 旋转位移 (a-轴) 获取 x,y,z

    也可以反向执行 a,b,z = f(x,y),但这更加棘手但更快更准确。您还可以在相邻的 (pixels/areas)[a][b] 之间插值 x,y,z

  5. 添加像素

    如果 x,y,z 在正面 (z>0z<0 取决于摄像机 Z 方向),则

    avg[a][b]+=image[x][y]; cnt[a][b]++;
    
  6. 嵌套循环#3结束。

  7. 转到#2并使用下一个照片
  8. 整个 avg 纹理循环以恢复平均颜色

    if (cnt[a][b]) avg[a][b]/=cnt[a][b];
    

[注]

  1. 可以测试复制的像素是否为:

    在白天或晚上获取(只使用您想要的,不要混合在一起!)还可以确定云层(我认为是灰色/白色而不是雪)并忽略它们。

  2. 不要溢出颜色

    可以使用3个单独的纹理r [] [],g [] [],b [] []而不是avg来避免这种情况

  3. 可以忽略地球边缘附近的区域以避免扭曲

  4. 可以应用照明校正

    时间a,b坐标来规范照明

希望有所帮助...

[编辑1]正交投影

因此,这里是我所说的正交投影的含义:

Satellite photo texture (EUMETSAT)

这是使用的纹理(在网络上找不到更适合且免费的),我想使用真实的卫星图像而不是一些渲染出来的东西...

orthogonal projection

这是我的正交投影应用程序

  • 红、绿、蓝线是地球坐标系(x,y,z轴)
  • (红、绿、蓝)白色线是卫星投影坐标系(x,y,z轴)

目的是将地球顶点坐标(vx,vy,vz)转换为卫星坐标(x,y,z)如果z>=0则为已处理纹理的有效顶点,因此可以从x,y 直接计算纹理坐标(正交)而不需要透视。

例如:tx=0.5*(+x+1); ... 如果x被缩放到<-1,+1>并且可用的纹理是tx <0,1>,那么对于y轴也是一样的:ty=0.5*(-y+1); ... 如果y被缩放到<-1,+1>并且可用的纹理是ty <0,1>(我的相机与纹理矩阵相比具有反转的y坐标系,因此在y轴上有反转符号)。
如果z < 0,则正在处理超出纹理范围的顶点,因此请忽略它...正如您在图像上看到的,纹理的外部边界被扭曲,因此您应该仅使用内部(例如地球图像区域的70%),还可以根据距离从纹理中心点进行某种纹理坐标校正。完成后,将所有卫星图像投影合并为一个图像即可。 [编辑2]好吧,我稍微玩了一下,发现了这个:
  • 反向投影校正对我的纹理根本不起作用,我认为可能是后处理的图像...
  • 基于中点距离的校正似乎很好,但使用的比例系数很奇怪,不知道为什么要乘以6,当应该是4时...

    tx=0.5*(+(asin(x)*6.0/M_PI)+1); 
    ty=0.5*(-(asin(y)*6.0/M_PI)+1); 
    

corrected nonlinear projection

校正非线性投影(通过asin)

corrected nonlinear projection edge zoom

  • 修正了非线性投影边缘缩放
  • 纠正asin纹理坐标后,扭曲比没有纠正时小得多

一个暴力的方法是“采样、反投影,然后将结果插值/模糊成一个新的矩形纹理”。看起来应该可以正常工作,尽管我更喜欢做一些可以在线运行的东西,因为例如Apple/Imagination不允许我们在运行时生成PVR纹理:( - Adam
在你的应用程序中创建BMP / TGA / JPG / PNG纹理文件,然后使用命令行工具(例如texturetool)将其转换为PVR纹理,再从文件加载它如何?或者在运行时也不允许?另外,为什么不能使用非PVR纹理(这种情况下速度会更快)。您还可以通过GLSL进行所有渲染变换,但根据您的描述,在运行时无法更改输入数据,因此您的应用程序固定为相同的输入图像,这似乎很愚蠢(所以您可以在桌面上创建纹理,然后将生成的纹理复制到iPad上...)。 - Spektre
PVR命令行工具需要至少四GB的RAM,因此...它无法在任何你今天可以购买的设备上运行(即使假设Imagination为iOS提供了一个版本-我不相信他们会这样做)。另外,它怎么可能“更快”呢? - Adam
我修改了我的答案,所以你现在可以看到我所说的正交投影的意思了... - Spektre
谢谢!这帮了我很多。比我想象的容易多了,我只是过度复杂化了它 :(. 我真是个傻瓜 :). - Adam
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接