3

I am trying to render a globe (sphere with maps on it) with OpenGL ES 1.1 on iOS.

I am able to draw the sphere, and map borders but with one problem: lines that are not facing front in my view, are also being drawn on the screen. Like this:

Globe with lines on the back being shown

In the picture, you can see that America renders just fine, but you can see Australia rendered on the back. It is not supposed to be shown because it's in the back of the globe, and BLACK and PURPLE stripes in the globe are not transparent.

Any ideas on what parameters should I be tweaking in order to get a proper globe?

If it helps, I can post the relevant parts of the code. Just ask which part and I will update the question.

Thanks a lot in advance.

Update: This is what I am using for Sphere rendering:

glEnableClientState(GL_VERTEX_ARRAY);
glPolygonOffset(-1.0f, -1.0f);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
int x, y;
GLfloat curR, curG, curB;
curR = curG = curB = 0.15f;
for (y=0; y<EARTH_LAT_RES; y++) {
    if (y%10 == 0) {
        glColor4f(curR, curG, curB, 1.0f);
        curR = curR == 0.15f ? 0.6f : 0.15f;
        curB = curB == 0.15f ? 0.6f : 0.15f;
    }
    for (x=0; x<EARTH_LON_RES; x++) {
        Vertex3D vs[4];
        vs[1] = vertices[x][y];
        vs[0] = vertices[x][y+1];
        vs[3] = vertices[x+1][y];
        vs[2] = vertices[x+1][y+1];
        glVertexPointer(3, GL_FLOAT, 0, vs);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    }
}
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDisable(GL_POLYGON_OFFSET_FILL);
glDisableClientState(GL_VERTEX_ARRAY);

This is what I am using to render the border lines:

// vxp is a data structure with vertex arrays that represent
// border lines
int i;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
for (i=0; i<vxp->nFeatures; i++)
{
    glVertexPointer(3, GL_FLOAT, 0, vxp->pFeatures[i].pVerts);
    glDrawArrays(GL_LINE_STRIP, 0, vxp->pFeatures[i].nVerts);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_BLEND);

These are the settings I am using before rendering any of the objects:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glEnable(GL_DEPTH_TEST); /* enable depth testing; required for z-buffer */
glEnable(GL_CULL_FACE); /* enable polygon face culling */ 
glCullFace(GL_BACK);
glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
glFrustumf (-1.0, 1.0, -1.5, 1.5, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Pablo Santa Cruz
  • 176,835
  • 32
  • 241
  • 292
  • So you've got the various borders defined as geometry, you're doing some maths to map their coordinates onto the surface of a globe and then drawing as GL_LINES (or line loop or some other line primitive)? Do you have anything tessellated? – Tommy May 13 '11 at 11:13
  • @Tommy: yes. exactly. I am mapping the coordinates onto the surface of the globe and drawing them with `GL_LINE_STRIP`. I don't even know how to do anything tessellated... :-) – Pablo Santa Cruz May 13 '11 at 11:15
  • could you share you vxp data ? I'm working on similar issue but for android platform... – oleg.semen Feb 03 '14 at 12:07

1 Answers1

5

The obvious way, if it doesn't obstruct the rest of your code, is to draw the sphere as a solid object in an invisible way to prime the depth buffer, then let the depth test figure out which of the lines is visible. You can use glPolygonOffset to add an implementation-specific 'small amount' to values that are used for depth calculations, so you can avoid depth-buffer fighting. So it'd be something like:

// add a small bit of offset, so that lines that should be visible aren't
// clipped due to depth rounding errors; note that ES allows GL_POLYGON_OFFSET_FILL
// but not GL_POLYGON_OFFSET_LINE, so we're going to push the polygons back a bit
// in terms of values written to the depth buffer, rather than the more normal
// approach of pulling the lines forward a bit
glPolygonOffset(-1.0, -1.0);
glEnable(GL_POLYGON_OFFSET_FILL);

// disable writes to the colour buffer
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

drawSolidPolygonalSphere();

// enable writing again
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

// disable the offset
glDisable(GL_POLYGON_OFFSET_FILL);

drawVectorMap();

So that'll leave values in your depth buffer as though the globe were solid. If that's not acceptable, then the only alternative I can think of is to do visibility calculations on the CPU. You can use glGet to get the current view matrix, determine the normal at each vertex directly from the way you map them to the sphere (it'll just be their location relative to the centre), then draw any line for which at least one vertex returns a negative value for the dot product of the vector from the camera to the point and the normal.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • @Tommy: thanks a lot for answering. I updated the question with the code I am using to render the sphere. I added your suggestion, but I am still experiencing the issues I mentioned (seen back-of-the-globe lines rendered). It's weird because when I use similar code in regular OpenGL I don't have this effect... – Pablo Santa Cruz May 13 '11 at 12:00
  • Are you sure you have a depth buffer attached? – Tommy May 13 '11 at 15:18
  • @Tommy: thanks for helping. I added to the question the relevant part. I don't know if that's enough. As you might expect, I am setting the the buffer, the view and other related stuff **before** rendering the sphere and the lines. – Pablo Santa Cruz May 13 '11 at 15:21
  • 1
    But you should have a bit somewhere that creates the framebuffer — are you definitely attaching something to GL_DEPTH_ATTACHMENT_OES? The EAGLView that comes with the current Xcode OpenGL ES template doesn't create or attach a depth buffer. – Tommy May 13 '11 at 15:28
  • @Tommy: wow... that's a **GREAT** suggestion as I am using the current XCode OpenGL ES template... Will take a look at that. – Pablo Santa Cruz May 13 '11 at 15:29
  • 1
    @Tommy: thanks again. That was exactly it: I needed to use glRenderBufferStorage and glFramebufferRenderbufferOES to enable the depth buffer you mentioned... I've been reading your other OpenGL answers. They're all pretty good. Keep up the good OpenGL work! :-) – Pablo Santa Cruz May 13 '11 at 16:45