如何将2D图像纹理正确映射到icosphere

时间:2017-01-31 12:41:20

标签: c++ opengl textures texture-mapping

我正在使用C ++编写一个能够代表地球的简单图形引擎。地球被建模为 icosphere ,我计划使用每个顶点的法线来映射其纹理。为此,我基本上试图从顶点法线获得垂直和水平坐标(分别为φ和θ)(即纬度和经度)。

以下是实现我的方法的(编辑的)函数(在生成新顶点时调用)。当参数(0,0)是法线向量时,它应该将纹理坐标从(1,1)返回到n

glm::vec2 Icosphere::getTexCoord(glm::vec3 n)
{
    float theta = (atan2f(n.x, n.z) / PI) / 2.f + 0.5f;
    float phi = (asinf(-n.y) / (PI / 2.f)) / 2.f + 0.5f;
    return glm::vec2(theta, phi);
}

但是,这会产生意想不到的结果。使用this test image,我的icosphere看起来像这样:

Example 1

Example 2

小的白色和红色三角形位于(x,y,z) = (1,0,0)。在第一张图像中,我生成了具有较少三角形面(320)的icosphere,而在后者中,使用~82k三角形生成了icosphere。

我怀疑导致这些纹理“毛刺”的原因是坐标(0,*)(1,*)不被认为是相邻的。有没有正确的方法呢?

注意:这些是我的纹理参数:

/* Configure texture parameters: */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);

1 个答案:

答案 0 :(得分:1)

我终于设法克服了这种丑陋的纹理映射。问题确实是由于在一个球体中三角形的特征非均匀取向造成的。在一个icosphere(以及一个二十面体)中,不可能在原点(0,0,0)中找到一个不与任何三角形相交的平面。如果我们想到地球,这意味着它的所有子午线都会与某些三角形相交。这也意味着在映射纹理时,位于纹理垂直边缘的三角形(即tex.coord。(1,y)(0,y))将在其中一侧具有一些顶点。发生这种情况时,纹理会从x≈1插入到x≈0,从而产生我的图像中显示的效果。

为了解决这个问题,我将纹理包裹设置为GL_REPEAT,并简单地强制一些顶点远离纹理坐标空间(即x > 1)。这允许纹理边缘相邻并完美地映射纹理:

/* Configure texture parameters: */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Not GL_CLAMP_TO_EDGE.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Not GL_CLAMP_TO_EDGE.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);

结果:

修改边缘中三角形的纹理坐标(使用GL_CLAMP_TO_EDGE):

Result1

将纹理参数更改为GL_REPEAT

enter image description here