Тени при помощи теневых объемов (shadow volumes)

128
18 августа 2019, 02:30

Похоже, я зашел в тупик. Понемногу разбираюсь с программированием графики, решил попробовать реализовать тени альтернативным shadow-mapping'у способом, а именно при помощи техники shadow volumes (еще ее называют stencil shadows). Сейчас я опишу как я понял алгоритм, вероятно в моем понимании есть ошибка, из-за которой я не могу понять то самое, из-за чего я это пишу:

  • Для каждого источника света, у объекта определяются силуэтные ребра. Это такие ребра, которые находятся на стыке двух полигонов (один направлен к источнику света, другой нет)
  • Эти ребра вытягиваются от источника света вдаль (желательно в бесконечность). Само вытягивание можно произвести прибавлением к точкам ребер вектора идущего от источника к каждой точке помноженного на какое-то значение.
  • После добавления вытянутых вершин ребер, для каждого ребра по этим вершинам строится грань, и в итоге все это образует некий конусообразный объем (так же для корректной работы следует еще добавить "крышки" в конце и в начале этого объема)
  • Затем происходит отрисовка этих конусов (то есть объемов) в буфер глубины и трафарета. Причем в начале рисуются пиксели лицевых полигонов, прошедших z-тест (в этот момент в stencil буфере значения увеличивается на единицу) а затем рисуются пиксели не лицевых полигонов, опять же прошедших z-тест (и на этот раз значения в stencil буфере уменьшаются). В итоге в stencil буфере остается область где значения stencil буфера остались единицами, там то и будет тень
  • Когда происходит отрисовка, то выполняется так же и тест трафарета, и отрисовка происходит только в тех месах где stencil-буфер равен нулю (то есть рисуется сцена, но области тени игнорируются)
  • Затем, чтобы области с тенями не были полностью черными можно отдельным проходом отрендерить фоновый цвет, наложив его на результат предыдущего прохода (используя blending)

Вопросы:

Если мое описание алгоритма верно, то как при всем этом добиться эффекта наложения теней разных источников друг на друга? Например, если источников света будет несколько, и тень от одного будет перекрывать тень от другого, то в этом месте тень должна становиться еще темнее, но если следовать описанному выше алгоритму - так происходить не будет (поскольку область в stencil буфере в результате будет одна) На различных видео с демонстрацией работы этого алгоритма, я натыкался на ПРАВИЛЬНЫЙ эффект (например здесь - https://www.youtube.com/watch?v=GqyXT6nsxCQ), то есть тени от разных источников накладываются и темнеют, но как?

Так же есть вопрос с засветлением затененных областей другими источниками света. То есть тень должна закрывать свет только того источника, который ее породил, но этот алгоритм такого будто бы не подразумевает. В то же время, опять же, есть видео где подобное поведение реализовано - https://www.youtube.com/watch?v=69xKosYal-Y

На практике я остановился на построении теневого объема, но перед тем как я продолжу, мне бы просто хотелось понять в теории - как, следуя этому этому алгоритму, можно добиться такого результата как на видео? Что именно я упускаю в понимании этого подхода? Буду рад подробному пояснению.

Answer 1

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

Это можно сделать, производя отрисовку в несколько проходов. Например, на каждом проходе производить действия по построению и отрисовке shadow volumes для одного источника освещения, но в конце рисовать геометрию не в экранный буфер, а аддитивно в карту освещенности. Тогда на выходе получится карта освещенности, где значение 0 соответствует ambient освещенности (т.е. пиксель не освещается ни одним источником света), а все значения выше нуля показывают, насколько хорошо этот пиксель освещается от источников света. С использованием этой карты освещенности в конце рисуется вся сцена.

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

READ ALSO
Тип элементов вектора. С++

Тип элементов вектора. С++

std::vector<type> насколько я понимаю , написав определенный type, то элементами моего вектора могут быть только этого типаА можно ли сделать так...

109
C# получить время кадра любого приложения, использующего GPU

C# получить время кадра любого приложения, использующего GPU

Хочу написать программу, которая будет проверять частоту кадров любого приложенияМоей целью является залогировать FPS и время каждого кадра

99
Как пользоваться Drools standalone?

Как пользоваться Drools standalone?

Кто пользовался процессором правил Drools? Из того, что я прочитал - это набор ява-библиотек, которые интегрируются в проектПосле чего можно...

124