Трассировка лучей с помощью Compute Shader и Screen Quad

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

Каковы преимущества и недостатки метода вычислительных шейдеров по сравнению с четырехъядерным экраном?


person Simon Müller    schedule 25.05.2017    source источник
comment
Растеризация четырехугольника, заполняющего экран, займет некоторое время. Так зачем вообще задействовать полный конвейер рендеринга, если вы уже с самого начала знаете, что он вам не понадобится?   -  person BDL    schedule 25.05.2017
comment
Добавляет ли растеризация столько накладных расходов?   -  person Simon Müller    schedule 25.05.2017
comment
Я бы не сказал ооочень много, но это определенно добавляет накладных расходов.   -  person BDL    schedule 25.05.2017


Ответы (2)


Краткий ответ: потому что вычислительные шейдеры предоставляют более эффективные инструменты для выполнения сложных вычислений.

Длинный ответ:

Возможно, самым большим преимуществом, которое они предоставляют (в случае трассировки), является возможность точно контролировать как работа выполняется на графическом процессоре. Это важно, когда вы трассируете сложную сцену. Если ваша сцена тривиальна (например, Cornell Box), то разница незначительна. Трассируйте несколько сфер в своем фрагментном шейдере в течение всего дня. Посетите http://shadertoy.com/, чтобы увидеть безумие, которого можно достичь с помощью современных графических процессоров и фрагментных шейдеров.

Но. Если ваша сцена и затенение достаточно сложны, вам необходимо контролировать выполнение работы. Рендеринг квадроцикла и выполнение трассировки во фраг-шейдере в лучшем случае заставит ваше приложение зависнуть, пока драйвер плачет, изменит свое официальное имя и переместится на другой конец света... Водитель. Многие драйверы прерываются, если одна операция занимает слишком много времени (что практически никогда не происходит при стандартном использовании, но происходит очень быстро, когда вы начинаете пытаться трассировать 1M полигональных сцен).

Значит, вы слишком много работаете с фрагментарным шейдером... но дальше логично? Хорошо, ограничьте нагрузку. Нарисуйте квадраты меньшего размера, чтобы контролировать, какую часть экрана вы отслеживаете одновременно. Или используйте glScissor. Делайте нагрузку все меньше и меньше, пока ваш водитель не справится с ней.

Угадайте, что мы только что заново изобрели? Вычислительные шейдеры рабочие группы! Рабочие группы — это механизм вычислительного шейдера для управления размером задания, и они представляют собой гораздо лучшую абстракцию для этого, чем хакерство на уровне фрагментов (когда мы имеем дело с такой сложной задачей). Теперь мы можем естественным образом контролировать количество лучей, которые мы посылаем, и мы можем делать это без жесткой привязки к экранному пространству. Для простого трассировщика это добавляет ненужную сложность. Для «настоящего» это означает, что мы можем легко выполнять субпиксельный рейкаст на дрожащей сетке для AA, огромное количество рейкастов на пиксель для отслеживания пути, если мы того пожелаем, и т. д.

Другие функции вычислительных шейдеров, полезные для высокопроизводительных промышленных трассировщиков:

  • Общая память между группами потоков (позволяет, например, отслеживание пакетов, когда весь пакет пространственно-когерентных лучей отслеживается одновременно, чтобы использовать когерентность памяти и возможность общаться с ближайшими лучами)
  • Scatter Writes позволяет вычислительным шейдерам записывать в произвольные местоположения изображения (примечание: изображение и текстура немного различаются, но преимущество остается актуальным); вам больше не нужно отслеживать непосредственно из известного местоположения пикселя

В целом, архитектура современных графических процессоров предназначена для более естественной поддержки такого рода задач с использованием вычислений. Лично я написал прогрессивный трассировщик пути в реальном времени, используя MLT, ускорение kd-дерева и ряд других вычислительно затратных методов (PT уже чрезвычайно дорог). Я старался оставаться в фрагментном шейдере/полноэкранном квадроцикле столько, сколько мог. Как только моя сцена стала достаточно сложной, чтобы потребовать структуру ускорения, мой драйвер начал задыхаться, независимо от того, какие хакерские действия я выполнял. Я повторно реализовал CUDA (не совсем то же самое, что вычисления, но используя те же фундаментальные архитектурные достижения графического процессора), и все было хорошо с миром.

Если вы действительно хотите покопаться, взгляните на раздел 3.1 здесь: https://graphics.cg.uni-saarland.de/fileadmin/cguds/papers/2007/guenther_07_BVHonGPU/Guenter_et_al._-_Realtime_Ray_Tracing_on_GPU_with_BVH-based_Packet_Traversal.pdf. Откровенно говоря, лучшим ответом на этот вопрос было бы подробное обсуждение микроархитектуры графических процессоров, а я совсем не компетентен для этого. Глядя на современные трассировочные документы графических процессоров, подобные приведенному выше, вы поймете, насколько глубоки соображения производительности.

И последнее замечание: любое преимущество вычислений над фрагментацией в контексте трассировки лучей сложной сцены не имеет абсолютно никакого отношения к накладным расходам на растеризацию/вершинный шейдер/операции смешивания и т. д.. Для сложной сцены со сложным затенением узкие места полностью заключаются в трассировке вычислений, которые, как обсуждалось, в вычислительных шейдерах есть инструменты для более эффективной реализации .

person Josh Parnell    schedule 26.05.2017

Я собираюсь дополнить информацию о Джоше Парнелле.

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

Трассировщик лучей рекурсивен по своей природе (да, я знаю, что всегда можно преобразовать рекурсивный алгоритм в нерекурсивный, но это не всегда так просто сделать).

Таким образом, другой способ увидеть проблему может быть следующим:

Вместо того, чтобы иметь «один поток» на пиксель, одна идея может заключаться в том, чтобы иметь один поток на путь (путь является частью вашего луча (между 2 отскоками)).

Идя таким образом, вы направляете свою «кучу» лучей, а не свою «пиксельную сетку». Это упростит потенциальную рекурсивность трассировщика лучей и позволит избежать расхождения в сложных материалах:

Дополнительная информация здесь: http://research.nvidia.com/publication/megakernels-considered-harmful-wavefront-path-tracing-gpus

person Antoine Morrier    schedule 11.08.2017
comment
Не уверен, что понимаю, что вы подразумеваете под отсутствием рекурсии. Написав трассировщики лучей Radar, трассировщики сцен и некоторые другие во фрагментных шейдерах, я не согласен, что это правда. Для многих примеров этого метода изучите лучевые кастеры на ShaderToy. - person David Lannan; 20.07.2020
comment
@DavidLannan Я говорил о рекурсивности с точки зрения лучей - person Antoine Morrier; 20.07.2020