Зависимости: shadertoy1.
В данном задании вам предстоит познакомится с написанием приложений при помощи Vulkan.
Однако чтобы отрисовать даже один одинокий треугольник "с нуля" на Вулкане требуется не один день разбираться с горой разных абстракций и движущихся частей API. Сложилась такая ситуация потому, что Vulkan разрабатывался для написания промышленных игровых движок, а не маленьких учебных приложений. Для решения этой дилеммы мы будем использовать библиотеку, упрощающую работу с Вулканом, Etna. Более того, в папке задания вам предоставлена простая заготовка, инициализирующая все необходимые библиотеки и подсистемы.
- Внимательно прочитайте данный файл до конца.
- Ознакомьтесь с уже написанной заготовкой, прочитайте комментарии. Понимать как она работает на 100% не требуется.
- Вспомните материал лекций и семинаров.
Наша цель — заставить ваш код из домашки shadertoy 1 запускаться локально на вулкане.
Но, в отличии от shadertoy, мы будем пользоваться не фрагментным шейдером, а вычислительным.
Это наложит на нас некоторые ограничения: мы не сможем записывать результат шейдера прямо в так называемый бэкбуфер, а точнее текущую картинку свопчейна.
Вместо этого предлагается создать новую картинку (etna::Image
) и записывать в неё результаты вычислительного шейдера при помощи storage images.
Обратите внимание, что storage image -- это не свойство самого изображения, а лишь способ забиндить почти произвольное изображение в шейдер и писать в него по произвольным координатам из произвольного треда.
Сам вычислительный шейдер необходимо запускать с достаточным количеством тредов чтобы цвет каждого пикселя вычислялся отдельным тредом.
После же мы просто "скопируем" наше изображение в бэкбуфер при помощи операции blit.
Подробности того, как именно загружать шейдера и биндить изображения, предлагается узнать самостоятельно из семплов shadowmap и simple_compute.
Итак, по пунктам:
- Загрузите шейдер
toy.comp
и создайте compute pipeline для его запуска. - Создайте новое изображение для записи результата шейдера.
- Забиндите изображение в шейдер и запустите его с достаточным количеством тредов.
- Сделайте
blit
из вашего нового изображения в изображение свопчейна. Разберитесь, в чём отличие командblit
иcopy
. - Не забудьте расставить
etna::set_state
иetna::flush_barriers
для приведения обоих изображений в корректное состояние на момент выполненияdispatch
иblit
. - Замените тестовый код в
toy.comp
на ваш шейдер из задания shadertoy1 и добейтесь того, чтобы он работал. Обратите внимание, что доступа к позиции мышки, текущему времени и другим дополнительным координатам "из коробки" в отличии от shadertoy нет. В базовом виде достаточно "заткнуть" эти значения константами.
После выполнения всех пунктов выше вы можете заметить, что функционала в нашей игрушечной версии shadertoy сильно меньше чем в настоящей. В качестве бонуса предлагается восстановить недостающий функционал. Не забывайте заглядывать в семпл shadowmap за примерами и вдохновением.
- Добавьте возможность перезагружать шейдера по нажатию кнопки без перезапуска приложения.
- Прокиньте в шейдер различные дополнительные числовые параметры: разрешение, текущее время, координаты мышки. Для этого используйте либо юниформ-буферы, либо пуш-константы.
- https://docs.vulkan.org/spec/latest/index.html — единый ресурс всего про Vulkan (документация, туториалы, гайды)
- https://www.khronos.org/opengl/wiki/OpenGL_Shading_Language — справочник по языку GLSL