Loading a texture from disk

Before going into technical details about textures in the graphics pipeline, it is useful to know how to actually load a texture into OpenGL.

A simple way to achieve this is to use the System.Drawing.Bitmap class (MSDN documentation). This class can decode BMP, GIF, EXIG, JPG, PNG and TIFF images into system memory, so the only thing we have to do is send the decoded data to OpenGL. Here is how:

using System.Drawing;
using System.Drawing.Imaging;
using OpenTK.Graphics.OpenGL;
static int LoadTexture(string filename)
    if (String.IsNullOrEmpty(filename))
        throw new ArgumentException(filename);
    int id = GL.GenTexture();
    GL.BindTexture(TextureTarget.Texture2D, id);
    // We will not upload mipmaps, so disable mipmapping (otherwise the texture will not appear).
    // We can use GL.GenerateMipmaps() or GL.Ext.GenerateMipmaps() to create
    // mipmaps automatically. In that case, use TextureMinFilter.LinearMipmapLinear to enable them.
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
    Bitmap bmp = new Bitmap(filename);
    BitmapData bmp_data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bmp_data.Width, bmp_data.Height, 0,
        OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
    return id;

Now you can bind this texture id to a sampler (with GL.Uniform1) and use it in your shaders. If you are not using shaders, you should enable texturing (with GL.Enable) and bind the texture (GL.BindTexture) prior to rendering.


Comment viewing options

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

You can have a look at my Texture class. You can loads a texture from a file, a Stream or a byte[], resizes the texture, saves the texture to a disk and access texels.

ironic's picture

Does this example work if stride of BitmapData is not equal to width*4 ?

the Fiddler's picture

OpenGL pack alignment is 4 by default. You can modify this using GL.PixelStore(). Note that the GDI+ (System.Drawing) may impose additional alignment requirements, which are outside the scope of OpenTK/OpenGL. You should test both .Net and Mono to ensure your textures are being loaded correctly.

wcdeich4's picture

I have noticed how some people use bmp.Dispose(); right after bmp.UnlockBits(bmp_data);

Is it safe to call .Dispose() b/c there is another copy of the data passed into the unmanaged layer? Or is it a bad practice?