Como uso o teste de profundidade e a transparência da textura juntos no meu mundo 2.5D?

11

Nota: Eu já encontrei uma resposta (que postarei após esta pergunta) - estava me perguntando se estava fazendo o certo ou se há uma maneira melhor.

Estou criando um jogo isométrico "2.5D" usando o OpenGL ES (JOGL). Com "2.5D", quero dizer que o mundo é 3D, mas é renderizado usando blocos isométricos 2D.

O problema original que tive que resolver era que minhas texturas tinham que ser processadas em ordem (de trás para frente), de modo que os ladrilhos se sobrepusessem adequadamente para criar o efeito adequado. Após algumas leituras, percebi rapidamente que essa é a abordagem 2D do "velho chapéu". Isso ficou difícil de ser feito com eficiência, já que o mundo 3D pode ser modificado pelo player (para que as coisas apareçam em qualquer lugar no espaço 3D) - parecia lógico que eu aproveitasse o buffer de profundidade. Isso significava que não precisava me preocupar em renderizar as coisas na ordem correta.

No entanto, eu enfrentei um problema. Se você usar GL_DEPTH_TESTe GL_BLENDjuntos, ele cria um efeito onde os objetos são misturados com o fundo antes de serem "ordenadas" por ordem z (o que significa que você obtenha um tipo estranho de sobreposição onde a transparência deve ser).

problema de sobreposição de transparência

Aqui estão alguns pseudo-códigos que ilustram o problema (aliás, estou usando a libgdx para 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
    // ...
}

Portanto, a pergunta é: como resolver o problema de sobreposição de transparência?

Nick Bolton
fonte
2
Apenas um comentário para dizer que eu segui exatamente da mesma maneira que você no meu mecanismo 2D: primeiro tentando ser inteligente e classificar Z por mim mesmo, depois percebendo que não havia razão para que a cena fosse plana, dando assim aos meus mosaicos um Coordenada Z e teste alfa de ativação. Não tenho certeza se você está certo, mas você não está sozinho :-)
Sam Hocevar

Respostas:

7

OK, então aqui está a minha solução (comente se isso pode ser feito melhor) ...

Acontece que eu deveria, de fato, usar o teste alfa (no entanto, descobri isso por acidente, por isso não tenho muita certeza do por que ele funciona).

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

Observe o uso de GL_ALPHA_TEST, e glAlphaFunc.

Nick Bolton
fonte
Também resolveu o meu problema. Obrigado por compartilhar. Você está ótimo
Mathlover
2

O teste alfa é usado para parar o renderizador que desenha pixels para qualquer buffer, incluindo o buffer z. A mistura alfa é apenas uma coisa visual - os valores ainda são gravados no zbuffer, o que pode resultar em problemas como este - pixels invisíveis ficam na frente dos pixels renderizados subseqüentemente, o que significa que eles falharão no ztest quando você desenhar os novos pixels. Isto é o que você pode ver na imagem que você deu, uma falha no ztest.

Desativar a gravação z também alcançará os mesmos fins, mas você deve garantir que desenha tudo de volta à ordem inicial. Isso deve ser fácil o suficiente no seu jogo isométrico.

Lutero
fonte
1
Eu acho que desenhar coisas de trás para frente é fácil em um jogo iso 2D somente quando você tem um plano Y fixo e o designer está no controle total do mundo. No entanto, quando coisas podem existir em qualquer lugar no espaço 3D e você permite que o usuário mude as coisas, isso se torna mais complicado. Eu acho que usar o buffer de profundidade tornará minha vida muito mais fácil.
Nick Bolton