# Sphere Texture Mapping shows visible seams

As you can see from the above picture there is a visible seam in the texture mapping. The underlying mesh is a geosphere based on octahedron subdivisions. On that particular latitude, vertices have been duplicated. However there still is a visible seam.

Here is how I calculate the UV coordinates:

float longitude = (float)Math.Atan2(normal.X, -normal.Z);
float latitude = (float)Math.Acos(normal.Y);

float u = (float)(longitude / (Math.PI * 2.0) + 0.5);
float v = (float)(latitude / Math.PI);


Is this a problem in the coordinates or a mipmapping issue?

Edit: the GeoSphere is generated using SharpDX's Toolkit code. My SamplerState is set to Clamp. Further, I am using a normal mapping shader.

Could it be that the tangent of the duplicated vertices needs to be altered? I am using a Vector4 element for it, where w is the handedness. If so, how should it be modified?

Edit2: this is the code used to duplicate the vertices along the seam

int preCount = vertices.Count;
var indicesArray = indexList.ToArray();
fixed (void* pIndices = indicesArray)
{
indices = (int*)pIndices;

for (int i = 0; i < preCount; ++i)
{
// This vertex is on the prime meridian if position.x and texcoord.u are both zero (allowing for small epsilon).
bool isOnPrimeMeridian = MathUtil.WithinEpsilon(vertices[i].Position.X, 0, XMVectorSplatEpsilon)
&& MathUtil.WithinEpsilon(vertices[i].TextureCoordinate.X, 0, XMVectorSplatEpsilon);

if (isOnPrimeMeridian)
{
int newIndex = vertices.Count;

// copy this vertex, correct the texture coordinate, and add the vertex
VertexPositionNormalTexture v = vertices[i];
v.TextureCoordinate.X = 1.0f;

// Now find all the triangles which contain this vertex and update them if necessary
for (int j = 0; j < indexList.Count; j += 3)
{
var triIndex0 = &indices[j + 0];
var triIndex1 = &indices[j + 1];
var triIndex2 = &indices[j + 2];

if (*triIndex0 == i)
{
// nothing; just keep going
}
else if (*triIndex1 == i)
{
Utilities.Swap(ref *triIndex0, ref *triIndex1);
Utilities.Swap(ref *triIndex1, ref *triIndex2);
}
else if (*triIndex2 == i)
{
Utilities.Swap(ref *triIndex0, ref *triIndex2);
Utilities.Swap(ref *triIndex1, ref *triIndex2);
}
else
{
// this triangle doesn't use the vertex we're interested in
continue;
}

// check the other two vertices to see if we might need to fix this triangle
if (Math.Abs(vertices[*triIndex0].TextureCoordinate.X - vertices[*triIndex1].TextureCoordinate.X) > 0.5f ||
Math.Abs(vertices[*triIndex0].TextureCoordinate.X - vertices[*triIndex2].TextureCoordinate.X) > 0.5f)
{
// yep; replace the specified index to point to the new, corrected vertex
indices[j + 0] = newIndex;
}
}
}
}

FixPole(northPoleIndex);
FixPole(southPoleIndex);

// Clear indices as it will not be accessible outside the fixed statement
indices = (int*)0;
}

• More info please, what is your texture sampler state? Are you using an indexed mesh and how are you calculating it? – MickLH May 31 '14 at 18:18
• I just added some additional information. – TheWanderer May 31 '14 at 20:15
• You need the u value to be 0.0 on one side of the seam and 1.0 on the other side. It doesn't look like the UV generation code you posted will do that, since it's based on the normal, and the normal should be the same on both sides of the seam. (BTW, you can easily tell if it's a mipmapping issue by disabling mipmaps.) – Nathan Reed Jun 1 '14 at 1:24
• Yes, the code that duplicates the vertices runs after the generation of the initial vertices. I just added the code used to duplicate the vertices along the seam. – TheWanderer Jun 1 '14 at 10:55
• @AvengerDr OK, that looks reasonable, but there are enough details that it's hard to be sure it's right from looking at the code. Have you verified that all the seam vertices are detected correctly? Have you stepped through in a debugger and verified that it's generating the UVs you expect? – Nathan Reed Jun 1 '14 at 22:32

return tex2Dlod(TextureSampler, float4(u, v, 0, 0));