OpenGL (4.2) обработка фрагментов & буфер глубины & imageLoadAndStore
У меня есть двухпроходный рендеринг. в первом проходе я визуализирую некоторую непрозрачную геометрию с помощью FBO в несколько текстур.
Во втором проходе я снова визуализирую ту же геометрию и основываюсь на различных свойствах геометрии (например, объект, нормаль и т. д.) я записываю вычисленные значения цветов из pass 1 в определенные текселы некоторых текстур с помощью imageStore () (image_load_and_store)
Я хочу, чтобы это произошло только для видимых фрагментов, однако (только те, которые соответствуют окончательному фрагментные цвета прохода 1)
Поэтому сейчас я пытаюсь взять текстуру GL_DEPTH_ATTACHMENT из прохода 1 и прикрепить ее к fbo из прохода 2 (также как GL_DEPTH_ATTACHMENT) , а затем перед прохождением рендеринга 2 я устанавливаю
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
glDepthMask(false);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
...render my scene...
И я ожидаю, что шейдер фрагментов (который использует imageStore ()) будет выполняться только для тех фрагментов, которые были видны в проходе 1 (и поскольку это та же сцена, которую я рендерю, также в проходе 2).
Но это, кажется, не работает-скрытые фрагменты тоже обрабатываются и выполните imageStore () (и так как они используют цвета, вычисленные в pass1 для видимых фрагментов, они делают неверную вещь)
Есть идеи, почему? заставляет ли imageStore или что-то еще выполнять fragmentshader? могу ли я как-то это контролировать? это как-то связано с ранним z?
2 ответа:
Спецификация OpenGL определяет, что шейдер фрагментов выполняет перед тестом глубины. Если какое-то оборудование сначала выполняет тест глубины, то это будет только в тех случаях, когда коммутатор не заметит никаких изменений в поведении.
Ну, если вы просто не скажете шейдеру фрагментов выполнить после теста глубины, поместив эту строку в свой шейдер фрагментов:
layout(early_fragment_tests) in;
Это часть shader_image_load_store, по понятным причинам.
Поскольку early-z - это только средство оптимизации, которое не нужно делать, я думаю, что это вполне допустимое поведение.
Как уже было сказано, early-z-это простая оптимизация, которая никоим образом не позволяет изменить поведение. Это не изменяет выходные данные, когда глубина фрагмента get отклоняется в любом случае, но с появлением хранилища загрузки изображений фрагмент больше не является единственным выходным, и вызов шейдера для фрагмента, который не прошел тест глубины, все еще мог бы быть записан в изображение. Поэтому early-z должен быть отключен в этом случае, чтобы гарантировать последовательное поведение. Ваш компилятор волшебным образом не знает, что вы не хотите записывать в образ, когда тест глубины терпит неудачу, так как он видит только шейдер, который записывает что-то в образ, и early-z нигде не указан.Вы не сможете выполнить свой собственный тест глубины, используя текстуру глубины не как вложение глубины, а как ввод текстуры:
uniform sampler2D depth; void main() { if(gl_FragCoord.z > texture(depth, gl_FragCoord.xy / textureSize(depth)) discard; ... }