воскресенье, 5 июля 2020 г.

Volume render, часть 1

Экспериментирую с рендером объемов и их оптимизацией.




Для большей детализации объем рисуется только внутри ограничивающего куба (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 &lt; 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.
  • Расчет освещения сложный и медленный, об этом будет расказано отдельно.
  • Нет уровней детализации. Самый эффективнй способ увеличить производительность - снизить разрешение. Уменьшение количества шагов сильно ухудшают качество, мелкие детали начинают мелькать, границы объемов отличаться при движении камеры и тоже мелькают.
  • Второй и последующие уровни детализации требуют большего количества шагов, что сильно нагружает одно ядро. Таким образом при уменьшении разрешения время работы шейдера остается большим, а множество ядер простаивают, но это может быть приемлемо, если остальные ядра заняты другими расчетами.

Комментариев нет:

Отправить комментарий