# How do I use depth testing and texture transparency together in my 2.5D world?

Note: I've already found an answer (which I will post after this question) - I was just wondering if I was doing it right, or if there is a better way.

I'm making a "2.5D" isometric game using OpenGL ES (JOGL). By "2.5D", I mean that the world is 3D, but it is rendered using 2D isometric tiles.

The original problem I had to solve was that my textures had to be rendered in order (from back to front), so that the tiles overlapped properly to create the proper effect. After some reading, I quickly realised that this is the "old hat" 2D approach. This became difficult to do efficiently, since the 3D world can be modified by the player (so stuff can appear anywhere in 3D space) - so it seemed logical that I take advantage of the depth buffer. This meant that I didn't have to worry about rendering stuff in the correct order.

However, I faced a problem. If you use GL_DEPTH_TEST and GL_BLEND together, it creates an effect where objects are blended with the background before they are "sorted" by z order (meaning that you get a weird kind of overlap where the transparency should be).

Here's some pseudo code that should illustrate the problem (incidentally, I'm using libgdx for 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
// ...
}


So the question is: How do I solve the transparency overlap problem?

• Just a comment to tell you that I have gone exactly the same way as you for my 2D engine: first trying to be clever and Z-sort tiles myself, then realising there was no reason the scene should be flat, thus giving my tiles a Z coordinate and activating alpha test. Not sure whether you’re right, but you’re not alone :-) – sam hocevar Mar 11 '11 at 0:51

OK, so here's my solution (please comment if it can be done better)...

Turns out that I should in fact be using alpha testing (though, I discovered this by accident, so I'm not entirely sure why it works).

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


Note the use of GL_ALPHA_TEST, and glAlphaFunc.

• It solved my problem too. Thanks for sharing. You are great – Mathlover Jan 12 '14 at 21:37

Alpha testing is used to stop the renderer drawing pixels to any buffer, including the z buffer. Alpha blending is just a visual thing - values are still written to the zbuffer, which can result in problems like this - invisible pixels are infront of subsequently rendered pixels which means they'll fail the ztest when you draw the new pixels. This is what you can see in the image you gave, a ztest fail.

Switching off z writing will also achieve the same ends but you have to ensure you draw everything int back to front order. This should be easy enough to do in your isometric game.

• I think that drawing stuff from back to front is easy in a 2D iso game only when you have a fixed Y plane, and the designer is in full control of the world. However, when stuff can exist anywhere in 3D space, and you allow the user to change stuff, it becomes more complicated. I think using the depth buffer will make my life a lot easier. – Nick Bolton Mar 10 '11 at 16:50