2011-05-13 99 views
3

我想在iOS上用OpenGL ES 1.1呈现地球仪(球体上有地图)。用OpenGL ES绘制地球仪

我可以绘制球体,并映射边界,但有一个问题:在我看来并不面向前方的线条也正在屏幕上绘制。就像这样:

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

因此,您已将各种边界定义为几何,您正在做一些数学将其坐标映射到地球表面,然后绘制为GL_LINES(或线循环或其他线基元)?你有什么镶嵌的东西吗? – Tommy 2011-05-13 11:13:29

+0

@Tommy:是的。究竟。我将坐标映射到地球表面并使用GL_LINE_STRIP绘制它们。我甚至不知道如何做镶嵌... :-) – 2011-05-13 11:15:27

+0

你能分享你的vxp数据吗?我正在处理类似的问题,但对于Android平台... – 2014-02-03 12:07:06

回答

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获取当前的视图矩阵,直接从您将它们映射到球体的方式(它将只是它们相对于中心的位置)确定每个顶点的法线,然后绘制任何至少有一个线的线顶点返回从相机到点和法线的矢量点积的负值。

+0

@Tommy:非常感谢您的回答。我用我用来渲染球体的代码更新了这个问题。我添加了你的建议,但是我仍然遇到了我提到的问题(可以看到回显的全球线条)。这很奇怪,因为当我在普通的OpenGL中使用类似的代码时,我没有这种效果...... – 2011-05-13 12:00:23

+0

你确定你有一个深度缓冲区? – Tommy 2011-05-13 15:18:23

+0

@Tommy:谢谢你的帮助。我在相关部分中添加了这个问题。我不知道这是否足够。正如你所期望的那样,在渲染球体和线条之前,我正在设置缓冲区,视图和其他相关的东西**。 – 2011-05-13 15:21:09