Как вывести многоугольник на передний план в OpenGL? - PullRequest
4 голосов
/ 09 июля 2019

Код ниже создает 2 квадратных многоугольника, красный и зеленый.
Я пытаюсь поставить красный квадрат поверх зеленого, но не могу.
Буфер глубины объявлен, очищен при необходимости, ортогональная система настроена правильно.
Если я укажу значение вне диапазона (2; -2), полигон исчезнет, ​​как и должно быть.

#include <...>

constexpr auto FPS_RATE = 120;
int windowHeight = 600, windowWidth = 600, windowDepth = 600;

void init();
void idleFunction();
void displayFunction();
double getTime();

double getTime()
{
  using Duration = std::chrono::duration<double>;
  return std::chrono::duration_cast<Duration>(
    std::chrono::high_resolution_clock::now().time_since_epoch()
    ).count();
}

const double frame_delay = 1.0 / FPS_RATE;
double last_render = 0;

void init()
{
  glutDisplayFunc(displayFunction);
  glutIdleFunc(idleFunction);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, 2, -2);
  glClearColor(0.0, 0.0, 0.0, 0.0);
}

void idleFunction()
{
  const double current_time = getTime();
  if ((current_time - last_render) > frame_delay)
  {
    last_render = current_time;
    glutPostRedisplay();
  }
}

void displayFunction()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  //move the red square to the foreground
  glTranslatef(-32.5, -32.5, 2);
  glColor3f(1, 0, 0);
  glBegin(GL_POLYGON);
  glVertex3i(-150, 150, 0);
  glVertex3i(150, 150, 0);
  glVertex3i(150, -150, 0);
  glVertex3i(-150, -150, 0);
  glEnd();
  glPopMatrix();
  glPushMatrix();
  //move the green square to the background
  glTranslatef(32.5, 32.5, -2);
  glColor3f(0, 1, 0);
  glBegin(GL_POLYGON);
  glVertex3i(-150, 150, 0);
  glVertex3i(150, 150, 0);
  glVertex3i(150, -150, 0);
  glVertex3i(-150, -150, 0);
  glEnd();
  glPopMatrix();
  glutSwapBuffers();
}

int main(int argc, char* argv[])
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
  glutInitWindowSize(windowWidth, windowHeight);
  glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) - windowWidth) / 2, (GetSystemMetrics(SM_CYSCREEN) - windowHeight) / 2);
  glutCreateWindow("Window");
  init();
  glutMainLoop();
  return 0;
}

1 Ответ

4 голосов
/ 09 июля 2019

Вы должны включить Проверка глубины :

glEnable( GL_DEPTH_TEST );

Функция проверки глубины по умолчанию (glDepthFunc) - < (GL_LESS).
Если расстояние до дальней плоскости равно 2,0, а геометрия рисуется с координатой z 2,0, то геометрия ограничивается дальней плоскостью, поскольку глубина геометрии не меньше глубины инициализации буфера глубины.

Измените функцию глубины на <= (GL_LEQUAL):

glDepthFunc( GL_LEQUAL );

В Правосторонней системе Z-ось пространства просмотра направлена ​​за пределы области просмотра. Поэтому, если координата z «меньше», то объект находится «позади» другого объекта.

Матрица проекции преобразуется из пространства просмотра в нормализованное пространство устройства. По сравнению с пространством просмотра нормализованное пространство устройства представляет собой левостороннюю систему, где ось z указывает в области просмотра. Нормализованная координата z устройства в диапазоне [-1, 1] (спереди назад) отображается на значение глубины (обычно в диапазоне [0, 1]), которое используется для проверки глубины.
Чтобы справиться с этим, glOrtho инвертирует ось z, если параметр near установлен меньше, чем параметр far (именно так предлагается функция будет использоваться).
Это приводит к тому, что порядок глубины (z) не изменяется, когда геометрия преобразуется из пространства просмотра формы в нормализованное пространство устройства.

Примечание: glOrtho(-w, w, -h, h, -z, z) совпадает с glScaled(1.0/w, 1.0/h, -1.0/z)

Поскольку в вашем примере ось z не инвертирована ортографической проекцией, потому что около > далеко ,

glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, 2, -2);

координата z должна быть больше, чтобы быть "позади".

Если зеленый прямоугольник должен быть позади красного, то вы должны изменить ортографическую проекцию ( около <<em> далеко ). e.g.:

glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, -2, 2);

Если вы не хотите менять проекцию, вам нужно поменять координаты z геометрии:

glPushMatrix();
//move the red square to the foreground
glTranslatef(-32.5, -32.5, -2.0); // foreground because near > far
// ...
glPopMatrix();

glPushMatrix();
//move the green square to the background
glTranslatef(32.5, 32.5, 2.0);   // background because near > far
// ...
glPopMatrix();
...