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