Для большей детализации объем рисуется только внутри ограничивающего куба (bounding box), внутри куба идет маршинг с фиксированным шагом, максимлаьное количество шагов - 256.
Внутрений объем задан ячейками вороного, для каждой ячейки расчитывается случайный радиус, а получившееся расстояние от границы сферы до центра принимается за плотность, это дает плавное увеличение плотности.
float3 pos; float accum_density = 0; for (; accum_density < 1;) { pos += dir * step; float density = LowResVolume( pos ); if ( density > 0 ) { // calculate lighting ... accum_density += density; } }
Можно добавить второй шум, чтобы получить большую детализацию. Работает это так: детальный шум умножается на плотность, на картинке синий - низкочастотный шум, красный - высокочастотный шум умноженый на низкочастотный.
По детальному шуму идет маршинг с меньшим шагом.
float3 pos; float accum_density = 0; for (; accum_density < 1;) { pos += dir * step; float density = LowResVolume( pos ); if ( density > 0 ) { float hr_density = HiResVolume( pos ) * density; if ( hr_density > 0 ) { // calculate lighting ... accum_density += hr_density; } } }
Чтобы получить более интересные формы добавляется турбуленция перед расчетом ближайшей ячейки вороного.
float3 pos; float accum_density = 0; for (; accum_density < 1;) { pos += dir * step; float density = LowResVolume( Turbulence( pos )); if ( density > 0 ) { float hr_density = HiResVolume( pos ) * density; if ( hr_density > 0 ) { // calculate lighting ... accum_density += hr_density; } } }
Преимущества такого способа рендеринга произвольных форм.
- Можно конструировать любые формы складывая, вычитая, умножая объемы, добавляя шумы и тд. Нет ограничений на корректность дистанс функции, как при маршинге по SDF.
Недостатки.
- Низкая производительность, в моем случае расчет шумов сильно снижал производительность, но оптимизации с использованием 3D текстур с шумами не сильно улучшают ситуацию. Финальный результат выдает 5fps на gtx1070 в разрешении 1920x1080.
- Расчет освещения сложный и медленный, об этом будет расказано отдельно.
- Нет уровней детализации. Самый эффективнй способ увеличить производительность - снизить разрешение. Уменьшение количества шагов сильно ухудшают качество, мелкие детали начинают мелькать, границы объемов отличаться при движении камеры и тоже мелькают.
- Второй и последующие уровни детализации требуют большего количества шагов, что сильно нагружает одно ядро. Таким образом при уменьшении разрешения время работы шейдера остается большим, а множество ядер простаивают, но это может быть приемлемо, если остальные ядра заняты другими расчетами.
Комментариев нет:
Отправить комментарий