使用OpenGL ES绘制地球仪

时间:2011-05-13 05:22:40

标签: objective-c ios ios4 opengl-es

我正在尝试在iOS上使用 OpenGL ES 1.1 渲染地球仪(带有地图的球体)。

我能够绘制球体,并绘制边框但有一个问题:在我的视图中不面向前方的线条也在屏幕上绘制。像这样:

Globe with lines on the back being shown

在图片中,你可以看到美国渲染得很好,但你可以看到澳大利亚在后面渲染。它不应该被显示,因为它位于地球的后面,并且地球上的黑色和紫色条纹不透明。

为了获得合适的地球,我应该调整哪些参数?

如果有帮助,我可以发布代码的相关部分。只要询问哪个部分,我就会更新问题。

提前多多感谢。

更新:这是我用于球体渲染的内容:

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);

这就是我用来渲染边框线的内容:

// 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);

这些是我在渲染任何对象之前使用的设置:

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();

1 个答案:

答案 0 :(得分:5)

显而易见的是,如果它不妨碍你的其余代码,就是以一种不可见的方式将球体绘制成一个实体对象来填充深度缓冲区,然后让深度测试找出哪条线是可见。您可以使用glPolygonOffset将特定于实现的“少量”添加到用于深度计算的值,这样您就可以避免深度缓冲区争用。所以它就像是:

// 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();

这样就可以在深度缓冲区中保留值,就好像地球是实心的一样。如果这是不可接受的,那么我能想到的唯一选择就是在CPU上进行可见性计算。您可以使用glGet获取当前视图矩阵,直接从您将它们映射到球体的方式确定每个顶点的法线(它只是它们相对于中心的位置),然后绘制任何至少一个的线顶点返回从摄像机到点和法线的矢量点积的负值。