Буфер глубины OpenGL не использует значение z

У меня есть QtOpenglWidget с запущенным OpenGL 3.3, который пытается выполнить рендеринг экземпляра, но мой z-буфер не работает.

В настоящее время я добавляю 3 тестовых куба в порядке отрисовки куб3, куб2, затем куб1, и изменение его показывает, что он просто отображает последний нарисованный куб. Я также знаю, что DEPTH_TEST включен, так как возня с glDepthFunc просто ничего не покажет.

введите здесь описание изображения

Моя инициализация:

glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

Мой розыгрыш:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Вершина:

layout(location = 0) in highp vec3 position;
layout(location = 1) in highp mat4 modelToWorld;
uniform mat4 MVP;
out highp float DEPTH;

void main() {
    gl_Position = MVP * modelToWorld * vec4(position, 1.0);
    DEPTH = gl_Position.z / 20.0f;
}

Фрагмент:

in highp float DEPTH;
out highp vec4 fColor;
void main() {
   fColor = vec4(DEPTH, DEPTH, DEPTH,1.0);
}

EDIT Я обнаружил, что это может быть проблема QtWidget. Первое, что вызывается в main, это

QSurfaceFormat format;
format.setVersion(3, 3);
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);

person FrickeFresh    schedule 28.12.2017    source источник
comment
У вас вообще есть Z-буфер? Просто включить тест глубины недостаточно — тест глубины ничего не сделает, если в текущем привязанном фреймбуфере нет буфера глубины.   -  person derhass    schedule 29.12.2017
comment
@derhass извините за глупость, но я был под впечатлением z-buffer == тест глубины, а также зачем тогда glDepthFunc(GL_GREATER) удалять все?   -  person FrickeFresh    schedule 29.12.2017
comment
@FrickeFresh: ну, я просто хотел, чтобы вы знали, что вы не можете автоматически предположить, что буфер глубины существует (я не знаю, есть ли в Qt какие-то настройки форматов по умолчанию, которые обеспечивают это). Правильно, если буфера глубины не существует, установка GL_GREATER не должна иметь никакого эффекта. Другая возможность заключается в том, что вы просто проецируете все на одну и ту же плоскость. Вы можете подумать, что исключили это, визуализировав gl_Position.z, но на самом деле значение z, которое будет использовать тест глубины, получено из gl_Position.z / gl_Position.w, и вы могли построить такую ​​проекционную матрицу.   -  person derhass    schedule 29.12.2017
comment
Помимо того, что gl_Position.z / gl_Position.w является константой, я мог бы представить гипотетический случай, когда вы устанавливаете glDepthRange, который отображает все в одно значение, но это действительно очень гипотетически и будет более или менее намеренно нарушать тест глубины, поэтому я не думаю это тот случай.   -  person derhass    schedule 29.12.2017
comment
@derhass Я думаю, что вы попали в цель с gl_Position.z / gl_Position.w, так как все кубики белые независимо от того, я собираюсь снова попытаться обмануть свой MVP   -  person FrickeFresh    schedule 29.12.2017
comment
Ну, вы могли бы включить свои фактические матрицы в вопрос. Я подозреваю, что третья строка матрицы концептуально выглядит как (0 0 a 0), а четвертая строка как (0 0 b 0), что полностью разделяет глубину, проецируя все на z_ndc=a/b. Но вы также можете использовать другие средства для достижения того же эффекта, например, в матрицах модели или представления.   -  person derhass    schedule 29.12.2017


Ответы (1)


После ЧАСОВ отладки и изучения примеров я обнаружил проблему!

Это была эта линия

void MyWidget::resizeGL(int width, int height) {
    ...
    m_projection.perspective(45.0f, width / float(height), 0.0f, 1000.0f);
    ...
}

так должно быть

void MyWidget::resizeGL(int width, int height) {
    ...
    m_projection.perspective(45.0f, width / float(height), 0.1f, 1000.0f);
    ...
}

По-видимому, установка моей проекции с NearPlane на 0 вызывает это. На самом деле я не знаю, ПОЧЕМУ это происходит, поэтому, если вы знаете, просветите меня в комментариях.

Примечание: это класс QMatrix4x4.

person FrickeFresh    schedule 30.12.2017
comment
Я не знаю, что именно делает QMatrix4x4 при указании расстояния ближней плоскости 0,0, но перспективной проекции с таким свойством даже не существует с точки зрения того, как проективные преобразования применяются в конвейере рендеринга - результирующий объем просмотра должен был бы быть бесконечным в пространстве NDC, что полностью противоречит определению объема просмотра как четко определенного выровненного по оси параллелепипеда в пространстве NDC. - person derhass; 30.12.2017