Jump to content
  • Advertisement
EddieK

OpenGL OpenGL Z depth test and transparency doesn't work together

Recommended Posts

Hello. I'm trying to make an android game and I have come across a problem. I want to draw different map layers at different Z depths so that some of the tiles are drawn above the player while others are drawn under him. But there's an issue where the pixels with alpha drawn above the player. This is the code i'm using:

int setup(){
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        GLES20.glEnable(GL10.GL_ALPHA_TEST);
		GLES20.glEnable(GLES20.GL_TEXTURE_2D);	
}

int render(){
	    GLES20.glClearColor(0, 0, 0, 0);
        GLES20.glClear(GLES20.GL_ALPHA_BITS);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT);
        GLES20.glBlendFunc(GLES20.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

		// do the binding of textures and drawing vertices
}

My vertex shader:

uniform mat4 MVPMatrix; // model-view-projection matrix
uniform mat4 projectionMatrix;

attribute vec4 position;
attribute vec2 textureCoords;
attribute vec4 color;
attribute vec3 normal;

varying vec4 outColor;
varying vec2 outTexCoords;
varying vec3 outNormal;

void main()
{
    outNormal = normal;
    outTexCoords = textureCoords;
	outColor = color;
	gl_Position = MVPMatrix * position;
}

My fragment shader:

precision highp float;

uniform sampler2D texture;

varying vec4 outColor;
varying vec2 outTexCoords;
varying vec3 outNormal;

void main()
{
    vec4 color = texture2D(texture, outTexCoords) * outColor;
    gl_FragColor = vec4(color.r,color.g,color.b,color.a);//color.a);
}

I have attached a picture of how it looks. You can see the black squares near the tree. These squares should be transparent as they are in the png image:

2018-01-22-15-58-11.png

Its strange that in this picture instead of alpha or just black color it displays the grass texture beneath the player and the tree:

2018-01-22-15-58-11.png

Any ideas on how to fix this?

 

Thanks in advance :)

 

 

Edited by EddieK

Share this post


Link to post
Share on other sites
Advertisement

This is a classic problem with transparency in computer graphics. For transparency, you can not rely on the depth buffer as transparent parts of your geometry will also write the depth. Instead you must sort the geometry from back to front and draw them without a depth buffer. But in your case as it seems like a pixel art style game, you can make use of the depth buffer and instead of transparency, you would use alpha testing. Alpha testing means discarding transparent pixels, so the pixel shader modifies geometry which it outputs. This works well for sorting with a depth buffer, but results in any pixel being either completely transparent or completely opaque. For your art style it might work out perfectly. 

To enable alpha testing, you could write something like this in the fragment shader:

vec4 color = texture2D(texture, outTexCoords) * outColor;
if(color.a < 0.5)
{
  discard;
}
gl_FragColor = vec4(color.r,color.g,color.b,1);

That code will cut out any pixel which has less than 0.5 alpha.

Share this post


Link to post
Share on other sites
9 minutes ago, turanszkij said:

This is a classic problem with transparency in computer graphics. For transparency, you can not rely on the depth buffer as transparent parts of your geometry will also write the depth. Instead you must sort the geometry from back to front and draw them without a depth buffer. But in your case as it seems like a pixel art style game, you can make use of the depth buffer and instead of transparency, you would use alpha testing. Alpha testing means discarding transparent pixels, so the pixel shader modifies geometry which it outputs. This works well for sorting with a depth buffer, but results in any pixel being either completely transparent or completely opaque. For your art style it might work out perfectly. 

To enable alpha testing, you could write something like this in the fragment shader:


vec4 color = texture2D(texture, outTexCoords) * outColor;
if(color.a < 0.5)
{
  discard;
}
gl_FragColor = vec4(color.r,color.g,color.b,1);

That code will cut out any pixel which has less than 0.5 alpha.

Big thanks, that did the trick :)

Share this post


Link to post
Share on other sites

Check that clearbuffer thing this may not work same way on different es2 devices ( clearing alpha to 0 instead use 1)

Share this post


Link to post
Share on other sites

Aside: this line isn't doing much of anything:

        GLES20.glClear(GLES20.GL_ALPHA_BITS)

Alpha is part of the color, and hence will be cleared by GL_COLOR_BUFFER_BIT.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!