Як я можу використовувати тестування глибини та прозорості текстури разом у своєму 2.5D світі?


11

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

Я роблю ізометричну гру «2.5D» за допомогою OpenGL ES (JOGL). Під "2.5D" я маю на увазі, що світ - 3D, але він відображається за допомогою 2D ізометричної плитки.

Первісна проблема, яку мені довелося вирішити, полягала в тому, що мої текстури мали бути викладені в порядку (зі спини вперед), щоб плитки перекривались належним чином, щоб створити належний ефект. Після деякого читання я швидко зрозумів, що це 2D підхід "старої шапки". Це стало важко зробити ефективно, оскільки 3D-світ може змінюватися програвачем (тому речі можуть з’являтися в будь-якому місці в 3D-просторі) - тому здавалося логічним, що я скористався перевагою буфера глибини. Це означало, що мені не доведеться турбуватися про те, щоб видати речі в правильному порядку.

Однак я зіткнувся з проблемою. Якщо ви використовуєте GL_DEPTH_TESTі GL_BLENDразом, він створює ефект , коли об'єкти змішується з фоном , перш ніж вони «упорядковано» по г порядку ( що означає , що ви отримаєте дивний вигляд перекриття , де прозорість повинна бути).

Проблема перекриття прозорості

Ось якийсь псевдо-код, який повинен ілюструвати проблему (до речі, я використовую libgdx для Android).

create() {
    // ...
    // some other code here
    // ...

    Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);
    Gdx.gl.glEnable(GL10.GL_BLEND);
}

render() {
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    Gdx.gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

    // ...
    // bind texture and create vertices
    // ...
}

Отже, питання полягає в тому, як вирішити проблему з перекриттям прозорості?


2
Просто коментар, щоб сказати вам, що я пройшов точно так само, як і ви для мого 2D двигуна: спершу намагаюся бути розумним і керувати плитками Z, потім зрозумівши, що немає причини, щоб сцена повинна бути плоскою, таким чином надаючи мої плитки Z координування та активація альфа-тесту. Не впевнений, чи прав ти, але ти не один :-)
sam hocevar

Відповіді:


7

Гаразд, ось ось моє рішення (прокоментуйте, будь ласка, якщо це можна зробити краще) ...

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

create() {
    // ...
    // some other code here
    // ...

    Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);
    Gdx.gl.glEnable(GL10.GL_ALPHA_TEST);
}

render() {
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    Gdx.gl10.glAlphaFunc(GL10.GL_GREATER, 0);

    // ...
    // bind texture and create vertices
    // ...
}

Зверніть увагу на використання GL_ALPHA_TESTта glAlphaFunc.


Це вирішило і мою проблему. Дякую, що поділились. Ви чудові
Mathlover

2

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

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


1
Я думаю, що малювати речі зі спини вперед можна в 2D ізо-грі лише тоді, коли у вас фіксований літак Y, і дизайнер повністю контролює світ. Однак, коли речі можуть існувати в будь-якому місці 3D-простору, і ви дозволяєте користувачеві змінювати речі, це стає складнішим. Я думаю, що використання буфера глибини полегшить моє життя.
Нік Болтон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.