khdani's picture

Alpha Channel Texture

How properly I should load textures with alpha channel using OpenTK?
Using C, it was quite straightward, but it doesn't seems to work in C#/OpenTK,
I guess my code isn't correct. (The texture is TIFF, though in C I used TGA)

            Bitmap bmp = new Bitmap(textureFileName);
            BitmapData data = bmp.LockBits(
                new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            GL.GenTextures(1, out this.textureID);
            GL.BindTexture(TextureTarget.Texture2D, this.textureID);
            GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (float)TextureEnvMode.Replace);
            Glu.Build2DMipmap(TextureTarget.Texture2D, (int)PixelInternalFormat.Rgba,
                bmp.Width, bmp.Height, OpenTK.Graphics.PixelFormat.Bgra, PixelType.UnsignedByte,


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
triton's picture

I'm trying to load a 32-bit PNG with an alpha channel and I'm also not able to make it work. I'm getting the texture with a black background where it should be translucent.

I've tried all sort of combinations and none work. Does someone have any sample?


        private void UploadTexture()
            shipTexture = GL.GenTexture();
            GL.BindTexture(TextureTarget.Texture2D, shipTexture);
            BitmapData data = _bitmap.LockBits(new Rectangle(0, 0, _bitmap.Width, _bitmap.Height),
                ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
                OpenTK.Graphics.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
        public override void Draw()
            var min = position - _size / 2.0;
            var max = position + _size / 2.0;
            GL.BindTexture(TextureTarget.Texture2D, shipTexture);
                GL.Color4(1.0f, 1.0f, 1.0f, 0.5f);
                GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                    GL.TexCoord2(0.0, 0.0); GL.Vertex2(min.X, max.Y);
                    GL.TexCoord2(1.0, 0.0); GL.Vertex2(max.X, max.Y);
                    GL.TexCoord2(1.0, 1.0); GL.Vertex2(max.X, min.Y);
                    GL.TexCoord2(0.0, 1.0); GL.Vertex2(min.X, min.Y);
objarni's picture

You could use my TexUtil class to initialize/upload textures. Don't forget to call InitTexturing.

[ Only thing that seem to differ is your use of mipmaps ]

1. Start with orthographic mode for example GL.Ortho(0, 1, 0, 1, -1, 1);
2. Make non-alpha-textures work first, for example build them "by hand" directly in code, no files
3. Make alpha-textures built by hand work
4. Now adress the load-rgba-bitmaps-issue, once you got 1-3 working

triton's picture

I actually intend to use your class once I get everything working "by hand". I actually already checked out your code and it seems to be very similar.

1. I am using ortographic mode already.

2. Non-alpha-textures work fine.

3. I'm gonna try this, but this seems like a lot of work. :D

4. I think the problem is with .NET PNG loading. Or I'm not really understanding how blending works.

I have attached the texture. I saved it under Paint.NET and it reports the alpha channel. I've also installed Photoshop just to be sure.

How can I check if the alpha values are being read fine by .NET and OpenGL?


ships-normal.png7.37 KB
the Fiddler's picture

The texture upload code seems correct in both cases. It is almost identical to the code used in font rendering, which works fine. The blend function looks correct, too.

To ensure that .Net loads the PNG correctly, use Bitmap.ReadPixel and check the alpha values.

To check that OpenGL receives the correct data, use GL.GetTexSubImage2D to read back the uploaded texture.

@khdani: Depending on your target hardware, consider replacing Glu.Build2DMipmap with GL.GenerateMipmaps, which may be hardware accelerated.

objarni's picture


Step 3 is not that difficult if you go for a 1x1 texture ;) Just upload a byte-array to GL:

byte[] rgba = new byte[] { 128, 50, 100, 150 };

See the Upload()-method of the TexUtil class:

private static void Upload(int width, int height, bool alpha, byte[] bytes)
      var internalFormat = alpha ? PixelInternalFormat.Rgba : PixelInternalFormat.Rgb;
      var format = alpha ? PixelFormat.Rgba : PixelFormat.Rgb;
        width, height,
objarni's picture

I loaded your .png in Paint.NET, it is 32 bit just as the ball.png I experimented with when developing TexUtil.

So the input file seems correct!

triton's picture

Thanks everyone for the help.

I had to disable depth-testing to make it work.

objarni's picture

Cool, what was it that was wrong?

triton's picture

Well, I couldn't get the transparency to work and was only getting my textured quad with a black color where it was supposed to be transparent. It was just using the color I used to clear the screen in OpenGL, instead of the alpha value, and the blending wasn't working.

I'm still a beginning in OpenGL so I might have done something wrong somewhere else, but for now it seems to work ok.

objarni's picture

OK.. Blending/texturing is a little bit hard to get right in OpenGL. For me, coming from an 2d-game "mask color" kind of background, it was hard to re-learn how stuff works. It is just so much more general in OpenGL, so many more "mines" to step on :)