Problem with transparency in 2D [Solved]

Started by Sankacoffee51, March 16, 2012, 13:22:38

Previous topic - Next topic

Sankacoffee51

Hello the forum, I am a computer science engineer, currently working in a smartphone software company in Geneva.

I am making a small 2D game engine which I will use for game-prototype designing and testing a few ideas.

However, I am having some issues with transparency in opengl, and all the solutions I found so far don't work in my code. I use the TextureLoader class from the small space invaders game.

At first I had 32bit PNG's with an alpha channel, but there wasn't any transparent on the sprite, the animations worked fine, but i had my white square background beside the character.
Then I took off the white background and replaced it with a transparent one.
If I comment the lines GL11.GL_Enable(GL11.GL_BLEND) and GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE_MINUS_SRC_ALPHA),
my sprite is rendered as a black full square.

I then uncomment these two lines GL11.GL_Enable(GL11.GL_BLEND) and GL11.glBlendFunc(GL11.GL_SRC_ALPHA,GL11.GL_ONE_MINUS_SRC_ALPHA), and now I can't see anything of the character, he has completely disappeared.

I then tried with a 8bit png with alpha channel, the results are the same.
I tried messing (couldn't find good doc for these two functions) with GL11.glEnable(GL11.GL_ALPHA_TEST), GL11.glAlphaFunc(GL11.GL_GREATER, 0.1f) with no succes.

I also tried using GL11.glTexEnvi(GL11.GL_TEXTURE_ENV,GL11.GL_TEXTURE_ENV_MODE,GL11.GL_BLEND) but it messes with all the colors on the screen (blue gets yellow, green gets red-pink) and my png is still grey or transparent.

If I summarize a bit : my transparent png's are rendered black when blending is disabled, and rendered completely transparent when blending is enabled.

My conclusions are that only the alpha channel is being rendered(once all black, and once all transparent).
Or since the alpha channel multiplies the current pixel color, if alpha is always 0, my picture color is always the same.

There must be a logic way to avoid this, but I couldn't find any useful specific information on my problem.
If anyone has an idea on how to solve this, I'm stuck here for the moment.

I listed my OPENGL code hereunder and the Texture loading code from TextureLoader as well as a few links to my different types of png's.

OpenGL Initialisation Code:
(called once in the program)
GL11.glEnable(GL11.GL_TEXTURE_2D);
			GL11.glDisable(GL11.GL_DEPTH_TEST);
			GL11.glMatrixMode(GL11.GL_PROJECTION);
                        GL11.glMatrixMode(GL11.GL_MODELVIEW);
			GL11.glLoadIdentity();
			GL11.glOrtho(0, width, height, 0, -1, 1);
                        GL11.glViewport(0, 0, width, height);


OpenGL Current Frame Code:
(called once each frame before drawing objects)
                           GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
                            GL11.glLoadIdentity();



OpenGL Object Draw Code:
(called x times per frame, x = number of objects to draw)
public void drawf(float x, float y, int spriteX, int spriteY) {
		GL11.glPushMatrix();
		
		// bind to the appropriate texture for this sprite
		texture.bind();
                
                float divX = (texture.getImageWidth()/texWidth);
                float divY = (texture.getImageHeight()/texHeight);

                // coords of the sprite in the spritesheet
                float texBindX = spriteX*(texture.getWidth()/divX);
                float texBindY = spriteY*(texture.getHeight()/divY);
                float texBindX2 = (texture.getWidth()/divX) + spriteX*(texture.getWidth()/divX);
                float texBindY2 = (texture.getHeight()/divY) + spriteY*(texture.getHeight()/divY);
		
		// draw a quad textured to match the sprite at right pos on screen
                float textureStartX = ((float)x-10f)/10.0f;
                float textureStartY = ((float)y-5f)/5.0f;
                float textureEndX = textureStartX + 1.0f/10f;
                float textureEndY = textureStartY + 1.0f/5f;
                
                GL11.glEnable(GL11.GL_BLEND);
                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
           
                GL11.glBegin(GL11.GL_QUADS);
		{   
                    GL11.glTexCoord2f(texBindX, texBindY);
                    GL11.glVertex2f(textureStartX, textureStartY);
                    GL11.glTexCoord2f(texBindX, texBindY2);
                    GL11.glVertex2f(textureStartX, textureEndY);
                    GL11.glTexCoord2f(texBindX2, texBindY2);
                    GL11.glVertex2f(textureEndX,textureEndY);
                    GL11.glTexCoord2f(texBindX2, texBindY);
                    GL11.glVertex2f(textureEndX,textureStartY);
		}
		GL11.glEnd();
		GL11.glPopMatrix();
	}



TextureLoader texture loading code
       
        int textureID = createTextureID(); 
        Texture texture = new Texture(GL11.GL_TEXTURE_2D,textureID); 
        
        // bind this texture 

        GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); 
        BufferedImage bufferedImage = loadImage(resourceName); 
        texture.setWidth(bufferedImage.getWidth());
        texture.setHeight(bufferedImage.getHeight());
        
        if (bufferedImage.getColorModel().hasAlpha()) {
            srcPixelFormat = GL11.GL_RGBA;
        } else {
            srcPixelFormat = GL11.GL_RGB;
        }

        // convert that image into a byte buffer of texture data 

        ByteBuffer textureBuffer = convertImageData(bufferedImage,texture); 
        
        if (target == GL11.GL_TEXTURE_2D) 
        { 
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); 
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); 
        } 
 
        // produce a texture from the byte buffer

        GL11.glTexImage2D(target, 
                      0, 
                      GL11.GL_RGBA, 
                      get2Fold(bufferedImage.getWidth()), 
                      get2Fold(bufferedImage.getHeight()), 
                      0, 
                      srcPixelFormat, 
                      GL11.GL_UNSIGNED_BYTE, 
                      textureBuffer );


Here are two links to the png's spritesheets

http://keupon99.is-a-geek.org/pic2.png
http://keupon99.is-a-geek.org/pic1.png

spasi

Have you verified that convertImageData produces correct image data? Is it in RGBA format or something else, like BGRA?

Sankacoffee51

Here is the code from convertImageData that produces the image:

I did not look exactly what the functions do, but i have read the code, and it seems logical to me.
However, I am not experienced enough in png format to recognize glitches.

        glAlphaColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                                            new int[] {8,8,8,8},
                                            true,
                                            false,
                                            ComponentColorModel.TRANSLUCENT,
                                            DataBuffer.TYPE_BYTE);
                                            
        glColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                                            new int[] {8,8,8,0},
                                            false,
                                            false,
                                            ComponentColorModel.OPAQUE,
                                            DataBuffer.TYPE_BYTE);

        if (bufferedImage.getColorModel().hasAlpha()) {
            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,4,null);
            texImage = new BufferedImage(glAlphaColorModel,raster,false,new Hashtable());
        } else {
            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,3,null);
            texImage = new BufferedImage(glColorModel,raster,false,new Hashtable());
        }

spasi

That code looks weird. At least I haven't seen anyone doing image loading this way before. Try using slick-util or some other library for loading textures.

Sankacoffee51

okay, I will try to find a few hours this week-end to get some testing done.
At least my opengl code is familiar to me now, after testing everything possible.¨
I'll send some feedback as soon as I have tested slick-util. I hesitated to use that directly,
but wanted something simple and plug&play I could say.

Thank you very much,       

                                                   Olivier

Sankacoffee51

I tried using slick-utils and after a few minor issues, my problem is solved. Thanks for finding the problem so quickly!