Jak korzystać z testów głębokości i przejrzystości tekstur w moim świecie 2.5D?

11

Uwaga: znalazłem już odpowiedź (którą opublikuję po tym pytaniu) - zastanawiałem się tylko, czy zrobiłem to dobrze, czy jest lepszy sposób.

Tworzę izometryczną grę „2.5D” przy użyciu OpenGL ES (JOGL). Przez „2.5D” rozumiem, że świat jest 3D, ale jest renderowany za pomocą płytek izometrycznych 2D.

Pierwotny problem, który musiałem rozwiązać, polegał na tym, że moje tekstury musiały być renderowane w kolejności (od tyłu do przodu), tak aby płytki nakładały się prawidłowo, aby uzyskać odpowiedni efekt. Po lekturze szybko zdałem sobie sprawę, że jest to podejście 2D „starego kapelusza”. Stało się to trudne do wykonania skutecznie, ponieważ gracz może modyfikować świat 3D (aby rzeczy mogły pojawiać się w dowolnym miejscu w przestrzeni 3D) - więc logiczne było, że korzystam z bufora głębokości. Oznaczało to, że nie musiałem się martwić renderowaniem rzeczy we właściwej kolejności.

Jednak napotkałem problem. Jeśli użyjesz GL_DEPTH_TESTi GL_BLENDrazem, tworzy to efekt, w którym obiekty są mieszane z tłem, zanim zostaną „posortowane” według kolejności Z (co oznacza, że ​​uzyskuje się dziwne nakładanie się tam, gdzie powinna być przezroczystość).

problem nakładania się przezroczystości

Oto pseudo kod, który powinien zilustrować problem (nawiasem mówiąc, używam libgdx dla Androida).

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
    // ...
}

Pytanie brzmi: jak rozwiązać problem nakładania się przezroczystości?

Nick Bolton
źródło
2
Tylko komentarz, aby powiedzieć, że poszedłem dokładnie tak samo jak ty w przypadku mojego silnika 2D: najpierw próbowałem być sprytny i sam sortować kafelki Z, a potem zdałem sobie sprawę, że nie ma powodu, aby scena była płaska, dzięki czemu moje kafelki Współrzędna Z i aktywacja testu alfa. Nie jestem pewien, czy masz rację, ale nie jesteś sam :-)
sam hocevar,

Odpowiedzi:

7

OK, więc oto moje rozwiązanie (proszę o komentarz, jeśli można to zrobić lepiej) ...

Okazuje się, że faktycznie powinienem używać testów alfa (odkryłem to przez przypadek, więc nie jestem do końca pewien, dlaczego to działa).

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
    // ...
}

Zwróć uwagę na użycie GL_ALPHA_TESTi glAlphaFunc.

Nick Bolton
źródło
To także rozwiązało mój problem. Dzięki za udostępnienie. Jesteś wspaniały
Mathlover,
2

Testy alfa służą do zatrzymania renderowania pikseli renderujących w dowolnym buforze, w tym w buforze Z. Mieszanie alfa to tylko kwestia wizualna - wartości wciąż są zapisywane w zbufferze, co może powodować takie problemy - niewidoczne piksele znajdują się przed kolejnymi renderowanymi pikselami, co oznacza, że ​​nie powiodą się one w teście zt podczas rysowania nowych pikseli. Oto, co możesz zobaczyć na obrazie, który dałeś, ztest nie powiódł się.

Wyłączenie pisania w Z również osiągnie te same cele, ale musisz upewnić się, że narysujesz wszystko z powrotem na pierwsze zamówienie. To powinno być łatwe do zrobienia w grze izometrycznej.

Luther
źródło
1
Myślę, że rysowanie od tyłu do przodu jest łatwe w grze 2D w iso tylko wtedy, gdy masz ustalony samolot Y, a projektant ma pełną kontrolę nad światem. Jednak gdy rzeczy mogą istnieć w dowolnym miejscu w przestrzeni 3D, a użytkownik pozwala na zmianę rzeczy, staje się to bardziej skomplikowane. Myślę, że korzystanie z bufora głębokości znacznie ułatwi mi życie.
Nick Bolton,