Songs of Conquest: Билборды для параллакса
Многие спрашивали меня о технологии, стоящей за 2.5D билбордами нашей игры, поэтому я посчитал, что пора написать об этом пост.
Вначале…
Почти сразу в нашей разработке 2.5D стало очевидно, что билбординг может быстро привести к огромным потерям производительности. Нам были нужны тысячи анимированных билбордов, образующих горные цепи, леса и равнины. В самых первых подходах мы пытались использовать регулярные спрайты с прикрепленными Monobehavior, обновляющими их ротацию. Это работало довольно хорошо, пока угол камеры не изменился. Но как вы, наверное, видели в трейлере, мы хотели иметь возможность увеличивать и уменьшать масштаб при изменении поворота камеры.
На сцену выходит картография…
Ясно, что подход придется изменить, поэтому родилась картография. Так мы в конечном итоге назвали систему, отвечающую за создание и рисование ландшафтов (земля, скалы, деревья, горы, трава, вода и т.д.). Мы также внедрили новый легкий конвейер рендеринга Unity, чтобы получить от рендеринга еще больше производительности.
Чтобы решить проблему с билбордингом, мы обратились к шейдерным приближениям. Мы просто перемещаем вершины «спрайтов» таким образом, будто бы они вращаются. С первого взгляда это работает очень хорошо, но мы быстро столкнулись с проблемой перевода между мировым пространством и пространством объектов, так как хотели, чтобы основание объектов всегда оставалось неподвижным и прикрепленным к земле. В итоге запечатали эту информацию в y-компонент второго uv-канала билборд «спрайтов» (или сеток).
Запечь данную информацию оказалось очень просто, все показано ниже.
void BillboardFixer(Mesh mesh)
{
var vertices = mesh.vertices;
var uvs = new List(mesh.vertexCount);
for (var i = 0; i < mesh.vertexCount; ++i)
{
var uv = vertices[i];
uvs.Add(uv);
}
mesh.SetUVs(1, uvs);
}
С помощью этой запеченной информации мы затем создали подграф для вычисления желаемого положения вершины. Помимо запеченной второй uv информации, нам также нужно было знать вращение камеры. Это вычисляется и передается шейдерам с помощью простой строки кода.
Shader.SetGlobalVector(
"_Billboard",
Camera.main.transform.rotation.eulerAngles * (Mathf.PI / 180f)
);
Это, в свою очередь, подается в наши шейдеры, как в очень простом примере ниже. Обратите внимание, что мы также должны были восстановить нормали, чтобы получить правильное освещение. Мы выбрали статическую реконструкцию, поскольку она выглядела лучше, чем динамическая. Но это определенно будет зависеть от варианта использования.
Заключение
Данное решение в значительной степени адаптировано к нашему конкретному случаю, поскольку билборды вращаются только по оси X. Ограничение, которое очень хорошо подходит для нашей игры. Этот подход также хорошо сочетается с другими, и как правило, он очень быстрый, но достаточно точный для наших нужд. Но надо сказать, что мы решили не использовать его для персонажей и зданий (чего-то действительно динамичного), поскольку любое повышение производительности быстро перевешивается сложностью системы.
Источник: https://www.lavapotion.com/blog/2019/9/9/the-shader-approach-to-billboarding
Исправьте
List<Vector3>(mesh.vertexCount);
на
List(mesh.vertexCount);
Упс… Что-то на сайте пошло не так с комментарием. В общем в первом примере кода, строка 4 должно быть var uvs = new List (треугольная скобочка открывается) Vector3 (треугольная скобочка закрывается) (mesh.vertexCount);
Та же проблема с знаком “меньше” в цикле на 6-й строке
Спасибо большое, это движок сайта преобразовал угловые скобки в html коды, я поправил! В комментариях дизайн “поплыл”… в ближайшие пару недель займемся исправлением
Здорово! Выглядит точь в точь как герои :)
Ув. разработчики, просьба, если это возможно – поделитесь
шейдером смешивания текстур разной местности,
буду безмерно благодарен!