Итак, я прохожу учебник по трассировке лучей в попытке растянуть мои ноги F #. Поскольку учебное пособие написано на C ++, довольно сложно понять, как применять концепции функциональным образом. Я хотел бы написать все настолько функционально, насколько это возможно, потому что я намерен в конечном итоге запустить трассировщик лучей параллельно. Но это привело меня к следующей ситуации, суть которой, я уверен, проявляется в других темах, кроме трассировки лучей.
У нас есть объект Engine
, который (помимо прочего) хранит объект Scene
(набор объектов Primitive
). В настоящее время Scene
и Primitive
в нем полностью неизменны.
Чтобы попытаться улучшить время рендеринга, мы реализуем обычную трехмерную сетку. Для эффективного обхода сетки учебник ссылается на этот документ как для алгоритма обхода, так и для уменьшения количества тестов пересечения для примитивов, которые лежат за границами сетки. Вот как работает последняя часть:
- Каждому
Ray
присваивается уникальный rayID
- Каждый
Primitive
имеет поле lastRayID
.
- Когда
Ray
проверяет пересечение с Primitive
,
- Если
rayID
из Ray
равно lastRayID
из Primitive
, тогда тест пересечения пропускается.
- В противном случае выполняется проверка, и
rayID
из Ray
сохраняется в поле lastRayID
в Primitive
.
Это аккуратный способ кэширования тестов пересечения, но он настроен на последовательный трассировщик лучей и не будет работать вообще даже для двух одновременных лучей. Поэтому, хотя я мог бы использовать mutable
поля и, следовательно, иметь возможность реализовывать этот алгоритм, он не мог бы защитить мои конечные цели от параллелизуемого трассировщика лучей.
У меня есть одна идея. Проблема с сохранением изменчивого состояния с каждым примитивом состоит в том, что в отношении алгоритма рендеринга сцена является глобальной сущностью - каждый луч может потенциально ударить любой примитив. С другой стороны, каждый луч полностью автономен. Таким образом, в каждом луче я полагал, что мог бы создать набор примитивов, которые уже были проверены (этот набор будет эквивалентен полю lastRayID
, описанному выше). Проблема заключается в том, что каждый луч имеет чрезвычайно короткий срок службы, и потенциально может существовать много лучей в любой момент времени, поэтому установка такой структуры данных в каждом луче может быть дорогостоящей ((де) выделять время и память расходы на потребление могут быстро сложиться)
Есть ли у кого-нибудь советы по решению подобных ситуаций? Даже если это общая идея о преобразовании общего изменяемого состояния в локальное изменяемое состояние или что-то подобное, я уверен, что это мне очень поможет. Я был бы рад уточнить что-нибудь, если это необходимо.