Как я могу реализовать эффект развертки?

8

Я работаю над платформером старой школы в libgdx и хочу, чтобы он имел эффект "scanline", например так:

Малдита Кастилья Эффект Сканирования

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

Является ли мой подход с использованием двух камер и текстуры разумным? Какое хорошее решение для достижения этого эффекта?

Александр ГИДЕТ
источник

Ответы:

4

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

Вы должны вместо плиткитекстуры по всему квадру таким образом, чтобы сохранить соотношение пикселей к текселю 1: 1. Это включает в себя настройку текстурных координат квада так, чтобы они были больше 1 в максимально возможной степени, а также настройку параметра обтекания текстур для повторения вместо зажима. Если ваша текстура имеет размер 64x64 пикселя, а размер экрана составляет 1024x768 пикселей, вы можете предположить, что по оси X вы должны поместить текстуру 16 раз (1024/64). Точно так же по оси Y вы должны положить его 12 раз (768/64). Вы можете настроить эту математику для фактических границ вашей текстуры и экрана. Используйте эти числа (16 и 12) в качестве максимальных экстентов текстурных координат вашего квадра, и вы получите гораздо лучший результат. В зависимости от того, как ваша орфографическая проекция в настоящее время настроена для плиток, вам может даже не потребоваться изменить ее для визуализации.

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

float2    screenSize;
sampler2D textureSampler;
float2    textureCoordinate;

float4 main () { 
   // Interpolation of texture coordinates means that we don't get nice
   // integer boundaries we could take the modulus of.
   float half_y = textureCoordinate.y * screenSize.y * 0.5;
   float delta = round(half_y) - half_y;
   float delta_squared = delta * delta;
   if (delta_squared < 0.1) {
      return texture2D(textureSampler, textureCoordinate);
   } 

   return float4(0,0,0,0);
}

источник
0

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

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

Более простой вариант - масштабировать его самостоятельно. Например. если ваша камера увеличена до 75%, ваше изображение будет масштабировано до 133% ( 1/0.75).

ashes999
источник
Вы говорите, что изображение должно быть достаточно большим, чтобы охватить весь экран, разве нельзя заполнить немного прямоугольника небольшой текстурой?
Александр GUIDET
@AlexandreGUIDET Я не уверен. Я использую текстуру для постепенного исчезновения, и это 1x1 пиксель, который масштабируется. Для строк развертки вы хотите, чтобы это повторилось. Вы должны проверить, есть ли у libGDX опция для этого.
ashes999
@AlexandreGUIDET ты пробовал это?
ashes999
Я выбираю другой подход, используя другую камеру и рисуя эффект линии сканирования над сценой. Я еще не удовлетворен результатом, потому что сцена, кажется, скользит позади линий развертки. Что вы думаете об использовании шейдера вместо этого?
Александр GUIDET