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

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

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

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

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

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

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

Ответы [ 4 ]

3 голосов
/ 21 августа 2009

Если вы не хотите использовать второй проход запроса окклюзии, вы можете попробовать выполнить выборку из 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
2 голосов
/ 25 августа 2009

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

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

2 голосов
/ 24 августа 2009

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

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

0 голосов
/ 10 мая 2018

Ответ от Эшвина Нанджаппы был очень полезным. Я не эксперт 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 );
...