Comments 6
Первый раз вижу, чтобы раннюю валидацию и избегание дублирования bounds check преподносили как какое-то откровение...
ибо внутри цикла reflect и add их больше нет.
Как же нет, у вас там std::max(0.0f, formFactor) внутри, любой std::max это условный переход. Сами же говорите про вызовы валидированных типов и сами же это нарушаете.
Зачем вообще делать std::max с нулём для отбрасывания незначащих малых отрицательных чисел, std::fabs быстрее. https://godbolt.org/z/hbh34zG5d (опуская -ffast-math пока что)
Ну и для кода, думающего о низкоуровневой оптимизации, суммирование sumIncoming очень подозрительное, в цикле sumIncoming переприсваивается значение много раз на основе предыдущего значения, очень похоже на "алгоритм маляра Шлемиэля".
Спасибо, что прочитали мою статью и за внимательный разбор кода! Позвольте ответить.
По поводу std::max и условных переходов. Ну вот например, на архитектуре x86 (начиная с SSE) и даже на моем FX-9590 современные компиляторы разворачивают std::max в инструкцию MAXSS / MAXPS. Это branchless операция, она не создает никаких "пузырей" в конвейере, в отличие от реального if. Поэтому производительность здесь не страдает.
Ну и по поводу std::fabs. В задаче Radiosity использование модуля (fabs) физически некорректно. Отрицательное значение (ошибка интегрирования) - это отсутствие света (0), а не "положительный свет". fabs превратит ошибку -0.1 в энергию +0.1, нарушив закон сохранения энергии (создаст свет из ниоткуда). Клампинг к нулю здесь - единственно верное решение.
Насчет нарушения философии. Тут вы абсолютно правы. Валидация formFactor внутри reflect - это компромисс, который я допустил, и сделал это зря. В следующем коммите я вынесу это в отдельный тип FormFactor (как сделано для SpectralEnergy), чтобы ядро функции осталось чистым fmul и философия "валидации на входе" соблюдалась строго.
Большое спасибо за указание в правильную сторону. =)
Максимальный предел отражения света 99.9999% достигнут в лаборатории CNRS
Более чем справедливое замечание. Действительно, в лабораторных условиях (например, в лазерных резонаторах или экспериментах CNRS) существуют метаматериалы и сверхчистые зеркала с коэффициентом отражения, близким к единице.
Однако. Если рассматривать их в контексте Radiosity как Global Illumination, то использование таких значений превращается в этакую "световую бомбу". Проблемы тут вот какие:
Сходимость. Если альбедо близко к 1.0, энергия в системе практически не затухает. Численному решателю потребуются тысячи итераций, чтобы "успокоить" свет, что для реалтайма неприемлемо в принципе.
Ошибка float. На 50-м отскоке погрешность float может случайно превратить 0.999999 в 1.000001, и мы получим генерацию энергии из ниоткуда. В итоге, мы увидим что-то вроде ядерного взрыва в шейдере.
Ограничение 0.95 в H24 тут служит как своеобразный инженерный предохранитель. Мы строим не симулятор лазерной лаборатории, а стабильный графический движок для реалтайма. Для 99% реальных материалов (камень, дерево, ткань, кожа) альбедо редко превышает 0.8-0.9, так что 0.95 - это безопасный потолок, гарантирующий, что свет когда-нибудь затухнет, и картинка стабилизируется.
А можно ли где-нибудь код посмотреть? Я, конечно, в самом начале освоения графики (буквально в самом), но всё рано интересно посмотреть на работы, уже состоятельные в той или иной степени.
Приветствую в рядах графических программистов! Путь предстоит долгий, однако невероятно интересный.
Движок MagnaVerse пока находится в стадии активного R&D (исследований и разработки), это своего рода "лабораторный стенд", поэтому полного исходного кода в открытом доступе нет - там слишком много экспериментальной математики, которая меняется каждый день.
Например, я беру никем не проверенные в IT гипотезы из мира высшей математики и строю код так, словно они являются аксиомами. В некоторых случаях это работает и дает настоящие прорывы в производительности и качестве, но не во всех. Это обстоятельство повышает порог входа, требуя от программиста погружения в математику. Но парадокс в том, что иногда это же позволяет снизить порог использования самого кода, делая его безопаснее и логичнее.
Однако код, приведенный в статье (структуры H24) - это абсолютно рабочий "боевой" фрагмент. Вы можете смело брать эти структуры (SpectralEnergy, ValidatedMaterial) и пробовать внедрять их даже в свои первые проекты на OpenGL/Vulkan/DirectX. Это хороший фундамент, чтобы сразу приучить себя к культуре типов.
Успехов в освоении! Если возникнут вопросы по математике - спрашивайте.
Проблема Гильберта №24 в геймдеве: Как типобезопасная физика сделала Radiosity легче перышка