我有一个地球的纹理,我想要映射到一个球体上。 因为它是一个单位球体而且模型本身没有纹理坐标,所以我能想到的最简单的方法就是计算每个顶点的球面坐标并将它们用作纹理坐标。
textureCoordinatesVarying = vec2(atan(modelPositionVarying.y, modelPositionVarying.x)/(2*M_PI)+.5, acos(modelPositionVarying.z/sqrt(length(modelPositionVarying.xyz)))/M_PI);
在片段着色器中执行此操作时,这可以正常工作,因为我从(插值的)顶点位置计算纹理坐标。
但是当我在顶点着色器中执行此操作时,如果模型本身具有纹理坐标,我也会这样做,我得到的结果如下图所示。顶点显示为点,低于0.5的纹理坐标(u)为红色,而其他所有为蓝色。
因此看起来两个相邻的红色/蓝色顶点的纹理坐标(u)具有值(几乎)1.0和0.0。然后可变地进行平滑插值,因此产生介于0.0和1.0之间的值。这当然是错误的,因为值应该是1.0或0.0,但两者之间没有任何内容。
有没有办法使用球面坐标作为纹理坐标而不会获得上面显示的那些效果? (如果可能,不改变模型)
答案 0 :(得分:4)
这是一个常见问题。两个纹理坐标拓扑之间的接缝,您希望纹理坐标从1.0无缝地换行到0.0,这需要网格正确处理它。为此,网格必须沿着接缝复制每个顶点。其中一个顶点将具有0.0纹理坐标,并将连接到来自右侧的顶点(在您的示例中)。另一个将具有1.0纹理坐标,并将连接到左侧的顶点(在您的示例中)。
这是一个网格问题,最好在网格本身中解决它。相同的位置需要两个不同的纹理坐标,因此您必须复制相关位置。
或者,您可以让片段着色器从插值顶点法线生成纹理坐标。当然,这在计算上更加昂贵,因为它需要从一个方向转换到一对角度(然后到[0,1]纹理坐标范围)。