PDA

View Full Version : Problem texturing a sphere with VBO



Alex Sierra
10-29-2011, 11:38 AM
Hi,

I created a sphere by normalizing all vertices of a subdivided cube. I put the data in two arrays, one for the vertices and the other for the indices. To draw it I create the buffers once and call a drawing function every time it's necessary.

const unsigned int num_vertices = 1538;
const unsigned int num_faces = 3072;

GLfloat vertices[] = {
1.000000, -1.000000, -1.000000,
...
-0.875000, 0.875000, -1.000000
};

GLuint faces[] = {
465, 1537, 449,
...
393, 413, 1154
};

void createCube() {
glGenBuffers(1, &vbuffer_id);
glBindBuffer(GL_ARRAY_BUFFER, vbuffer_id);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),
vertices, GL_STATIC_DRAW);
glGenBuffers(1, &ibuffer_id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer_id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(faces),
faces, GL_STATIC_DRAW);
}

void drawCube()
{
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vbuffer_id);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer_id);
glDrawElements(GL_TRIANGLES, 3*num_faces,
GL_UNSIGNED_INT, 0);
}

I use a vertex shader to create on the fly texture coordinates
using the inverse parametric equation of the sphere, which works mostly fine as you can see in the attached image.

gl_TexCoord[0].s = 0.5 + atan(v.z, -v.x)/(2.0*pi);
gl_TexCoord[0].t = 0.5 + asin(v.y)/pi;

The problem with this approach is that it assigns the same s texture coordinate to the leftmost and rightmost vertices in the texture space, which in the model space are actually the same vertices but used for different faces (first and last in a row). That's the cause of the mess you see at the extreme meridian edge.

Using a geometry shader I would know if the triangle is the westmost or the eastmost and then I would be able to correct the texture coordinate but I'm almost sure there's a simpler solution using only vertex and fragment shaders.

Any idea please?

tksuoran
10-31-2011, 04:10 AM
-Store the texture coordinates per vertex
-Duplicate vertices which are on u/v discontinuity. You need to store different u/v value on each copy of the vertex
-For slices and stacks sphere, locating the seam is trivial (simply use for loop which includes both 0 and 1 as u/v)
-For subdivided and normalized sphere generators, you can detect the seam as described in http://sol.gfxile.net/sphere/index.html

"To figure out which, I wrote a routine that scans all the triangles, and duplicates a vertex whenever the u coordinate changes more than 0.25 within one edge. The duplicated u coordinate is decremented by 1.0."

Alex Sierra
11-01-2011, 08:32 PM
Problem solved, thank you very much. Following your advice I rebuilt the mesh duplicating vertices for any conflicting face, including the poles. For the poles I replaced the s (or u) coordinate with the average of the other two vertices.

It is incredible how undocumented is this problem. Is it too obvious?

Anyway I will try the alternative of using the help of a geometry shader, at least to try it out.

mbentrup
11-02-2011, 01:18 AM
You could also compute the texture coordinate in the fragment shader, that would avoid the interpolation issues, but you may get artifacts by mipmapping as the derivate estimates are wrong near the wrap-around meridian.

Or you turn the whole thing around: pass the texture coordinates to the vertex shader and calculate the vertex position from them with sin and cos...