Тест глубины инвертирован по умолчанию в OpenGL, или я ошибся? - PullRequest
3 голосов
/ 16 ноября 2010

Я играл с OpenGL целую неделю или эквивалент.После 2D я сейчас пробую 3D.Я хочу воспроизвести 3D-сцену, которую вы можете увидеть в третьем видео на http://johnnylee.net/projects/wii/.
Мне было трудно заставить все работать должным образом с текстурами и глубиной.

У меня недавно было 2 проблемыкоторые визуально имеют несколько одинаковое воздействие:

  • Один с текстурами, которые не очень хорошо сочетаются в 3D, с использованием техник, которые я нашел для 2D.
  • Один с объектами, которые отображаются снизу вверх,Как проблема, описанная здесь: Буфер глубины в OpenGL

Я решил обе проблемы, но я хотел бы знать, правильно ли я все понял , специально для второго пункта .

Для первого , я думаю, он у меня есть.У меня есть изображение круглой цели с альфой для всего, что находится за пределами диска.Он хорошо загружен внутри OpenGL.Некоторые (из-за моей проблемы z-упорядочения) другие цели позади него страдали от того, что были скрыты прозрачными областями квадрата естественного квадрата, который я использовал для его рисования.

Причина этого состояла в том, что каждая часть текстурыпредполагается, что он полностью непрозрачен с учетом буфера глубины.Использование glEnable(GL_ALPHA_TEST) с тестом для glAlphaFunc(GL_GREATER, 0.5f) заставляет альфа-слой текстуры действовать как индикатор непрозрачности (булево) и, таким образом, делает смешивание совершенно бесполезным (потому что мое изображение имеет логическую прозрачность).

Дополнительный вопрос: Кстати, есть ли способ указать источник альфа-теста, отличный от альфа-слоя, используемого для смешивания?

Второй , я нашел решение моей проблемы.Перед очисткой буфера цвета и глубины я установил глубину по умолчанию 0 glClearDepth(0.0f), и я использовал "большую" функцию глубины glDepthFunc(GL_GREATER).

Что мне кажется странным, так это то, что глубинаравен 1.0, а функция глубины по умолчанию «меньше» GL_LESS.Я в основном инвертирую это, чтобы мои объекты не отображались в перевернутом виде ...

Я нигде не видел такого взлома, но, с другой стороны, я не видел, чтобы объекты систематически рисовались внеправильный порядок, независимо от того, в каком порядке я их рисую !

Хорошо, вот фрагмент кода (урезанный, надеюсь, не слишком много), который сейчас работает так, как я хочу:

    int main(int argc, char** argv) {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
        glutInitWindowSize(600, 600); // Size of the OpenGL window
        glutCreateWindow("OpenGL - 3D Test"); // Creates OpenGL Window
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);

        PngImage* pi = new PngImage(); // custom class that reads well PNG with transparency
        pi->read_from_file("target.png");
        GLuint texs[1];
        glGenTextures(1, texs);
        target_texture = texs[0];
        glBindTexture(GL_TEXTURE_2D, target_texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, pi->getGLInternalFormat(), pi->getWidth(), pi->getHeight(), 0, pi->getGLFormat(), GL_UNSIGNED_BYTE, pi->getTexels());

        glutMainLoop(); // never returns!
        return 0;
    }

    void reshape(int w, int h) {
        glViewport(0, 0, (GLsizei) w, (GLsizei) h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(-1, 1, -1, 1);
        gluPerspective(45.0, w/(GLdouble)h, 0.5, 10.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }

    void display(void) {
        // The stared *** lines in this function make the (ugly?) fix for my second problem
        glClearColor(0, 0, 0, 1.00);
        glClearDepth(0);          // ***
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glShadeModel(GL_SMOOTH);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_DEPTH_FUNC);  // ***
        glDepthFunc(GL_GREATER);  // ***

        draw_scene();

        glutSwapBuffers();
        glutPostRedisplay();
    }

    void draw_scene() {
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(1.5, 0, -3, 0, 0, 1, 0, 1, 0);

        glColor4f(1.0, 1.0, 1.0, 1.0);
        glEnable(GL_TEXTURE_2D);
        // The following 2 lines fix the first problem
        glEnable(GL_ALPHA_TEST);       // makes highly transparent parts
        glAlphaFunc(GL_GREATER, 0.2f); // as not existent/not drawn
        glBindTexture(GL_TEXTURE_2D, target_texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        // Drawing a textured target
        float x = 0, y = 0, z = 0, size = 0.2;
        glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x-size, y-size, z);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x+size, y-size, z);
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x+size, y+size, z);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x-size, y+size, z);
        glEnd();
        // Drawing an textured target behind the other (but drawn after)
        float x = 0, y = 0, z = 2, size = 0.2;
        glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(x-size, y-size, z);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f(x+size, y-size, z);
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f(x+size, y+size, z);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(x-size, y+size, z);
        glEnd();
    }

Ответы [ 4 ]

4 голосов
/ 16 ноября 2010

Обычно значение глубины очистки равно 1 (фактически бесконечность), а функция прохода глубины - МЕНЬШЕ, потому что вы хотите смоделировать реальный мир, в котором вы видите вещи, стоящие перед вещами, стоящими за ними.Очистив буфер глубины до 1, вы, по сути, говорите, что все объекты ближе, чем максимальная глубина, должны быть нарисованы.Изменение этих параметров обычно не то, что вы хотели бы сделать, если вы действительно не понимаете, что делаете.

С параметрами камеры, которые вы передаете gluLookAt, и позициями ваших объектов, квадратик z = 2 будетдальше от камеры, чем объект z = 0.Что вы пытаетесь сделать так, чтобы это не казалось правильным?

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

Также обратите внимание, что при настройке матрицы перспективы вы можете получить странное поведение.Обычно вы называете gluOrtho ИЛИ gluPerspective.Но не оба.Это умножит две разные матрицы перспективы вместе, что, вероятно, не то, что вы хотите.

0 голосов
/ 15 июня 2016

Формулы, реализованные в стандартной карте функций glOrtho, от zNear до -1 и zFar до 1, которые по умолчанию отображаются на координаты окна как [0,1] (можно изменить с помощью glDepthRange для фиксированного конвейера, не уверен, что эта функция все еще поддерживается) , Тест глубины действительно работает в этих условиях. Чтобы обойти это, просто предположите, что zNear находится дальше всего от плоскости проекции, или сгенерируйте матрицу самостоятельно, которая в любом случае понадобится, если вы хотите избавиться от устаревшего конвейера.

0 голосов
/ 08 декабря 2010

Относительно второй проблемы: вполне вероятно, что-то не так с вашей матрицей modelViewProjection.

У меня была такая же проблема (и я мог бы "исправить" ее вашим хаком), которая была вызвана тем, что я использовалматрица, которая была как-то странно неправильно.Я решил, что реализую свое собственное поколение матриц.

0 голосов
/ 16 ноября 2010

Дополнительный вопрос: Кстати, есть ли способ указать источник альфа-теста, отличный от альфа-слоя, используемого для смешивания?

Да, если вы используете шейдерВы можете сами вычислить альфа-значение выходного фрагмента.

...