Ray tracing

Тема в разделе "WASM.DirectX", создана пользователем Sashasan, 23 июн 2021.

Метки:
  1. Sashasan

    Sashasan New Member

    Публикаций:
    0
    Регистрация:
    17 фев 2008
    Сообщения:
    23
    Адрес:
    Воронеж
    Кто, что делал.
    https://www.shadertoy.com/view/7sfXDf на GLSL пример трассировки луча методом шага по лучу, т. е. находим пересечение луча с поверхностью способом ray marching. Сделано все в пиксельном шейдере или фрагмент шейдере глубина рейтрейсинга 10, рейтрейсинг обратный.
    Вкратце как работает рейтрейсинг : начинается все с экранного пространства (это может быть полигон во весь экран, на котором мы рисуем с помощью пиксельного шейдера), в каждом пикселе которого хранится вектор вида (он разный во всех пикселях). Из каждого пикселя экранного пространства пускаем луч и ищем пресечение с поверхностью, если есть, то делаем расчет освещения и т.п., если нет - то приравниваем цвет пикселя к цвету окружающей среды, например кубической текстуре.
    Рейтрейсинг может быть прямой и обратный.

    Прямой -
    это от источника света к поверхности и до камеры, так же как в реальном мире.
    Обратный - это из камеры до поверхности, и до источника света и т. п.(растеризация - по сути это обратный рейтрейсинг с глубиной 1. Те же лучи из каждого пикселя, определяется пересечение луча и геометрии заданной вертексами). Растеризация не позволяет увеличить глубину луча, т. к. не программируется, да это и не нужно, есть для этого пиксельный шейдер, а еще лучше вычислительный шейдер cs :cools:.

    Глубина рейтрейсинга - это сколько раз каждый луч ищет пересечение с поверхностью. В примере из каждого пикселя экрана, а их 1920*1080 штук пускаем луч, который проверяет пересечение, если есть ,то высчитывает новый луч в направление отражения или преломления, снова проверяем на пересечение поверхности, если есть, то снова - новый луч, и так заданное число раз, в примере -10 раз . Вот почему рейтрейсинг так реалистичен и так затратен на вычислительную мощность.
    Чем сложнее или богаче геометрия, тем больше уходит времени на поиск пересечения, тем ниже фпс. Есть несколько способов задания геометрии.

    • Классический - загрузка вершин из файла (в блендере нарисовал, сохранил, загрузил).
    • Геометрия из вокселей (как я понимаю делается raymarching с заданным шагом).
    • Геометрия процедурная или заданная формулами (на мой взгляд самая лучшая и удобная, можно легко делать всякие демки от 4 кб :cools:).

    Преимущество рейтрейсинга по сравнению с растеризацией в том, что отражения и тени правильные, без артефактов. При растеризации не тестируется каждый луч (точнее даже сказать, что нет доступа к управлению растеризацией, он вшит в железо), а делаются разные хитрости с рендер таргетами (текстуры, в которые рисуется сцена), что обобщает отражение и взывает так называемые артефакты. К тому же увеличить глубину луча не получится, а если и получится, то это будет артефакт на артефакте. Вот видео со старым моим примером dx9 shader 3.0, на нем артефакты сразу видны, :) глубина луча 1.
    Вообще, что лучше OpenGl или DirectX - конечно DirectX, потому что OpenGl - это тестовая площадка разных функций DirectX. Если хотите, чтобы приложение всегда лежало или работало только у вас, то OpenGl - самое лучшее решение для этого :) . Единственный + OpenGl - это мультиплатформенность.

    DirectX есть кучи версий, но нормальные начинаются с dx9 - dx12. Что из них выбрать? Пример рейтрейсинга от Thetrik на dx9, и он работает, но лучше рейтрейсинг делать на dx12 или dx11, начиная с shader 5.0 (в нем - кардинально улучённое управление потоками, не говоря о dx12 и shader 6.0). Что это дает - когда в шейдере появляется условие, то на dx9 выполняются оба, а результат записывается в зависимости от условия, а на dx11 и выше - выполняется только верное, что дает большой прирост производительности + в зависимости от архитекторы видео карты, еще улучшается управление потоками. Разница очень заметна, например у меня на AMD Radeon R9 200 идет шейдер 20 фпс ,тогда как этот же шейдер на GEFORCE GTX 1070 - идет 60 фпс. Как так получается у gtx 1070 1920 ядер и 256 бит шина, тогда как у r9200 2560 ядер и 512 бит шина? Дело в архитектуре, в r9200 ядра "простаивают", т. е. не везде ядра работают параллельно, где-то они чаще ждут окончания работы других ядер по сравнению с gtx 1070.


    Вот скриншот из моей реализации трассировки луча на dx11 на пиксель шейдерах 5.0 фпс 800 (на скрине фпс - неправильный). Метод определения пересечения - геометрический.
     

    Вложения:

  2. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    861
    Sashasan нравится это.
  3. Sashasan

    Sashasan New Member

    Публикаций:
    0
    Регистрация:
    17 фев 2008
    Сообщения:
    23
    Адрес:
    Воронеж
    https://www.shadertoy.com/view/7sfXDf на GLSL
    Пример трассировки луча методом шага по лучу т. е. находим пересечение луча с поверхностью способом ray marching. Сделано все в пиксельном шейдере или фрагмент шейдере.
    upload_2021-6-25_12-44-51.png
    --- Сообщение объединено, 25 июн 2021 ---
    --- Сообщение объединено, 25 июн 2021 ---
     
    Последнее редактирование: 25 июн 2021