Если сцена не полностью помещается в память, вы попадаете в область рендеринга вне ядра. Здесь есть два основных подхода: а) создать сцену по запросу; б) загрузить сцену по запросу.
Первый подход хорошо согласуется с большинством рабочих процессов анимации, где модели в значительной степени подразделяются с использованием, например, Catmull-Clark, и могут сильно загружать память, но сами базовые сетки легко помещаются в память. У Pixar есть несколько статей об этом (например, кэширование разностей лучей и геометрия многоразрешающей геометрии для трассировки лучей распределения в сложных сценах ), но суть в том, что модели подразделяются только тогда, когда на них воздействует луч, и подразделяются только на столько, сколько есть. разумно для такого луча (например, диффузное взаимное отражение требует меньшей точности, чем зеркальное отражение). Остальное обрабатывается кешем геометрии, который хранит разделенные модели в памяти и, как мы надеемся, делает процесс эффективным благодаря хорошей стратегии выселения.
Пока все ваши базовые сетки удобно помещаются в памяти, вы можете легко выходить из ядра и рендерить сетки на уровнях подразделений, которые никогда не поместятся в память. Кэш геометрии также хорошо масштабируется с объемом имеющейся у вас памяти, что позволяет вам сравнивать оперативную память с временем рендеринга. Это также использовалось в автомобилях, я верю.
Второй подход носит более общий характер и не опирается на интенсивное использование подразделения. Вместо этого он опирается на тот факт, что ваша сцена, скорее всего, была сделана художником и уже разделена на достаточно маленькие объекты, которые индивидуально вписываются в память. Идея состоит в том, чтобы сохранить две иерархии (иерархию kD-деревьев или ограничивающих томов): иерархию верхнего уровня, которая хранит только ограничивающие блоки объектов в вашей сцене, и иерархию низкого уровня, в которой хранится фактическая геометрия. Существует одна такая иерархия низкого уровня для каждого объекта.
При таком подходе вы в идеале уже сохраняете ограничивающую рамку вместе с каждым объектом на диске. Когда сцена загружена, вы изначально строите иерархию верхнего уровня, то есть вам нужно смотреть только на ограничивающие рамки, а не на геометрию. Затем вы начинаете отслеживать лучи и проходить их через иерархию. Всякий раз, когда луч попадает на листовой узел в иерархии верхнего уровня (т. Е. Он попадает в ограничивающую рамку объекта), этот объект загружается в память и строится его иерархия низкого уровня. Луч затем продолжает прослеживать этот объект. В сочетании с объектным кешем, который сохраняет в памяти как можно большую часть низкоуровневой иерархии, он может работать достаточно хорошо.
Первое преимущество такого подхода заключается в том, что объекты, которые никогда не попадают, никогда не загружаются, а это означает, что он автоматически адаптируется к видимости вашей сцены. Второе преимущество заключается в том, что если вы отслеживаете много лучей, вам не нужно сразу загружать объект, поскольку он попадает под луч; вместо этого вы можете удерживать этот луч и ждать, пока достаточное количество лучей достигнет этого объекта, амортизируя нагрузку в результате нескольких попаданий лучей.
Вы также можете комбинировать этот подход с алгоритмом сортировки лучей, таким как Sorted Deferred Shading для трассировки производственных путей, чтобы избежать сбоев из-за некогерентных лучей. Упомянутая статья описывает архитектуру рендерера Hyperion Диснея, который, как я полагаю, использовался для Big Hero 6, поэтому он, скорее всего, может обрабатывать сцены в производственных масштабах.
Если вы организуете свою сцену в пространственной структуре (обычно это иерархия ограничивающих объемов ), вы можете использовать своего рода виртуальную сцену (я составляю этот термин в отношении виртуальных текстур ).
Диспетчер памяти будет одновременно загружать только ограниченное количество ограничивающих блоков и абстрагировать операцию, состоящую в ее получении.
Таким образом, ящик будет загружаться только по мере необходимости: когда луч попадает в ограничивающий прямоугольник, ящик загружается для разрешения столкновения. Позже, когда необходимо загрузить другой ящик, неиспользуемый ящик удаляется, чтобы освободить место для нового.
При загрузке и удалении всех этих блоков когерентность лучей будет основным фактором скорости. Я полагаю, что дальнейшее улучшение может заключаться в том, чтобы отложить загрузку, переупорядочив лучи, чтобы сначала обработать уже загруженные ящики.
источник
Что вы делаете, вы загружаете треугольники в память с диска на основе того, что было поражено ранее. Сначала вы можете начать с треугольников в непосредственной близости. Причина заключается в том, что в одной области лучи могут неоднократно попадать в одни и те же треугольники. И в конце концов вы будете несколько эффективны. (По этой причине рекомендуется кэшировать последний треугольник попадания в трассировке окклюзии, который не заботится о порядке)
Во-вторых, вы сохраняете треугольники в пространственном дереве, которое позволяет вам выполнять быстрый поиск с диска, чтобы обновить те части, которые у вас есть в памяти, по близости. Поэтому загружайте только те ветки, которые будут на пути луча. Если это своего рода воксельное дерево, например октри, вы можете даже сортировать вторичные лучи и решать их согласованно. Дерево BSP также хорошо подходит для обрезки участков.
Есть случаи, когда это терпит неудачу, но это достаточно эффективно в большинстве сцен, если вы не рендерите шум ...
источник