OpenGL:Как определить, закрыта ли 3D (визуализированная) точка другими 3D (визуализированными) примитивами перед ней?

StackOverflow https://stackoverflow.com/questions/1311869

  •  19-09-2019
  •  | 
  •  

Вопрос

В моей программе OpenGL я делаю следующее в последовательности:

// Drawing filled polyhedrons
// Drawing points using GL_POINTS
// Displaying information for each above point beside it

Для отображения информации о точке (скажем, идентификатора / номера точки) я преобразую 3D-координаты точки в 2D-координаты окна, используя Глюпроект().Я записываю идентификатор точки в этом местоположении 2D-окна, используя Гластерпос() и код рендеринга 2D-символов.

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

Как определить, закрыта ли 3D (визуализированная) точка другими 3D (визуализированными) примитивами перед ней?Или есть лучший способ отобразить текст информации о точке рядом с ним Только когда она не закрыта?

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

Это было полезно?

Решение

Если вы не готовы использовать второй проход запроса перекрытия, вы можете попробовать выборку Z-буфера для сравнения с вашей тестовой точкой.

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

Это, конечно, требует, чтобы вы отобразили всю свою геометрию перед текстом, но это не должно быть проблемой.

Пример кода:

// Assumed to already hold 3D coordinates of point
GLdouble point3DX, point3DY, point3DZ;

// Project 3D point coordinates to 2D
GLdouble point2DX, point2DY, point2DZ;  // 2D coordinates of point
gluProject( point3DX, point3DY, point3DZ,
            mMatrix, pMatrix, vMatrix,      // MVP matrices
            &point2DX, &point2DY, &point2DZ);

// Read depth buffer at 2D coordinates obtained from above
GLfloat bufDepth = 0.0;
glReadPixels(   static_cast<GLint>( point2DX ), static_cast<GLint>( point2DY ),     // Cast 2D coordinates to GLint
                1, 1,                                                               // Reading one pixel
                GL_DEPTH_COMPONENT, GL_FLOAT,
                &bufDepth);

// Compare depth from buffer to 2D coordinate "depth"
GLdouble EPSILON = 0.0001;  // Define your own epsilon
if (fabs(bufDepth - point2DZ) < EPSILON)
    // 3D point is not occluded
else
    // 3D point is occluded by something

Другие советы

Чтение из z-буфера может быть очень-очень медленным на современном оборудовании.Вот почему был изобретен окклюзионный запрос.Посмотрите расширение ARB-occlusion-query.У него есть задержка на пару кадров, прежде чем вы сможете получить результаты, но это не повлияет на вашу производительность.

Если запрос перекрытия по какой-либо причине не сработает, следующий запасной вариант - выполнить программную операцию пересечения лучей с миром, используя BSP-tree (которая вообще не использует GL).

В дополнение к ответу Алана, вы могли бы проверить наличие окклюзии математически, проецируя луч из положения вашей камеры в вашу точку и определяя, пересекает ли он какую-либо вашу геометрию.В Интернете есть множество ссылок на проведение тестирования пересечения лучей и объектов (см., например, Объект/ Страница пересечения объектов).Если у вас много геометрии, то вы можете ускорить процесс, используя ограничивающие объемы или дерево BSP.

В качестве бонуса, ваш код перекрытия должен быть намного проще для модульного тестирования, потому что он не зависит от извлечения значений из OpenGL.

Ответ от Эшвина Нанджаппы был очень полезен.Я не эксперт по OpenGL, поэтому мне потребовалось некоторое время, чтобы выяснить, как получить матрицы MVP.Я делюсь кодом здесь, чтобы дополнить его пост:

    GLint viewport[4];
    GLdouble modelview[16];
    GLdouble projection[16];
    glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
    glGetDoublev( GL_PROJECTION_MATRIX, projection );
    glGetIntegerv( GL_VIEWPORT, viewport );
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top