Войти
ПрограммированиеФорумГрафика

Path tracer (2 стр)

Страницы: 1 2 3 4 5 6 Следующая »
#15
(Правка: 14:22) 14:21, 20 апр. 2019

Suslik
Добавил TransferFunction. Стало действительно годно

+ Показать

#16
(Правка: 19:48) 19:47, 20 апр. 2019

IBets
сделай ещё preintegrated transfer function или как он там называется, где в 2д текстуру предрассчитываются все возможные варианты реймарчинга через transfer function. это может улучшить производительность на порядок.

#17
7:58, 21 апр. 2019

Suslik
> preintegrated transfer function
Вряд ли  у меня там стохастический Ray-Marching.

#18
9:33, 21 апр. 2019

IBets
никакой разницы нет. это просто ускорение для любого transfer function raymarching'а.

#19
14:16, 22 апр. 2019

Suslik
А кто-нибудь из Volume texture делал поле расстояний по пороговому isosurface или оно того не стоит?

#20
15:12, 22 апр. 2019

IBets
да, так делают. это на самом деле можно делать более-менее эффективно с помощью flood fill'а. но для меня основной интерес в volume rendering'е представлял всегда рендеринг именно volume'а, то есть не изоповерхности, а именно интегрирование по объёму, а там этот хак не прокатит.

#21
15:14, 22 апр. 2019

Suslik
Ну смотри что бы по пустому пространству много не идти. Доходим до порогового и там интегрируем

#22
(Правка: 15:16) 15:15, 22 апр. 2019

IBets
без ограничения общности можно полагать, что пустого пространства вообще нет. по крайней мере я в таком допущении интегрирорвал. я использовал другую схему, где шаг подбирается таким образом, чтобы за один шаг интегрирования цвет результирующего пикселя поменялся меньше, чем на пороговую величину.

#23
17:37, 22 апр. 2019

IBets
> что бы по пустому пространству много не идти
Для этого перед основным рендером я трассировал в картинку размером, кажется, в 64 раза меньше, чем экран, и по уменьшенной volume texture, в которой записана только плотность с точностью 1 байт. Трассировал с двух сторон, грубо говоря спереди (из камеры) и наоборот сзади в сторону камеры. Луч останавливался, когда плотность превышала порог, который рассчитывался из transfer function, меняющейся в реал-тайме. Таким образом получалась 2d текстура со значениями near и far. Основные лучи уже трассировались от near до far, таким образом пропуская пустоту в начале и в конце, но не в середине.

Прибавка по скорости была просто огромной, помнится что-то типа 1.5-2 раза, относительно обычного ray marching'а без этой оптимизации. Сам этот первый шаг рендерился предельно быстро - уменьшенная 1-байтовая volume texture лучше кешируется, и количество лучей очень маленькое. В итоге получается, что на один луч, рассчитывающий near-far, приходится 64 полноценных луча.

Distance field я тоже пробовал рассчитывать. Профит кажется был не существенный относительно оптимизации описанной выше, но была ещё проблема в том, что его нужно перерассчитывать каждый раз, когда меняется transfer function, а в моём случае нужна была возможность крутить transfer function в реал-тайме.

То же самое с pre-integrate - изменения в transfer function приводили к перерассчёту и были неприятные заедания. Хотя я его конечно не сильно оптимизировал, может и можно было улучшить. Кроме того, профита я особо не получил, поскольку на моих данных нельзя было использовать большой шаг ray marching'а в любом случае - можно было проскочить тонкие или плотные поверхности, и тогда появлялись артефакты. А на большом шаге да, профит был хороший - скорость была совсем чуть-чуть медленнее, но качество было ощутимо лучше - артефактов меньше, но они всё равно оставались. Пробовал делать хаки с шагом назад при резком повышении плотности, но всё это в итоге работало медленнее, чем честный ray marching с шагом, настолько мелким, чтобы артефакты не были заметны глазу. Понятно, что тут всё зависит от твоих данных.

+ Картинка на тех же данных, что и у тебя
#24
(Правка: 24 апр. 2019, 9:48) 23:48, 23 апр. 2019

Добавил блендинг.

+ Показать

#25
(Правка: 17:34) 17:22, 27 апр. 2019

Alexander K
Как ты поборолся с полосами?
Чувствую косяк с градиентом

+ Показать
#26
(Правка: 17:45) 17:43, 27 апр. 2019

IBets
такое чувство, что ты градиент считаешь после применения transfer function. надо до.

можешь дать ссылку на датасеты, которые ты гоняешь? сколько у тебя считается один кадр?

#27
(Правка: 18:59) 18:00, 27 апр. 2019

Suslik
Но градиент никак не влияет на выборку из transfer function, только Position. Ну если только не рассчитывать как Position = Positon + EPSILON * Normal. Я тестил разные комбинации особой разницы нет. Вот отсюда я взял manix.dat https://github.com/mlavik1/UnityVolumeRendering/tree/master/DataFiles
Формат R16. Первые 3 значения dim x, y, z uint16_t. Сказать сколько кадр рендерится сложно и я еще important sampling не пилил.
Нормали в world space

+ Показать
#28
(Правка: 20:53) 20:46, 27 апр. 2019

IBets
> Но градиент никак не влияет на выборку из transfer function, только Position
можно считать градиент функции F(p) = transferFunction(data(p)), а можно — F(p) = data(p). у второго больше точность (и считается быстрее). ещё качественный результат даёт предрасчёт нормалей через центральную разницу в текстуру, а потом интерполяция между нормалями. дело в том, что нормаль, вычисленная по интерполированным текселям — это вовсе не то же самое, что интерполированная нормаль, второе кушает больше памяти (в 4 раза, лол), но даёт красивые нормали без ступенек.

> https://github.com/mlavik1/UnityVolumeRendering/tree/master/DataFiles
спасибо

я тож за вечер решил написать volume renderer на vulkan'е на path tracing'е, пока что нога спанчбоба (не реализовал BRDF):
Изображение

#29
(Правка: 22:36) 22:35, 27 апр. 2019

Suslik
У меня по интерполированным пикселям. Вот дает лучше чем центральная разность но все равно ступеньки

float3 GetGradientFiltered(VolumeDesc volume, float3 position) {
   

    const float3 G0 = GetGradientCD(volume, position);
    const float3 G1 = GetGradientCD(volume, position + float3(-volume.GradientDelta.x, -volume.GradientDelta.y, -volume.GradientDelta.z));
    const float3 G2 = GetGradientCD(volume, position + float3( volume.GradientDelta.x, volume.GradientDelta.y, volume.GradientDelta.z));
    const float3 G3 = GetGradientCD(volume, position + float3(-volume.GradientDelta.x, volume.GradientDelta.y, -volume.GradientDelta.z));
    const float3 G4 = GetGradientCD(volume, position + float3(volume.GradientDelta.x, -volume.GradientDelta.y, volume.GradientDelta.z));
    const float3 G5 = GetGradientCD(volume, position + float3(-volume.GradientDelta.x, -volume.GradientDelta.y, volume.GradientDelta.z));
    const float3 G6 = GetGradientCD(volume, position + float3(volume.GradientDelta.x, volume.GradientDelta.y, -volume.GradientDelta.z));
    const float3 G7 = GetGradientCD(volume, position + float3(-volume.GradientDelta.x, volume.GradientDelta.y, volume.GradientDelta.z));
    const float3 G8 = GetGradientCD(volume, position + float3(volume.GradientDelta.x, -volume.GradientDelta.y, -volume.GradientDelta.z));
    
    const float3 L0 = lerp(lerp(G1, G2, 0.5), lerp(G3, G4, 0.5), 0.5);
    const float3 L1 = lerp(lerp(G5, G6, 0.5), lerp(G7, G8, 0.5), 0.5);
    
    return lerp(G0, lerp(L0, L1, 0.5), 0.75);
}
Страницы: 1 2 3 4 5 6 Следующая »
ПрограммированиеФорумГрафика