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);
 
    bmp.UnlockBits(bmp_data);
 
    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.