【问题标题】:Drawing a Globe with OpenGL ES使用 OpenGL ES 绘制地球
【发布时间】:2011-05-13 05:22:39
【问题描述】:

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

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

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

对于我应该调整哪些参数以获得合适的地球仪有什么想法吗?

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

非常感谢。

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

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

【问题讨论】:

  • 所以你已经将各种边界定义为几何图形,你正在做一些数学运算以将它们的坐标映射到地球表面,然后绘制为 GL_LINES(或线环或其他一些线图元)?你有什么镶嵌的吗?
  • @Tommy:是的。确切地。我将坐标映射到地球表面并使用GL_LINE_STRIP 绘制它们。我什至不知道如何做任何镶嵌... :-)
  • 你能分享你的vxp数据吗?我正在研究类似的问题,但对于 android 平台...

标签: objective-c ios ios4 opengl-es


【解决方案1】:

如果它不妨碍代码的其余部分,显而易见的方法是以不可见的方式将球体绘制为实体对象以填充深度缓冲区,然后让深度测试找出哪条线是可见的。您可以使用 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 获取当前视图矩阵,直接从将它们映射到球体的方式确定每个顶点的法线(它只是它们相对于中心的位置),然后绘制至少一条线vertex 为从相机到该点的向量与法线的点积返回一个负值。

【讨论】:

  • @Tommy:非常感谢您的回答。我用我用来渲染球体的代码更新了这个问题。我添加了您的建议,但我仍然遇到我提到的问题(看到呈现的地球背面线)。这很奇怪,因为当我在常规 OpenGL 中使用类似的代码时,我没有这种效果......
  • 你确定你附加了深度缓冲区吗?
  • @Tommy:感谢您的帮助。我在问题中添加了相关部分。我不知道这是否足够。正如您所料,我正在设置缓冲区、视图和其他相关内容渲染球体和线条之前。
  • 但是你应该有一些地方可以创建帧缓冲区——你肯定在 GL_DEPTH_ATTACHMENT_OES 上附加了一些东西吗?当前 Xcode OpenGL ES 模板附带的 EAGLView 不会创建或附加深度缓冲区。
  • @Tommy:再次感谢。就是这样:我需要使用 glRenderBufferStorage 和 glFramebufferRenderbufferOES 来启用您提到的深度缓冲区...我一直在阅读您的其他 OpenGL 答案。他们都很好。保持良好的 OpenGL 工作! :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多