球体纹理错误

4
我有一些球面经纬度坐标需要可视化。为此,我将这些点转换为笛卡尔坐标,并构建了一个三角形网格,可以使用VTK进行渲染。目前为止都很好。
现在我想为球体模型使用纹理。因此,我将球面坐标转换为纹理坐标,并将其分配给每个点。这适用于大多数球体表面三角形,结果看起来不错。
但是,在本初子午线对面的三角形上,纹理被错误地映射:整个纹理被挤压到单个三角形上,而不是重复纹理并映射“超过纹理边界”。下图显示了它的样子:
图片中的锯齿线显然是错误的,蓝色线应该是可见的。整个纹理被映射到三角形上,导致出现红白条纹。这是有道理的,因为对于问题三角形,纹理坐标跨越整个纹理空间。
为了说明这个问题(这不仅适用于球体,而是所有闭合对象),我创建了以下图像:
在上方矩形中,我们看到一个跨越纹理边界的三角形,具有计算的纹理坐标A、B和C。由于纹理可以平铺,这就是我想要的三角形呈现方式。
下面的三角形显示了当前如何解释纹理坐标。边A、B和C的坐标相同,但是这次,大多数纹理用于三角形,而不是在边界处平铺纹理。
我相信我犯了一个很常见的错误,但我还没有找到任何帮助。你有什么提示吗?

我过去一天左右一直在努力解决这个问题,主要是在检测哪些面有错误方面。结果发现错误的面具有逆时针顺序的纹理坐标。 - 3Dave
3个回答

5
答案很简单,你需要将纹理坐标映射到边缘上。具体实现取决于你的数据集,但这是解决问题的方法。
在计算机图形学中,纹理坐标存储在面上而不是顶点上,你的问题正是这个原因。当你将纹理映射在一个球体上,假设分为10步,你从0.0开始,沿着0.1的增量继续。如果你按照本初子午线的纹理坐标进行映射,你会得到纹理坐标为0.9和0.0的面。图形硬件按照指令执行,并在0.0和0.9之间插值纹理。
要解决你的问题,你需要将纹理从0.9映射到1.0。
如果可以的话,创建这种多边形,或者复制其他纹理坐标的有问题的顶点。

复制一些顶点似乎是目前最实际的解决方案 - 我会尝试一下。谢谢提示。 - Ferdinand Beyer
你能详细说明一下“以那种方式创建多边形”吗?我知道为什么会发生这种情况,但是不得不创建一行退化面来修复接缝似乎很糟糕。 - 3Dave
你并没有创建退化面,这些面是好的,只是你得到了具有纹理坐标0.0和1.0的重复顶点。如果你依赖于连接信息,这是一个问题,但渲染和网格操作是两个不同的事情。 - rioki

2
首先,你可能不想只将球面坐标映射到覆盖球体的单个矩形纹理中,因为在表面上像素分辨率变得非常不均匀。
更好的方法是使用一个图集。 "图集" 是将表面参数化为多个“图表”的过程,每个图表都是一个连通区域。例如,您可以将球映射到大约6个对应于立方体侧面的图表上,每个图表都能更好地保留球的部分形状。您可以搜索多图表参数化或类似内容。如果要使用DirectX,则可以使用内置的UVAtlas生成功能。实际上,在图表之间处理接缝的问题更简单,因为三角形始终位于一个图表中,并且是完全不同的问题。
话虽如此,在你的情况下,为了处理接缝,你需要知道哪些(球形)网格的三角形边界与边界(子午线或其他)相交。然后,您必须将那些与这些边界相交的三角形分成不跨越边界的片段,并正确应用纹理坐标。

感谢您介绍Atlas方法。实际上,我只需要可视化数据,而不是开发游戏或类似的东西,所以我想保持简单。我现在意识到,我必须调整几何图形才能摆脱接缝,我会点赞您的答案,因为它指出了这一点。 - Ferdinand Beyer

2

因为我认为vtk的vtkSphereSource内置方法更简单,所以回答一个很早之前的问题。

你想要"打破"球体,这样你就不会在球体周围0.9和0.0之间得到纹理插值。在Python中,调用sphere.SetEndTheta(360 - 1.e-4),这将实际上从球体中取出一个微小的切片。这给了你纹理映射到1.0的最后一组顶点。


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