Рисование глобуса с помощью OpenGL ES - PullRequest
3 голосов
/ 13 мая 2011

Я пытаюсь отобразить глобус (шар с картами на нем) с OpenGL ES 1.1 на iOS.

Я могу нарисовать сферу и нанести на карту границы, но с однимпроблема: линии, которые не смотрят спереди на мой взгляд, также рисуются на экране .Например:

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 Ответ

5 голосов
/ 13 мая 2011

Очевидный способ, если он не мешает остальной части вашего кода, это нарисовать сферу как сплошной объект невидимым способом, чтобы заполнить буфер глубины, а затем позвольте тесту глубины выяснить, какая из линий является видимый. Вы можете использовать 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();

Так что это оставит значения в вашем буфере глубины, как если бы глобус был сплошным. Если это неприемлемо, то единственная альтернатива, которую я могу придумать, - это выполнить вычисления видимости на процессоре. Вы можете использовать glGet, чтобы получить текущую матрицу вида, определить нормаль в каждой вершине непосредственно от того, как вы отображаете их на сферу (это будет просто их расположение относительно центра), а затем нарисовать любую линию, для которой хотя бы один вершина возвращает отрицательное значение для точечного произведения вектора из камеры в точку и нормаль.

...