Поскольку у вас есть ограниченный набор возможностей, вот очевидный способ справиться с этим:
using opt_path = std::optional<path>;
shader compile_shaders(opt_path vs, opt_path tcs = std::nullopt, opt_path tes = std::nullopt, opt_path gs = std::nullopt, opt_path fs = std::nullopt, opt_path cs = std::nullopt)
{
...
}
Они просто используют аргументы по умолчанию для всех других путей шейдеров.Вы можете сказать, что предоставляется, а что нет через интерфейс std::optional
.Если вы не используете C ++ 17, вы, очевидно, замените его на boost::optional
или аналогичный тип.
Конечно, как бы вы ни справились с этим, это приведет к явно плохому интерфейсу.Подумайте, что нужно сделать, чтобы создать наиболее распространенный случай: вершинный шейдер в сочетании с фрагментным шейдером:
compile_shaders(vs_path, std::nullopt, std::nullopt, std::nullopt, fs_path);
Помнит ли пользователь, что между ними есть 3 этапа?Шансы хорошие, они не будут.Люди будут постоянно совершать ошибку, используя только 2 std::nullopt
с или 4. И учитывая, что VS + FS является наиболее распространенным случаем, у вас есть интерфейс, в котором наиболее распространенный случай очень легко получить.неверно.
Теперь вы можете изменить порядок параметров, сделав FS вторым параметром.Но если вы хотите использовать другие этапы, теперь вам нужно найти определение функции, чтобы запомнить, какие значения соответствуют каким этапам.По крайней мере, то, как я это сделал здесь, следует конвейеру OpenGL.Произвольное отображение требует просмотра документов.
И если вы хотите создать вычислительный шейдер, вы должны помнить, что есть 6 этапов, которые вы должны явно обнулить:
compile_shaders(std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, cs_path);
Сравнитьвсе это для более информативного интерфейса:
shader_paths paths(vs_path, shader_paths::vs);
paths.fragment(fs_path);
auto shader = compile_shaders(paths);
Здесь нет никакой двусмысленности.Путь к конструктору явно указывается как вершинный шейдер с использованием второго аргумента.Поэтому, если вам нужен вычислительный шейдер, вы должны использовать shader_paths::cs
, чтобы выразить это.Затем пути получают фрагментный шейдер с использованием функции с соответствующим именем.После этого вы компилируете шейдеры, и все готово.