Трафаретный буфер и отложенный рендеринг с использованием OpenGL и GLSL
Меня интересует одна вещь, касающаяся использования буфера трафарета в контексте отложенного рендеринга: все ли фрагментные шейдеры на экранном пространстве используются в пределах "закрытой" области?
Вот пример для веб-сайта http://www.learnopengl.com/ (просто тема буфера трафарета, никакого отношения к отложенному отображению):
вопрос: что означает здесь выражение "остальные отбрасываются"? Это означает, что ни один пиксельный шейдер не будет вызван там, где значение равно 0 в сэмплере маски ИЛИ для каждого фрагмента на экране будет вызван пиксельный шейдер, НО будет применяться условие, исключающее заполнение пикселя, если значение равно 0?
Предположим, что первое изображение слева - это результат без буферизации трафарета. Поддержка информации - это четырехугольник, состоящий из 2 треугольников (мы применяем метод отложенного рендеринга, и поэтому мы работаем в пространстве экрана - размер экрана 500х500). Поэтому после растеризации будут задействованы 500 * 500 фрагментных шейдеров для заполнения буфера кадров, и все они будут использоваться даже в темной области, где нет света. Это означает, что если мы применяем модель затенения Blinn-Phong, эта последняя будет применена повсеместно на экране ДАЖЕ в темной области, и я думаю, что это потеря производительности.
Таким образом, логичным в этом случае должно быть создание маски (с использованием буфера трафарета или с использованием внешнего пользовательского прохода рендеринга маски с использованием другого буфера кадров для ее заполнения) и, наконец, использование модели затенения blinn-phong только для примера. где значение пикселя в сэмплере маски в пространстве экрана равно 1. Таким образом, модель затенения по фонгу будет применена ТОЛЬКО в нашем примере к двум полям и плоскости!
Хитрости здесь, чтобы выполнить работу правильно при первом подходе, должны состоять в том, чтобы добавить условие в фрагментный шейдер, чтобы сказать, нужно ли нам вычислять затенение blinn-phong для текущего фрагмента или нет в соответствии со значением текстуры выборки маски.
void main(void)
{
if (texture(MaskSampler, TexCoord.xy).r == 1.0f)
{
//Execute here Blinn-Phing shading model...
}
//Else nothing
}
Но мне интересно (если мы посмотрим на третье изображение выше), можно ли сказать OpenGL API, чтобы он вызывал фрагментные шейдеры, затронутые только цветной областью! (это означает, что мы не вводим в основной фрагмент шейдера). В этом случае количество используемых фрагментных шейдеров будет резко сокращено, а для производительности будет лучше! Или единственное решение - поместить условие в фрагментный шейдер, как я упоминал выше?
1 ответ
В большинстве случаев тест трафарета запускается перед фрагментным шейдером и пропускает его выполнение. Это подробно описано здесь, наряду с условиями, почему он может не выполняться перед фрагментным шейдером, хотя они маловероятны в описанной вами установке. Это было бы намного предпочтительнее, чем дополнительные ветви / образцы в вашем фрагментном шейдере. Это также намного легче реализовать и поддерживать.
Однако в случае ветвления предлагаемый вами способ запуска гораздо менее сложного шейдера также может обеспечить ускорение (скажем, запуск полного шейдера для каждого пикселя). Это связано с тем, что большинство современных драйверов оптимизируют предсказание ветвлений по пространственной согласованности. Это означает, что если все пиксели в локальной области всегда принимают одну и ту же ветку, это можно оптимизировать. Глава в Gem GPU описывает этот процесс. Конечно, это сильно зависит от сложности шейдера, площади и реализации драйвера. Метод трафаретного подхода гораздо менее неоднозначен.