Я работал над 2D-игрой на плитках и реализовал жесткое освещение:
Я хочу, чтобы это было немного сглажено. Мне не нужны тени или что-то еще, просто простое освещение. Я бы хотел, чтобы это выглядело так:
Моя текущая система использует уровни света для каждой плитки в мире, и они пересчитываются, когда плитка размещена или удалена. Я использую, batch.setColor(...)
чтобы затенять плитки. Какой хороший способ добиться этого плавного освещения?
Я не хочу использовать метод наложения карты освещения, я уже попробовал это, и я не был доволен результатом. Я хочу иметь возможность установить, сколько света может проходить через блок. Например, блок грязи должен поглощать часть света, но стеклянный блок не должен блокировать свет. Это не было действительно возможно с методом наложения карты освещения. ОБНОВЛЕНИЕ: я неправильно понял, что этот метод на самом деле. Теперь я понимаю. Я думал неправильно. Сожалею!
Ответы:
Простой способ добиться плавного освещения в игре на основе плиток - нарисовать «карту освещения» к цели рендеринга, а затем нарисовать эту цель рендеринга поверх вашей сцены, смешивая ее в альфа-режиме.
Ваша цель рендеринга карты освещения будет иметь размер вашей мозаичной карты, но в пикселях. Каждый пиксель будет представлять светлый цвет соответствующей плитки. Эта текстура рендеринга будет выглядеть примерно так (верхняя левая текстура в черно-белом варианте):
Получив эту текстуру карты света, вы можете нарисовать ее как наложение на игровой мир (растянутый). Вам нужно будет правильно его зажать, чтобы он идеально растягивал ваши плитки в игровом мире.
Тогда это вопрос альфа-смешения этой текстуры с вашим игровым миром в libGDX. Чтобы смешаться в LibGDX (лично я не знаю как), вам, возможно, придется взглянуть на
Gdx.gl.glBlendFunc
функцию.источник
независимый от двигателя способ сделать это состоит в том, чтобы использовать среднюю легкую картографию. Во-первых, вам нужно сгенерировать черно-белую карту в виде двумерного массива логических значений, который является размером мира, в котором блоки имеют значение True, а пустой - False.
Как это (1 черный, 0 белый):
Затем вам нужно создать новый 2D-массив такого же размера, как и первый массив, но это массив с плавающей точкой. Затем вы переходите от черного (True) блока к черному блоку в массиве и усредняете близкое значение выборки (объяснено ниже)
Это изображение поможет:
Это изображение представляет выборку (где + означает ложь и | означает истину). мы рассматриваем значения True как 1, а значения False как 0. Затем вы усредняете 9 чисел и помещаете их в правильную часть массива. ПРИМЕЧАНИЕ. Убедитесь, что при выборке ребер внешние значения рассматриваются как контекстно-зависимые. Например: под землей карта вне мира может быть 1, а небо - 0.
Это должно выглядеть так (взято из другого поста):
Тогда все, что вам нужно сделать, это подкрасить каждый блок в массиве
(оттенок = текущее усредненное значение блока во втором массиве, и альфа не имеет значения). Примечание: это предполагает, что псевдо-функция rgba принимает значения с плавающей точкой от 0-1 вместо 0-255, если это так, просто сделайте это:
Надеюсь, что это имеет смысл :) Если вы хотите код, пожалуйста, спросите!
источник
Поскольку вы говорите о вещах, блокирующих свет, я предполагаю, что у вас есть модель того, как свет должен распространяться. Например, все без блоков над ним полностью освещено, свет распространяется на все соседние ячейки, но теряет определенную яркость.
Вы должны быть в состоянии довольно легко реализовать эти правила на стороне программного обеспечения, по крайней мере, сглаживающая часть - это всего лишь вопрос добавления шейдера в сгенерированную вами карту освещения.
Методы, предложенные другими при наложении карты освещения, это то, что вы должны сделать в любом случае. Но вы можете изменить способ генерации этой карты освещения. Сначала вы можете заполнить его только информацией о блоке, но затем вы можете увеличить его и сгладить, например, в шейдере. Дополнительным преимуществом подхода карты освещения является то, что вы можете просто рисовать динамические источники света на своей карте освещения, а также выделять взрывы или что-то еще, и это будет естественным образом сочетаться с остальным миром.
Аддитивное смешивание материалов на вашей карте освещения, а затем мультипликативное смешивание вашей карты света с игровым миром.
Я сделал это некоторое время назад, который использует те же принципы. Эта система не поддерживает различное падение света для разных типов местности, но, по крайней мере, она должна иллюстрировать полезность наложения карты освещения.
источник
Для факела это довольно просто: используя собственный пиксельный шейдер, вы вычисляете расстояние между каждым фрагментом и факелом; Затем вы можете рассчитать, где находится первая плотная плитка, которая блокирует свет, исходящий от факела. Затем вы вычисляете расстояние, на котором свет не блокируется, умножаете его на что-то <1, чтобы факел не освещал солнце, вычитаете это из общего расстояния и повторяйте для остальной части расстояния (где свет был заблокирован на хотя бы на одну плитку) с умноженным значением на несколько меньше ... Я знаю, как это сделать, и это не слишком сложно реализовать в opengl.
РЕДАКТИРОВАТЬ: для простого источника света с определенной центральной точкой мой метод очень прост. Однако моя не работает с солнечным светом, но хотя альфа-карта действительно хорошо работает с солнечным светом, она не будет хорошей идеей для факела, учитывая, что это потенциально движущийся объект, и создание новой карты в каждом кадре неприятно. жизненный опыт. На мой взгляд, лучшим решением является сочетание: вычисление расстояния для конкретных источников света, которые на самом деле являются объектами в игре, отдельный шейдер, который вы просто добавляете поверх альфа-карты, которую вы процедурно сгенерировали, используя технику, упомянутую выше: текстура всех плитки альфы от вашего жесткого затенения, как много квадратов, и возиться с методами, чтобы сгладить его.
источник
Использует ли ваш рендеринг цвета вершин (или вы можете их изменить)?
Предполагая, что каждый блок представляет собой квадрат из 4-х вершин, это даст вам несколько вариантов, например:
Если ваш текущий алгоритм освещения дает вам значение освещения на блок, вы можете изменить его, чтобы получить значение на вершину. Поочередно, в каждой вершине вы можете усреднить светлый цвет текущего блока плюс трех его соседей. Любое решение будет недорогим.
источник