3

Artifact on longitude

I am UV mapping a 2D Texture on a 3d sphere X, Y, Z coordinates, by using the formula

u = (0.5 + atan2(X, Y) / (2 * glm::pi<double>()));
v = (0.5 - asin(Z) / glm::pi<double>());

in modern openGL C++.

I dont know why there is this artifact in the sphere. Cant figure it out.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
abstractnature
  • 456
  • 2
  • 9
  • I have only noticed that this artifact becomes thinner if I increase the number of divisions and complexity of the sphere by adding more vertices. But it is still there. – abstractnature Oct 24 '17 at 21:49
  • 4
    The artifacts happens at the flip-over point of the texture coordinates (the face where they go back from 1 to 0. The only way how you can solve that is to duplicate one ring of vertices where this happens. Assign then a texture coordinate of 0 to one circle and 1 to the other circle. Note, that you also have to adjust the indices. – BDL Oct 24 '17 at 22:24
  • 1
    @BDL Thanks, so this means at flip over point, fragment shader interpolates in backward direction and clamps all of the data in that one longitude? – abstractnature Oct 24 '17 at 22:26
  • Yes, exactly :) – BDL Oct 24 '17 at 23:15

2 Answers2

1

Ok, I have figured and corrected this out, thought I will answer here finally now.

Big thanks to BDL and Rabbid76.

Whenever u == 0, I added the same vertex position (X Y Z) to the vertices vector (or array) and also increased the index, but hardcoding the texture u to be 1.0f this time.

No issues now, the seam looks perfect now.

abstractnature
  • 456
  • 2
  • 9
  • Could you clarify or show some code..? I don't understand what you mean by adding the same vertex positions.. – Sti Mar 08 '20 at 19:59
0

This is detail of a textured sphere geometry which is indexed. You should use index for better performance: m_meridians and m_latitudes are detail level of sphere.

for (size_t i = 0; i < m_meridians + 1; i++)
{
    for (size_t j = 0; j < m_latitudes + 2; j++)
    {
        // texCoord in the range [(0,0), (1,1)]
       QVector2D texCoord((float)i / m_meridians, (float)j / (m_latitudes+1));
        // theta = longitude from 0 to 2pi
        // phi = latitude from -pi/2 to pi/2
        double theta, phi;
        theta = 2*M_PI * texCoord.x();
        phi = M_PI * texCoord.y() - M_PI_2;
        QVector3D pos;
        pos.setY((float)std::sin(phi));
        pos.setX((float)std::cos(phi) * std::cos(theta));
        pos.setZ((float)std::cos(phi) * std::sin(theta));

        m_vertices.push_back({pos, texCoord});
    }
}

// Calculate triangle indices

for (size_t i = 0; i < m_meridians; i++)
{
    // Construct triangles between successive meridians
    for (size_t j = 0; j < m_latitudes + 1; j++)
    {
        m_indices.push_back(i * (m_latitudes+2) + j);
        m_indices.push_back(i * (m_latitudes+2) + j+1);
        m_indices.push_back((i+1) * (m_latitudes+2) + j+1);

        m_triangleCount++;

        m_indices.push_back((i+1) * (m_latitudes+2) + j+1);
        m_indices.push_back((i+1) * (m_latitudes+2) + j);
        m_indices.push_back(i * (m_latitudes+2) + j);

        m_triangleCount++;
    }
}
Karoshi
  • 29
  • 1
  • 7
  • If you write an answer, you should also explain what the initial problem was and why your code solves it. Just posting code isn't helpful for future visitors. – BDL Oct 25 '17 at 09:07