Обработка фрагментов OpenGL (4.2), буфер глубины и imageLoadAndStore - PullRequest
2 голосов
/ 29 марта 2012

У меня есть два прохода рендеринга.На первом проходе я рендерил некоторую непрозрачную геометрию, используя FBO, в несколько текстур.

На втором проходе я снова рендерил ту же геометрию и основываясь на различных свойствах геометрии (таких как объект, нормаль и т. д.), я пишувычисленные значения цвета из прохода 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 для видимых фрагментов, они делают не то, что нужно)

* 1013Есть идеи почему?imageStore или что-то еще заставляет фрагментированный шейдер выполнить?я могу это как-то контролировать?это должно что-то делать с early-z?

Ответы [ 2 ]

3 голосов
/ 29 марта 2012

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

Ну, если вы просто не скажете фрагментному шейдеру выполнить после теста глубины, поместив эту строку в ваш фрагментный шейдер:

layout(early_fragment_tests) in;

Это часть shader_image_load_store по понятным причинам.

1 голос
/ 29 марта 2012

Так как early-z - это всего лишь средство оптимизации, которое не нужно делать, я думаю, это совершенно правильное поведение.

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

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

uniform sampler2D depth;

void main()
{
    if(gl_FragCoord.z > texture(depth, gl_FragCoord.xy / textureSize(depth))
        discard;
    ...
}
...