Які методи візуалізації я б використав, щоб намалювати тіньовий ефект для карт у картковій грі?


13

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

той, що я роблю, схожий, але все це робиться за допомогою двовимірного API малювання на основі OpenGL, тому немає координати Z.

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

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

Кількість карток може змінитися, і картки перекидаються на стіл, тому я не можу використовувати будь-які види світлих карт.

Які алгоритми мені слід переглянути (окрім розмитості, яку я знаю, що потрібно робити?)

Спасибі

Оновлення

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

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

Я думаю про це:

  • Зберігайте текстуру такого ж розміру, як і зворотний буфер.
  • Намалюйте темні прямокутники як спрощені картки до цієї текстури.

  • Розмийте цю текстуру.

  • Намалюйте мої картки до цієї текстури.
  • Робіть додаткове освітлення на картках.
  • Намалюйте цю текстуру до резервного буфера.

Мої запитання:

  • Це правильний спосіб зробити це?

  • Чи існує спосіб зробити це без візуалізації текстури (збереження растрової
    карти такою ж великою, як резервний буфер)?

  • Чи безпечно припускати, що максимальний розмір текстури не буде
    перевищений розміром резервного буфера? (Що я маю на увазі, якщо резервний буфер
    становить 2000х3000, то чи можна впевнено сказати, що я можу створити текстуру у
    відеопам'яті такого розміру?

Спасибі


1
Естетичний момент у вашому другому питанні: це насправді неможливо, якщо ви насправді тримаєте ці картки в руці. Карти, притиснуті один до одного, не помітно тінять одна одну. Якщо тільки ви тримаєте їх багато . Ви дійсно не можете тримати картки так, як їх зображено на цьому зображенні; ці карти виглядають так, ніби вони розділені на кілька міліметрів; вони не плоскі одна проти одної. Я просто не переймаюся цим.
Нікол Болас

Відповіді:


18

Я думаю, що всі поступаються занадто складними рішеннями цієї проблеми.

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

Отже, спочатку у нас є картка (або все, що ви хочете намалювати), зображена тут (а). Далі ми беремо його копію, заповнюємо її чорним кольором і виконуємо на ній гауссову розмитість (b). Все це відбувається в Photoshop або будь-якому улюбленому інструменті мистецтва.

Далі, в грі, коли ми хочемо намалювати карту, спочатку намалюємо розмите чорне зображення з мультипликативним (або альфа) поєднанням, трохи змістимо в деякому напрямку, а потім намалюємо картку поверх цього. Войла.

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

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


2
+1 - робити тіні поза грою. Ви також можете зробити це на крок далі і змінити місце розміщення тіні a, якщо в сцені є світло.
FrenchyNZ

+1, приємна ілюстрація. Крім того, у випадку, коли ви можете використовувати візуалізацію темних тіней на стіл, а напівсвітлі на картках із трафаретом. Це буде складніше, але ефект буде ще приємніший :)
Кромстер

2

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

Другий трохи нагадує SSAO (окклюзія навколишнього середовища в екрані). Ця техніка вимагає координати Z. Однак, якщо у вас немає різного кута між картами (це я б припустив, якщо у вас немає Z-буфера), ви, ймовірно, можете зробити досить гарне наближення, надавши тіні для краплі (як перша) для кожної картка. Виступ може бути трохи хитрим - кожен літак потребує розмитого альфа-каналу для всіх літаків над ним, і якщо на столі є купа карт, це може бути досить багато пропусків.


SSAO overkill =) Дуже важко сказати, яка техніка затінення використовується, не бачачи приклад анімований. Якщо картки завжди потрапляють у такому порядку і розташовуються один від одного, було б найпростіше просто заздалегідь відтворити тіні, але ви ніколи не дізнаєтесь, як побачити гру в дії.
Патрік Х'юз

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: вимкніть суміш і візуалізацію карт. Крім того, варто зазначити, що перший метод не дозволяє отримати тіні між картками, як це видно на другому екрані програми OP.
Натан Рід

@NathanReed: Я подумав, що він знає, як можна вимкнути речі. Крім того, "тіні між картками" не мають сенсу, як я зазначив у своєму коментарі під цим питанням.
Нікол Болас

1
Це може не реально відображати, як ви насправді тримаєте картки, але це виглядає круто! Це насправді не має сенсу, щоб картки летіли над столом, як це робиться в першому пострілі ...
Натан Рід

0

Я б використовував буфер трафарету. Очистіть його до 1 (бажано одночасно з очищенням глибини), намалюйте свою таблицю. Потім увімкніть тест трафарету, намалюйте тіні, використовуючи розмиту текстуру прямокутника, збільшуючи, якщо трафарет і глибину проходять, нічого не роблячи, якщо трафарет не виходить, нічого, якщо глибина не виходить, і встановіть функцію трафарету на GL_EQUAL (ref 1, маска 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. Це також буде працювати з текстурою, меншою, ніж backbuffer, і також добре підтримується на всьому апаратному забезпеченні (це частина OpenGL 1.1 і Doom 3, які використовували його, тому ви можете очікувати, що підтримка буде дуже хорошою).

Основна установка піде так:

  • Ясний колір до чорного.
  • Вимкнути запис глибини (хоча цей метод не потребує буфера глибини, тому ви можете ігнорувати цю частину, оскільки не використовуєте її).
  • Встановіть вікно перегляду таких же розмірів, як і ваша текстура.
  • Намалюйте картки як заповнені білою геометрією.
  • glCopyTexSubImage2D до вашої текстури.
  • Повернення вікна перегляду назад до повного розміру вікна.
  • Намалюйте таблицю як звичайну.
  • Намалюйте текстуру як повноекранний змішаний чотирикутник, використовуючи шейдер для розмивання та інвертування кольору.
  • Намалюйте все інше.

Це також має працювати дуже добре, це трохи інтенсивніше GPU, ніж метод буфера трафарету, але правильно обробляє корпус, що перекривається, і - як я вже сказав - я думаю, що така гра, як ваша, буде мати можливість записувати GPU, навіть на низькому рівні картка.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.