Можно ли добиться эффекта факела (более светлая область вокруг источника света) в 2D-игре?

16

Я думаю написать себе простую 2D-игру. Сначала он не будет блестящим с идеальной графикой или игровым процессом, но я бы посчитал это моим первым шагом в разработке игр для ПК. Итак, представьте себе такую ​​простую 2D-игру на основе спрайтов (например, Heroes IV или Startcraft BroodWar).

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

Проблема с этим решением заключается в том, что если в игре есть объект источника света (например, герой, носящий факел или горящее здание), вокруг него должна быть более светлая область, верно? Поскольку я накладываю полупрозрачный слой поверх всего, как бы вы предложили добиться желаемого визуального эффекта факела? Может быть, перерисовать этот слой, добавив «пробелы» или разноцветные области в зависимости от эффекта освещения?

Ивайло Славов
источник
2
Маска может быть путь, чтобы пойти
Густав Масиэль
5
«Факел» в названии может сбивать с толку из-за игры под названием Torchlight.
Тетрад
4
@Tetrad Должен быть в порядке, пока его не с заглавной буквы. Что касается меня, Torchlight вообще не приходил в голову, пока вы не прочитали ваш комментарий.
знаменитый Гаркин
Тем не менее, я предложил изменить, чтобы сделать заголовок более конкретным.
знаменитый Гаркин
2
Возможный дубликат Как реализовано 2D освещение?
Bummzack

Ответы:

12

Я не знаю, для чего вы программируете, но вот как я справился с этим в XNA:

  1. При вызове отрисовки List<Light>объект создается / очищается.
  2. Во время цикла прорисовки плитки каждая плитка проверяется, чтобы увидеть, имеет ли она какие-либо источники света, связанные с ней. Если это так, Lightобъекты добавляются в List<Light>.
  3. Плитка рисуется самостоятельно RenderTarget2D.
  4. После цикла мозаики список Lights итерируется и рисуется самостоятельно, RenderTarget2Dиспользуя созданную мной текстуру, которая выглядит следующим образом:
    Легкая текстура (Примечание: я использовал значения R, G и B здесь, но вам, вероятно, следует использовать альфа-канал в вашем актуальная текстура.)
  5. Используя пользовательский шейдер, я рендерирую поверхность плитки на экран и передаю ее в качестве параметра, который выбирается для значения «темноты» в каждом пикселе.


Теперь стоит отметить несколько вещей:

Относительно пункта 4:

На самом деле у меня есть два пользовательских шейдера: один для рисования источников света к цели рендеринга освещения (шаг 4), а другой для рисования цели рендеринга плитки на экране с помощью цели рендеринга освещения (шаг 5).
Шейдер, используемый в точке 4, позволяет мне добавить (то, что я называю) значение «яркости». Это значение floatумножается на каждый пиксель текстуры, прежде чем оно будет добавлено к цели рендеринга, так что я могу по существу сделать свет ярче или темнее.
На этом этапе я также принимаю во внимание значение «масштаба» источника света, что означает, что я могу использовать большие или маленькие источники света, используя только одну текстуру.

Относительно пункта 5:

Представьте, что цель рендеринга освещения по существу имеет значение для каждого пикселя от 0 (черный) до 1 (белый). Шейдер по существу умножает это значение на значения RGB для пикселя в цели рендеринга мозаичного изображения, чтобы получить окончательное нарисованное изображение.

У меня также есть еще немного кода, где я передаю (шейдеру) значение, которое будет использоваться как цвет наложения день / ночь. Это также умножается на значения RGB и включается в расчет цели визуализации освещения.


Теперь, это не позволит вам делать такие вещи, как блокирование света от обхода объектов и так далее, но, по крайней мере, для моих целей, это просто и работает хорошо.

Я написал более подробные сообщения в блоге здесь и здесь, которые могут вам помочь. У меня сейчас нет времени, но если вы хотите, я могу более подробно рассказать здесь о gamedev.

О, и вот посмотрите на это в моем редакторе карт:введите описание изображения здесь

Ричард Марскелл - Дракир
источник
Генерировать и очищать список каждый кадр не может быть слишком дорогим?
Густаво Масиэль
@Gtoknu В моей игре нет заметной разницы. Список просто содержит ссылки на объекты, которые уже существуют в памяти, поэтому не похоже, что каждый источник света воссоздается или что-то в этом роде, только один список.
Ричард Марскелл - Дракир
Вы можете быть правы, не совсем, но вы. Конечно, вы не создаете полные объекты, но вы добавляете указатели на ссылки, все еще мало используемые, но все же потребляющие. Вы делаете это хорошо, но я думаю, что было бы лучше, если бы вы поместили список за пределы метода draw, поскольку логика в обновлении выполняется намного быстрее, чем в draw
Густав Масиэль
@Gtoknu Конечно, вы можете объявить список где угодно, но дело в том, что источники света связаны с плитками. Метод плитки Draw- это то, где вы узнаете, есть ли на плитке огни или нет. Я не перебираю все нарисованные тайлы в Updateметоде, поэтому я бы добавил дополнительные накладные расходы для этого. Кроме того, XNA пытается гарантировать, что Updateон будет вызываться 60 раз в секунду, поэтому он может жертвовать Drawвызовами для этого, что означает, что этот код будет вызываться реже.
Ричард Марскелл - Дракир
Все это говорит о том, что это спорный вопрос, потому что я в конечном итоге переместил источники света в их собственные списки на основе пространственного разделения и просто нарисовал все источники света в разделах, которые пересекают экран. Я не говорил об этом в своем посте из-за нехватки времени, но это упоминалось во втором посте, на который я ссылался.
Ричард Марскелл - Дракир
9

Обычно освещение в 2D-играх осуществляется с помощью карты нормалей для всех ваших спрайтов, а затем рассчитывается эффект 3D-освещения для ваших 2D-спрайтов. Это известно как «2.5D». Однако я бы не рекомендовал делать это в вашей первой игре, поскольку она сложная.

Вот потрясающее видео того, кто сделал это в XNA: http://www.youtube.com/watch?v=-Q6ISVaM5Ww

Тем не менее, есть, вероятно, способы обмануть и получить систему псевдо-освещения, которая может работать с различными предположениями.

Джон Макдональд
источник
Уже видел это видео раньше, +1 за упоминание такой невероятной техники.
Густаво Масиэль
Спасибо за совет и ссылку на видео. Действительно, карта кажется решением. Я сам попытался бы использовать карту на своем верхнем слое, чтобы создать «разрыв» или изменить эффект, который она оказывает на нижележащие объекты.
Ивайло Славов
5

Трудно предложить подход, если вы не совсем уверены в том, какого эффекта вы пытаетесь достичь. Такие детали, как то, должны ли источники света мешать окружающей среде или нет, какова точка зрения вашей игры, в какой степени свет должен взаимодействовать с окружающей средой и т. Д.

Я оставлю свои два цента, хотя. Посмотрите, подходит ли вам этот урок от Catalin Zima под названием Dynamic 2D Shadows . Как видите, свет имеет радиус и не проходит через препятствия. Вы можете немного оживить радиус и цвет, чтобы он выглядел ближе к реальному свету факела.

введите описание изображения здесь

В этом случае свет действует как наложение поверх вашей сцены, но не взаимодействует с ним в той же степени, что и в примере с Джоном, хотя и принимает во внимание препятствия.

редактировать

Каталин ссылается на другую статью, которую он использовал в качестве ссылки, но ссылка не работает. Вот обновленная ссылка .

Дэвид Гувея
источник
Спасибо, я думаю, что это не тот эффект, которого я добиваюсь, но все же спасибо за то, что поделились :)
Ивайло Славов