Преобразование классов стиля менеджера в свободные функции в C ++ / DirectX11 - PullRequest
0 голосов
/ 02 апреля 2019

Недавно я столкнулся с проблемой проектирования в некоторых моих кодах с использованием DX11 / C ++.Я создаю небольшой редактор вокселей, и пока все работает, но есть некоторые проблемы с дизайном моего кода.

В настоящее время у меня возникают проблемы с организацией моих вычислительных шейдеров.Существуют различные вычислительные шейдеры для индивидуальных задач.Например: некоторые рисуют новые блоки в вокселях, другие сглаживают воксель, другие реализуют марширующие кубы для создания сетки для вокселя и т. Д., И т. Д. Вот фрагмент, который заставляет меня подвергать сомнению большую часть моего дизайна:

auto voxelInput = voxel::sphere(width, height, depth, center, radius);

auto kernel = voxel::kernel::separable::average(9);
auto smoother = voxel::kernel::processor();

smoother.apply(voxelInput, kernel); 

auto build = marchingCubes::builder<mesh::triangle<vertex::light>, vertex::light>();

return build.mesh(voxelInput, radius/2.f, v3::Zero());

Конкретные проблемы, с которыми я сталкиваюсь, - это классы marchingCubes :: builder и voxel :: kernel :: processor.Я знаю, что это неправильно, все, что они делают, это компилируют и поддерживают указатели на код шейдера.Я думаю, что они должны быть преобразованы в свободные функции и просто вызываться так:

voxel::kernel::apply(voxelInput, kernel);

return marchingCubes::mesh(voxelInput, radius/2.f, v3::Zero());

Я знаю несколько способов, которыми я могу решить эту проблему:

1) Каждый раз, когда любая функцияназывается, я компилирую необходимые шейдеры (это самый простой, получит мне конечный результат, но будет самым уродливым и заставит меня часто компилировать / удалять шейдеры, особенно если я собираю сразу несколько воксельных операций).

2) Используйте синглтон для создания класса в верхней части функции.Я больше не перекомпилирую каждый раз, но теперь я потерял возможность легко удалять объект.Что произойдет, когда я захочу загрузить другой совершенно другой модуль, который не использует никаких функций вокселей?Если я продолжу загружать модули подобным образом, то потенциально у меня будет тонна бессмысленных шейдеров, плавающих в памяти, которые я больше не использую.

3) Создайте класс вокселей, в который встроена вся эта функциональность. Вызовите воксель.applyKernel (krnl), voxel.paint (position), voxel.mesh (args) и т. д. Мне это не нравится, потому что я боюсь, что это сделает мой класс вокселей раздутым и утомительным для работы.Мне, вероятно, придется хранить shared_ptr в шейдере среди всех вокселей.Это решает мою проблему с памятью, но создает новую проблему проектирования, связанную с наличием монолитного класса omni.

4) Какой-то менеджер вычислительных шейдеров выше в моем движке.Он будет вести себя как синглтон, но я мог бы потенциально перезвонить ему, чтобы удалить шейдер, когда модуль вокселей выгружен.Я получаю бесплатные функции и возможность удалять шейдеры, когда захочу.Добавление большей функциональности (как у художника) будет проще.Есть некоторые проблемы, например, кто-то забывает удалить шейдеры при уничтожении модуля.Или кто-то призывает к удалению, но есть еще один модуль, использующий бесплатные функции.Последнее, вероятно, может быть решено с помощью некоторого счетчика ссылок / умного указателя, но я не уверен, что это также верно.Вероятно, это будет изрядная работа, и я думаю, что я просто перенесу проблему в другое место.

5) Сохраните тот же стиль классов, но инициализируйте их, когда будет создан модуль вокселей.Это самый простой и самый простой, но я все еще остаюсь с этими странными классами.Все, что я сделал, это переместил проблему снова.Вероятность возникновения ошибок таким образом меньше, но возможно дублирование кода шейдера, если другой модуль использует некоторые функции (должно быть небольшим количеством).

Все вышеперечисленные параметры технически работают, но ни один не кажется правильным,Я хотел бы знать, есть ли у кого-то лучший вариант, который я не рассматривал?

...