Какие методы рендеринга я бы использовал, чтобы нарисовать эффект тени для карточек в карточной игре?


13

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

тот, который я делаю, похож на него, но все это делается с помощью API 2D-рисования, работающего на OpenGL, поэтому Z-координаты нет.

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

Я просто не уверен, как добиться затененного взгляда, близкого к этому.

Количество карт обязательно изменится, и карты будут брошены на стол, поэтому я не могу использовать какие-либо типы световых карт.

На какие алгоритмы мне следует обратить внимание (кроме размытия, которое, как я знаю, нужно будет сделать?)

Благодарность

Обновить

Я делаю 2D карточную игру. Я хочу добавить смещение дропхэдс от карт, например:

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

Я думаю о том, как это сделать:

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

  • Размыть эту текстуру.

  • Нарисуй мои карты к этой текстуре.
  • Делаем дополнительное освещение на карточках.
  • Нарисуйте эту текстуру в буфер.

Мои вопросы:

  • Это правильный способ сделать это?

  • Есть ли способ сделать это без рендеринга в текстуру (сохраняя растровое изображение
    размером с буферный буфер)?

  • Можно ли предположить, что максимальный размер текстуры не будет
    превышен размером буфера? (Что я имею в виду, если задний буфер
    имеет размер 2000x3000, то можно ли с уверенностью сказать, что я могу создать текстуру в
    видеопамяти такого размера?

Благодарность


1
Эстетическое замечание по второму вопросу: это невозможно, если вы держите эти карты в руке. Карты, прижатые друг к другу, заметно не затеняют друг друга. Нет, если вы не держите их много . Вы не можете держать карты так, как они изображены на этом изображении; эти карты выглядят так, будто они разделены на несколько миллиметров; они не плоские друг против друга. Я просто не стал бы беспокоиться об этом.
Николь Болас

Ответы:


18

Я думаю, что все дают слишком сложные решения этой проблемы ..

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

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

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

Для дальнейшего обмана вы можете чередовать отображение теней и карт, чтобы получить эффект, как (d), или сначала нарисовать все тени, а затем карты, как в (e) (я покрасил карты в случае (e), чтобы показать, что они все еще отдельно =)

Также лучше не использовать чистый черный (или полный альфа) для тени, чтобы создать более тонкие, прозрачные тени.


2
+1 за создание теней вне игры. Вы также можете сделать еще один шаг вперед и изменить местоположение тени, если в сцене есть источник света.
FrenchyNZ

+1, хорошая иллюстрация. Кроме того, в случае E вы можете использовать рендеринг темных теней на стол и полублестящие на картах с трафаретом. Это будет сложнее, но эффект будет еще приятнее :)
Kromster

2

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

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


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

0

Не могли бы вы сделать карту теней? Отрисовать сцену в fbo. Сохраните только значения глубины и выполните обычную проверку значения глубины в шейдере, чтобы увидеть, должна ли быть отрисована тень или нет.


Я не использую Z-буфер, здесь нет «глубины».
JMasterx

0

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

Кроме того, вашему фреймбуферу нужен альфа-компонент.

  1. Получите серое изображение карты. Сделайте это нечетким по краям, возможно, увеличивая его размер. Это изображение вашей теневой карты. Обратите внимание, что это одноканальное изображение. Когда вы получаете доступ к этой текстуре в своем шейдере, вы должны убедиться, что вы поместили одно значение в альфа-компонент. Это можно сделать в вашем шейдере или где-то еще.

    Значение 0.0 на изображении означает, что тени нет. Значение 1,0 на изображении означает общую тень . То есть, абсолютно черный. Вы, вероятно, хотите значение 0,5 или около того, как ваш самый темный цвет.

  2. Очистите экран так, чтобы альфа был установлен на ноль .

  3. Перед рендерингом чего-либо (или, по крайней мере, всего, что будет отображено «под» столом), для каждой карты визуализируйте нечеткую текстуру, смещенную относительно фактического положения карты (но с той же ориентацией). Вывод цвета шейдером должен быть следующим: конфигурация смешивания для этого должна быть (на языке OpenGL):

    glBlendEquation(GL_MAX);

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

    Вы также должны использовать маску цветной записи, чтобы отключить цветную запись.

  4. Представьте таблицу. При этом смешивание должно быть настроено следующим образом:

    glBlendEquation(GL_ADD);
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);

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

  1. Создайте изображение карты тени, как и раньше.

  2. Сначала визуализируем тени. Свяжите теневой кадровый буфер (который должен быть только одноканальным изображением, если ваше оборудование может отображать один из них). Очистите его значение до нуля.

  3. Для каждой карты визуализируйте изображение теневой карты со смещением, как и раньше. Ваш шейдер должен записать одно и то же значение во все четыре компонента выходного цвета. Режим наложения снова должен быть glBlendEquation(GL_MAX).

  4. Вернитесь к обычному кадровому буферу. Нарисуйте все, что вы хотите, чтобы быть в тени.

  5. Теперь нарисуйте полноэкранный четырехугольник с теневым изображением, которое мы отрисовали. Шейдер должен хранить тексель, извлеченный из теневого изображения в альфа-выходе; RGB не имеет значения. Режим смешивания должен быть:

    glBlendEquation(GL_ADD);
    glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

В первом методе, я думаю, вы забыли шаг 5: отключить смешивание и рендеринг карт. Кроме того, стоит отметить, что первый метод не позволяет получать тени между картами, как видно на втором скриншоте ОП.
Натан Рид

@NathanReed: Я подумал, что он знает, как отключить все сам. Кроме того, «межкарточные тени» не имеют никакого смысла, как я указал в своем комментарии под вопросом.
Николь Болас

1
Это может не реально представлять, как вы на самом деле держите карты, но выглядит круто! На самом деле не имеет «смысла», когда карты плавают над столом, как они это делают на первом выстреле, либо ...
Натан Рид

0

Я бы использовал трафаретный буфер. Очистите его до 1 (желательно одновременно с очисткой глубины), нарисуйте свой стол. Затем включите тестирование трафарета, нарисуйте тени, используя размытую текстуру прямоугольника, увеличивая, если трафарет и проход глубины, ничего не делая, если сбой трафарета, ничего, если сбой глубины, и установите для функции трафарета значение GL_EQUAL (ref 1, mask 0xff), отключите тест трафарета. , (Я не полностью протестировал это, но он получен из кода, который работает аналогично и должен работать нормально; вам может понадобиться настроить параметры). Тогда нарисуйте все остальное.

Звонки будут:

glEnable (GL_STENCIL_TEST);
glStencilFunc (GL_EQUAL, 1, 2);
glStencilOp (GL_KEEP, GL_KEEP, GL_INCR);

// draw shadow textures

glDisable (GL_STENCIL_TEST);

Единственный раз, когда это может вызвать проблемы, это если у вас есть два размытых края, которые слегка перекрываются; в противном случае ему не нужно ничего сверх того, что предлагает базовый OpenGL 1.1, и он будет работать на всех аппаратных средствах (возможно, вам понадобятся старые карты 3DFX, которые, я полагаю, на самом деле не беспокоятся о поддержке ...)

Второй вариант, который должен очень хорошо работать в игре, не критичной к производительности, это glCopyTexSubImage2D. Это будет работать с текстурой, меньшей размера буфера, а также хорошо поддерживается на всех аппаратных средствах (это часть OpenGL 1.1, и Doom 3 использовал ее, так что можно ожидать, что поддержка будет очень хорошей).

Базовая настройка будет выглядеть так:

  • Чистый цвет на черный.
  • Отключите запись глубины (хотя этот метод не нуждается в буфере глубины, поэтому вы можете игнорировать эту часть, поскольку вы ее не используете).
  • Установите область просмотра таких же размеров, как ваша текстура.
  • Нарисуйте карты в виде белой заливки геометрии.
  • glCopyTexSubImage2D к вашей текстуре.
  • Переключите окно просмотра обратно на полный размер окна.
  • Нарисуйте таблицу как обычно.
  • Нарисуйте текстуру в виде полноэкранного смешанного четырехугольника, используя шейдер, чтобы размыть ее и инвертировать цвет.
  • Нарисуй все остальное.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.