C++, OpenGL Z-буферный препасс
Я делаю простой воксельный движок (думаю, Minecraft) и в настоящее время нахожусь на стадии избавления от окклюдированных лиц, чтобы получить немного драгоценного fps. Я не очень экспериментировал с OpenGL и не совсем понимаю, как работает магия glColorMask.
Вот что у меня есть:
// new and shiny
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// this one goes without saying
glEnable(GL_DEPTH_TEST);
// I want to see my code working, so fill the mask
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// fill the z-buffer, or whatever
glDepthFunc(GL_LESS);
glColorMask(0,0,0,0);
glDepthMask(GL_TRUE);
// do a first draw pass
world_display();
// now only show lines, so I can see the occluded lines do not display
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// I guess the error is somewhere here
glDepthFunc(GL_LEQUAL);
glColorMask(1,1,1,1);
glDepthMask(GL_FALSE);
// do a second draw pass for the real rendering
world_display();
Это несколько работает, но как только я меняю положение камеры, мир начинает исчезать, я вижу все меньше и меньше линий, пока ничего не происходит.
3 ответа
Похоже, вы не очищаете буфер глубины.
Вам нужно включить глубину записи (через glDepthMask(GL_TRUE);
) пока вы пытаетесь очистить буфер глубины с помощью glClear
, Вы, вероятно, все еще отключили его в предыдущем кадре, в результате чего все ваши очистки не выполняются в последующих кадрах. Просто переместите glDepthMask
позвонить до glClear
,
glColorMask и glDepthMask определяют, в какие части буфера кадра фактически записываются данные.
Идея ранней Z-выборки заключается в том, чтобы сначала визуализировать только часть буфера глубины - реальная экономия достигается за счет сортировки геометрии близко к дальнему, чтобы графический процессор мог быстро отбрасывать закупоренные фрагменты. Однако при рисовании Z-буфера вы не хотите рисовать компонент цвета: это позволяет переключать шейдеры, текстурирование, то есть все, что требует значительных вычислительных ресурсов.
Предупреждение: ранний Z работает только с непрозрачной геометрией. На самом деле весь буфер буфера глубины работает только для непрозрачных вещей. Как только вы выполняете смешивание, вам придется сортировать данные по дальности и не использовать буферизацию глубины (ищите "прозрачную для порядка прозрачность" для алгоритмов, чтобы преодолеть связанные с этим проблемы).
Если у вас есть что-то смешанное, удалите его со стадии "раннего Z".
На первом проходе вы установили
glDepthMask(1); // enable depth buffer writes
glColorMask(0,0,0); // disable color buffer writes
glDepthFunc(GL_LESS); // use normal depth oder testing
glEnable(GL_DEPTH_TEST); // and we want to perform depth tests
После завершения прохода Z вы немного меняете настройки
glDepthMask(0); // don't write to the depth buffer
glColorMask(1,1,1); // now set the color component
glDepthFunc(GL_EQUAL); // only draw if the depth of the incoming fragment
// matches the depth already in the depth buffer
GL_LEQUAL тоже выполняет эту работу, но также позволяет фрагментам даже ближе, чем в проходе буфера глубины. Но поскольку обновления буфера глубины не происходит, все, что находится между источником и сохраненной глубиной, будет перезаписывать его каждый раз, когда что-то рисуется там.
Небольшое изменение темы - использование заполненного буфера глубины "ранний Z" в качестве буфера геометрии в нескольких отложенных проходах затемнения.
Чтобы сохранить дальнейшую геометрию, взгляните на Окклюзионные Запросы. При запросах окклюзии вы спрашиваете, сколько GPU, если какие-либо фрагменты проходят все тесты. Это воксельный движок, вы, вероятно, используете дерево октодеев или Kd. Рисование пространственно-разделительных граней (с помощью glDepthMask(0), glColorMask(0,0,0)) ветвей дерева перед прохождением по ветке говорит вам, видна ли вообще какая-либо геометрия в этой ветке. Это в сочетании с почти-далеко отсортированным обходом и (грубым) усечением усеченного дерева даст вам ОГРОМНОЕ повышение производительности.
z-pre pass может работать с полупрозрачными объектами. если они полупрозрачные, не визуализируйте их в препассе, а затем выполните сортировку и визуализацию.