Z-бои после глубокой подготовки на GTX 980

Я реализую глубинный подготовительный в OpenGL. На Intel HD Graphics 5500 этот код работает нормально, а на Nvidia GeForce GTX 980 - нет (на рисунке ниже показан результат z-боя). Я использую следующий код для генерации изображения. (Все, что не имеет отношения к проблеме, опущено.)

// ----------------------------------------------------------------------------
// Depth Prepass
// ----------------------------------------------------------------------------

glEnable(GL_DEPTH_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);

glUseProgam(program1); // The problem turned out to be here!

renderModel(...);

// ----------------------------------------------------------------------------
// Scene Rendering
// ----------------------------------------------------------------------------

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_FALSE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

glUseProgam(program2); // The problem turned out to be here!

renderModel(...);

Похоже, что glDepthFunc не изменился на GL_LEQUAL , Тем не менее, когда я перехожу через вызовы GL в RenderDoc, glDepthFunc установлен правильно.

Похоже ли это на ошибку драйвера или у вас есть предложения, что я могу делать не так? Когда это ошибка драйвера, как я могу реализовать предварительный анализ глубины?

Z-файтинг на Nvidia GeForce GTX 980

2 ответа

Решение

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

Разница объясняется GLSL-спецификацией 4.4:

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

В этом случае классификатор используется следующим образом:

invariant gl_Position;

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

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

fWorldPosition = ModelMatrix*vPosition; // World position to the fragment shader
gl_Position = ProjectionMatrix*ViewMatrix*fWorldPosition;

Вершинный шейдер программы для препасса вычисляется gl_Position в одном выражении:

gl_Position = ProjectionMatrix*ViewMatrix*ModelMatrix*vPosition;

Изменив это на:

vec4 worldPosition = ModelMatrix*vPosition;
gl_Position = ProjectionMatrix*ViewMatrix*worldPosition;

Я решил проблему.

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

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

Другие вопросы по тегам