Как я могу реализовать плавное освещение на основе плитки?

8

Я работал над 2D-игрой на плитках и реализовал жесткое освещение:

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

Я хочу, чтобы это было немного сглажено. Мне не нужны тени или что-то еще, просто простое освещение. Я бы хотел, чтобы это выглядело так:

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

Моя текущая система использует уровни света для каждой плитки в мире, и они пересчитываются, когда плитка размещена или удалена. Я использую, batch.setColor(...)чтобы затенять плитки. Какой хороший способ добиться этого плавного освещения?

Я не хочу использовать метод наложения карты освещения, я уже попробовал это, и я не был доволен результатом. Я хочу иметь возможность установить, сколько света может проходить через блок. Например, блок грязи должен поглощать часть света, но стеклянный блок не должен блокировать свет. Это не было действительно возможно с методом наложения карты освещения. ОБНОВЛЕНИЕ: я неправильно понял, что этот метод на самом деле. Теперь я понимаю. Я думал неправильно. Сожалею!

ProRed
источник
Честно говоря, он выглядит более стильно с жестким освещением.
С. Тарык Четин
Мне это не очень нравится, также немного сложно различить фоновую плитку и плитки переднего плана с этим стилем.
ProRed

Ответы:

15

Простой способ добиться плавного освещения в игре на основе плиток - нарисовать «карту освещения» к цели рендеринга, а затем нарисовать эту цель рендеринга поверх вашей сцены, смешивая ее в альфа-режиме.

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

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

Получив эту текстуру карты света, вы можете нарисовать ее как наложение на игровой мир (растянутый). Вам нужно будет правильно его зажать, чтобы он идеально растягивал ваши плитки в игровом мире.

Тогда это вопрос альфа-смешения этой текстуры с вашим игровым миром в libGDX. Чтобы смешаться в LibGDX (лично я не знаю как), вам, возможно, придется взглянуть на Gdx.gl.glBlendFuncфункцию.

jgallant
источник
2
Вы можете управлять освещением так, как вы хотите с этой системой. Не уверен, что вы имеете в виду, когда говорите, что не можете блокировать свет. Кроме того, не совсем уверен, как вы планируете сгладить вашу текущую систему, так как вы буквально просто раскрашиваете свои плитки.
jgallant
4
Кстати, именно эта система и делает Starbound.
Qqwy
2
Это отличный подход, который обеспечивает гибкость там, где это необходимо. Я использую это в моей игре на основе тайлов, где у меня нет доступа к шейдерам, и это прекрасно работает!
Tyyppi_77
1
ОБНОВЛЕНИЕ : Кажется, это путь, я неправильно понял этот метод, и теперь я полностью понимаю! Я постараюсь реализовать этот метод сейчас, и я отмечу это как лучший ответ и дам вам награду!
ProRed
2
Если у вас есть дополнительные вопросы о том, как это сделать, не стесняйтесь спрашивать. Я реализовал это, и @ Tyyppi_77 также недавно. Я сделал это в XNA / Monogame и Unity. Tyyppi сделал это в SDL.
16:30
4

независимый от двигателя способ сделать это состоит в том, чтобы использовать среднюю легкую картографию. Во-первых, вам нужно сгенерировать черно-белую карту в виде двумерного массива логических значений, который является размером мира, в котором блоки имеют значение True, а пустой - False.

Как это (1 черный, 0 белый): карта

Затем вам нужно создать новый 2D-массив такого же размера, как и первый массив, но это массив с плавающей точкой. Затем вы переходите от черного (True) блока к черному блоку в массиве и усредняете близкое значение выборки (объяснено ниже)

Это изображение поможет: в среднем

Это изображение представляет выборку (где + означает ложь и | означает истину). мы рассматриваем значения True как 1, а значения False как 0. Затем вы усредняете 9 чисел и помещаете их в правильную часть массива. ПРИМЕЧАНИЕ. Убедитесь, что при выборке ребер внешние значения рассматриваются как контекстно-зависимые. Например: под землей карта вне мира может быть 1, а небо - 0.

Это должно выглядеть так (взято из другого поста):конец

Тогда все, что вам нужно сделать, это подкрасить каждый блок в массиве

rgba(tint,tint,tint,1)

(оттенок = текущее усредненное значение блока во втором массиве, и альфа не имеет значения). Примечание: это предполагает, что псевдо-функция rgba принимает значения с плавающей точкой от 0-1 вместо 0-255, если это так, просто сделайте это:

rgba(tint*255,tint*255,tint*255,255)

Надеюсь, что это имеет смысл :) Если вы хотите код, пожалуйста, спросите!

UDXS
источник
Спасибо за ваш ответ, но дело в том, что в моей игре уже есть яркое освещение ( здесь ). Я спросил, как я могу изменить это, чтобы выглядеть более гладко ( как это )
ProRed
1

Поскольку вы говорите о вещах, блокирующих свет, я предполагаю, что у вас есть модель того, как свет должен распространяться. Например, все без блоков над ним полностью освещено, свет распространяется на все соседние ячейки, но теряет определенную яркость.

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

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

Аддитивное смешивание материалов на вашей карте освещения, а затем мультипликативное смешивание вашей карты света с игровым миром.

Я сделал это некоторое время назад, который использует те же принципы. Эта система не поддерживает различное падение света для разных типов местности, но, по крайней мере, она должна иллюстрировать полезность наложения карты освещения.

Нильс Оле Тимм
источник
Понятно, чтобы я рендерил уровни освещенности в форме прямоугольников, точно равных размеру соответствующей плитки, второй цели рендеринга? И как бы я сгладить это?
ProRed
Вы можете позволить графическому процессору обрабатывать его путем понижающей дискретизации, поскольку при рендеринге он будет просто линейно интерполироваться для вас. Если этого недостаточно, вы можете запустить какое-то размытие в шейдере. Вы также можете рассмотреть рендеринг с более высокой степенью детализации, чем разрешение листов, если вы хотите нарисовать его по-разному в зависимости от соседних плиток. В основном, сложная часть состоит в том, чтобы придумать конкретные правила, которые вы хотите для какой области освещать. Если вы пишете эти правила, вы обычно найдете довольно простой способ сделать это.
Нильс Оле Тимм
1

Для факела это довольно просто: используя собственный пиксельный шейдер, вы вычисляете расстояние между каждым фрагментом и факелом; Затем вы можете рассчитать, где находится первая плотная плитка, которая блокирует свет, исходящий от факела. Затем вы вычисляете расстояние, на котором свет не блокируется, умножаете его на что-то <1, чтобы факел не освещал солнце, вычитаете это из общего расстояния и повторяйте для остальной части расстояния (где свет был заблокирован на хотя бы на одну плитку) с умноженным значением на несколько меньше ... Я знаю, как это сделать, и это не слишком сложно реализовать в opengl.

РЕДАКТИРОВАТЬ: для простого источника света с определенной центральной точкой мой метод очень прост. Однако моя не работает с солнечным светом, но хотя альфа-карта действительно хорошо работает с солнечным светом, она не будет хорошей идеей для факела, учитывая, что это потенциально движущийся объект, и создание новой карты в каждом кадре неприятно. жизненный опыт. На мой взгляд, лучшим решением является сочетание: вычисление расстояния для конкретных источников света, которые на самом деле являются объектами в игре, отдельный шейдер, который вы просто добавляете поверх альфа-карты, которую вы процедурно сгенерировали, используя технику, упомянутую выше: текстура всех плитки альфы от вашего жесткого затенения, как много квадратов, и возиться с методами, чтобы сгладить его.

Пол Бурсин
источник
0

Использует ли ваш рендеринг цвета вершин (или вы можете их изменить)?

Предполагая, что каждый блок представляет собой квадрат из 4-х вершин, это даст вам несколько вариантов, например:

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

Программист хронических игр
источник