c++ - 如何正确地将 2D 图像纹理映射到 icosphere

标签 c++ opengl textures texture-mapping

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

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

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) 的棱角球,而在后者中,生成的棱角球具有约 82k 个三角形。

我怀疑导致这些纹理“故障”的原因是坐标 (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);

最佳答案

我终于设法克服了这个丑陋的纹理映射。这个问题确实是由 icosphere 中三角形的特征不均匀方向引起的。在 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

关于c++ - 如何正确地将 2D 图像纹理映射到 icosphere,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41957890/

相关文章:

C++如何扩展/因式分解方程(不求解)

c++ - unique_ptr 如何同时支持 "dot"和 "arrow"调用以及未定义的方法?

c++ - 如何在 GTK3 上强制使用 CORE opengl 配置文件? (#version 330)

c - 使用 Glut 和 C 时纹理扭曲

android - Samsung Gear VR - 可以用 C++ 开发吗?

c++ - Windows 鼠标坐标 VS OpenGL 鼠标坐标

c++ - 如何在 glRotatef 中使用 glm::mat4

linux - 与 Linux 上的 GLUT 共享上下文

ios - 在 SKSpriteNode 上叠加两个纹理

C++ - 连续检查 3