Привет!
Добро пожаловать на «Factorio Friday Facts» от Feargall! (FFFF, если хотите.)
Добро пожаловать на «Factorio Friday Facts» от Feargall! (FFFF, если хотите.)
За последние несколько месяцев вы несколько раз видели астероиды в качестве фоновой части некоторых других FFF, но, несмотря на все их сдержанное величие, на самом деле это был довольно сложный трюк! Пойдемте со мной, и я возьму вас в путешествие 3720 к 1 через это поле астероидов.
Астероиды меня беспокоят
Сначала мы начали с астероидов-заполнителей, которые были такими же, как и любой другой спрайт — предварительно отрендеренным 2D-изображением со светом и тенями как его частью. Это сработало, но выглядело довольно странно, что все астероиды были ориентированы в одном направлении и двигались только в плоскости XY, не вращаясь.
Ранние астероиды-заполнители от v453000Итак, вращение — это то, о чем мы говорили в процессе проектирования астероидов.
Проекты астероидов (Эарендель)
Когда мы остановились на трех различных типах астероидов, мы могли приступить к созданию реальных конструкций астероидов. Учитывая обстановку, было ясно, что астероиды должны быть максимально визуально отличны друг от друга.
Мы могли бы использовать одну и ту же традиционную форму астероида для всех их подтипов и использовать цвет только для их различения, как в случае с заполнителями. Но тогда они-бы выходили более яркими, чем нам хотелось, но главная проблема в том, что в целом они будут выглядеть халтурно.
Вместо этого мы решили создать астероиды, которые будут отличаться во всех аспектах.
Во-первых, общая форма. Это важно из-за освещения на астероидах. Во многом их можно идентифицировать по форме их левой освещенной стороны. Металлические астероиды будут выглядеть как сильно деформированные вогнутые формы из изрытого металла. Углеродные астероиды будут представлять собой выпуклые массы гравия и пыли, немного больше похожие на слитые сферы, перемешанные вместе. Оксидные же астероиды будут иметь твердые ограненные формы с более прямыми линиями и острыми углами.
Что касается материалов, то металлические астероиды будут иметь металлический блеск. Углеродные астероиды будут грубыми, с более гравийными дефектами поверхности. Оксидные астероиды будут более блестящими и похожими на стекло, но менее похожими на чистый драгоценный камень и более потрепанными, пыльными или морозными.
С помощью этих приемов мы могли бы получить красивые и отчетливые астероиды, но это усугубляло еще одну проблему: астероиды были очень различимы и очень узнаваемыми, когда любой из них повторялся. Чтобы избежать заметных повторений, нам понадобится множество вариаций, а поскольку спрайты довольно большие, это будет очень дорого.
Другой вариант — скрыть часть сходства, заставив астероиды вращаться, но...
7680 причин не вращаться (Фергалл)
Обычно для спрайтов, которые необходимо вращать, например персонажа или транспортных средств, мы визуализируем отдельное изображение для каждого поворота, чтобы освещение совпадало. Хотя этот подход, вероятно, все еще работал, это был бы кошмар для производительности - поскольку каждый класс астероидов имел 5 размеров, каждый из которых потребовал бы некоторого количества вариантов и, вероятно, по крайней мере 64 кадров для убедительного вращения,. В итоге нам бы потребовалось колоссальные 7680 кадров анимации.
Очевидно, нужно было другое решение.
Представляем шейдеры
Казалось очевидным, что нам понадобится какой-то метод динамического применения информации об освещении астероида. Здесь на помощь приходит лучший друг игрового художника — карта нормалей. Для тех, кто не в курсе, карта нормалей — это изображение, которое, по сути, хранит наклон того, что оно представляет.
Чтобы использовать эту информацию о наклоне для применения освещения, нам нужно выполнить некоторые умные математические вычисления в шейдере, чтобы определить направление наклона от фиксированной точки света.Обновление освещения с вращением
Это дает нам «рассеянное» освещение, но информации о цвете нет! Поскольку мы не хотим создавать космическую оперу в стиле 50-х, нам нужно, чтобы наши астероиды не были черно-белыми. Поэтому при их рендеринге нам необходимо отделить информацию о цвете от информации об освещении.
Мы можем смешать сгенерированное освещение из карты нормалей с нашим необработанным цветным изображением, и это даст нам хороший результат.
Однако вы заметите несколько вещей: освещение очень «плоское», металл металлических астероидов и блеск льда не проступают. Это связано с тем, что шейдер еще не учитывает блеск материалов. Но мы не хотим равномерного увеличения блеска, на разных участках он должен быть разным! Итак, мы визуализируем еще один проход, на этот раз для зеркального освещения.
Мы применяем это, просто используя диффузный цвет для обработки цвета отражения и делая астероиды ярче в нужных областях.
Но лед по-прежнему выглядит неправильно! Он слишком твердый, лед пропускает сквозь себя немного света и рассеивается, придавая ему красивое голубое свечение. Это известно как подповерхностное рассеяние или SSS. Итак, еще одно изображение и проход рендеринга для них, смешанный только в тех областях, на которые косвенно падает свет.
Однако на всех астероидах по-прежнему слишком много теней. Хотя это технически точно, поскольку в космосе нет ничего, что могло бы отражать свет, для наших земных глаз это выглядит неестественно. Таким образом, мы можем уменьшить интенсивность тени и добавить дополнительный источник света под дополнительным углом к первому.
И мы закончили! Спасибо Earendel и Posila за помощь в решении некоторых вопросов с расчетами освещения.
Обновление освещения с вращением
Шейдер космической пыли (Фергалл)
Хотя шейдер звездного поля Ежи и движение астероидов в некоторой степени помогали показать игроку, что платформа движется, в целом эффект было сложно увидеть, нам нужно было что-то очевидное всеобъемлющее, но не чрезмерное.
Одним из решений мог бы быть классический эффект варп-скорости, как в «Звездном пути» или «Докторе Кто», но он казался немного мультяшным и немного оторванным от псевдореалистичного стиля Factorio. Поэтому вместо этого я остановился на компромиссе, состоящем из некоторых размытых движением микрометеоритов и межпланетной пыли, предположительно от всех взорвавшихся астероидов.
Космическая пыль пролетает мимо
Одним из способов создания этого эффекта было бы создание огромного количества дыма и частиц с некоторым размытием в движении, однако в больших количествах частицы требуют довольно много ресурсов, и поскольку этот эффект должен масштабироваться с платформой любого размера, которую вы просматриваете, это будет приведет к экспоненциальному увеличению затрат.
Вместо этого я решил создать одну текстуру со всеми «частицами» на ней. В целях дальнейшей оптимизации эта текстура затем «упаковывается» с несколькими другими текстурами, используемыми в шейдере. Это позволяет сохранить небольшое количество сэмплеров, но при этом позволяет сохранить много деталей.
Все 4 изображения объединены в 1 изображение RGBA.
Немного математики с координатами текстуры и мы можем заставить это изображение двигаться, а замаскировав красный, зеленый, синий и альфа-каналы, мы сможем получить доступ к «упакованным» данным, которые нам нужны.
Просто панорамирование всех текстур
Однако пыль все еще движется более или менее с той же скоростью, что выглядит странно. Таким образом, мы заставим пылинки и частицы двигаться с разной скоростью, просто изменяя скорость в функции панорамирования. Но мы также не хотим, чтобы все точки двигались с одинаковой скоростью, это будет слишком похоже на единую сплоченную структуру. Вот тут-то и пригодятся некоторые маскирующие текстуры. Мы можем использовать изображение №1, чтобы выборочно маскировать отдельные частицы в разное время, что помогает создать иллюзию множества мелких предметов, движущихся независимо. Это делается с помощью математических вычислений, чтобы построить график пика вокруг значения, затем мы присваиваем целевое значение переменной времени и повторяем его обратно.
«Случайный» выбор точки для отображения
В настоящее время частицы постоянно используют изображение следа на 100%, но они должны быть менее размытыми, если движутся медленно. Благодаря предварительному планированию при создании изображения мы можем сделать это, вырезав пиксели ниже порога. Поскольку изображение следа представляет собой линейный градиент, это означает, что мы можем довольно легко контролировать длину, мы просто вычитаем целевое значение из значения изображения.
По мере того, как платформа набирает обороты, пятнышки становятся более длинными.
Если мы повторим процесс пару раз с разными скоростями и масштабами, мы создадим эффект принудительного параллакса. Т.е. пыли ближе к камере больше и она движется быстрее.
Теперь все, что нам нужно сделать, это объединить все это вместе и привязать интенсивность к уровню масштабирования, чтобы это не слишком отвлекало при построении, и все готово!
Космическая пыль над движущейся платформой
В любом случае, с элементом переднего плана покончено.
Хотя пыль помогает проиллюстрировать движения, пространство по-прежнему кажется двумерным. Почему все астероиды идеально плоские с нашей платформой?
Итак, нам нужны элементы фона, больше астероидов! Опять же, мы могли бы просто создать больше астероидов, которые рендерятся за платформой и не сталкиваются, но это казалось неоптимальным.
Вместо этого я использовал технику под названием «нанесение текстур», чтобы создать бесконечное количество астероидов из одного атласа текстур, содержащего всего несколько изображений. Эта (F)FFF уже довольно длинная, поэтому я не буду вдаваться в подробности, но функция в основном разбивает экран на сетку и стремится разместить в каждой по 1 астероиду со случайным смещением.
Для тех, кто интересуется этой техникой, Дэниел Эллиот создал подробное видео о её реализации, которая является почти точной реализацией, используемой здесь.
Атлас текстур всех фоновых астероидов
Шейдер разбивает это изображение на отдельные астероиды, изменяя UV-координату образца текстуры. Если мы создадим сетку рандомизированных UV-разверток, мы сможем разместить в них астероиды. Однако если астероид поместить за границу двух ячеек сетки, он будет обрезан. Поэтому нам нужно было сослаться на соседние ячейки, чтобы выяснить, не перекрывают ли они текущую ячейку. К счастью, с этим можно справиться, просто используя одну и ту же функцию +/-1 в любом заданном направлении.
Здесь вы можете увидеть сетку ячеек, которую мы генерируем, а также перекрывающиеся образцы (окрашены в красный цвет).
Мы даем каждому астероиду случайную скорость вращения, движения и масштаб и проделываем все это снова в другом масштабе для параллакса. Затем мы делаем то же самое и используем те же расчеты для динамического освещения, что и раньше, и получаем бесконечные поля астероидов!
Продолжаем и продолжаем вечно
Большое спасибо, что отправились со мной в это долгое и техническое путешествие. Кажется, наш корабль уцелел.
Как всегда, пишите нам обычных местах:
Форум Редит
Отличный комментарий!