OpenGL Cheatsheet

Textures

Use this OpenGL reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Creating and Binding Textures

GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);

// Upload image data
glTexImage2D(GL_TEXTURE_2D, /*mip=*/0, GL_RGBA8,
             width, height, /*border=*/0,
             GL_RGBA, GL_UNSIGNED_BYTE, pixels);

glGenerateMipmap(GL_TEXTURE_2D); // auto-generate all mip levels

DSA (GL 4.5+) — preferred

GLuint tex;
glCreateTextures(GL_TEXTURE_2D, 1, &tex);

// Immutable storage — format and dimensions fixed (recommended)
glTextureStorage2D(tex, mipLevels, GL_RGBA8, width, height);
glTextureSubImage2D(tex, /*mip=*/0, /*x=*/0, /*y=*/0,
                    width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glGenerateTextureMipmap(tex);

Texture Targets

TargetDescription
GL_TEXTURE_1D1D texture
GL_TEXTURE_2D2D texture
GL_TEXTURE_3D3D / volume texture
GL_TEXTURE_1D_ARRAYArray of 1D textures
GL_TEXTURE_2D_ARRAYArray of 2D textures
GL_TEXTURE_CUBE_MAP6-face cube map
GL_TEXTURE_CUBE_MAP_ARRAYArray of cube maps (GL 4.0+)
GL_TEXTURE_2D_MULTISAMPLEMSAA texture
GL_TEXTURE_2D_MULTISAMPLE_ARRAYMSAA texture array
GL_TEXTURE_RECTANGLENon-power-of-2 (integer UV, no mips)
GL_TEXTURE_BUFFER1D view into a buffer object

Internal Formats

Sized color formats

FormatChannelsBit depthNotes
GL_R8R8 unorm
GL_RG8RG8+8 unorm
GL_RGB8RGB8+8+8 unormNo alpha
GL_RGBA8RGBA8×4 unormMost common
GL_SRGB8RGB8×3 sRGBAuto linearize on sample
GL_SRGB8_ALPHA8RGBAsRGB+linear A
GL_R16FR16-bit floatHDR single channel
GL_RGB16FRGB16-bit floatHDR color
GL_RGBA16FRGBA16-bit floatMost common HDR
GL_R32FR32-bit floatFull precision
GL_RGBA32FRGBA32-bit float
GL_R8I / GL_R8UIR8-bit int/uintInteger texture
GL_RGBA8I / GL_RGBA8UIRGBA8-bit int/uint
GL_R11F_G11F_B10FRGB11+11+10 floatCompact HDR, no alpha
GL_RGB9_E5RGBShared exponent
GL_RGB10_A2RGBA10+10+10+2

Depth / stencil formats

FormatDescription
GL_DEPTH_COMPONENT1616-bit depth
GL_DEPTH_COMPONENT2424-bit depth
GL_DEPTH_COMPONENT32F32-bit float depth
GL_DEPTH24_STENCIL8Packed depth+stencil
GL_DEPTH32F_STENCIL8Float depth + stencil
GL_STENCIL_INDEX8Stencil only

Compressed formats

FormatNotes
GL_COMPRESSED_RGB_S3TC_DXT1_EXTBC1 (EXT_texture_compression_s3tc)
GL_COMPRESSED_RGBA_S3TC_DXT5_EXTBC3
GL_COMPRESSED_RED_RGTC1BC4
GL_COMPRESSED_RG_RGTC2BC5
GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOATBC6H
GL_COMPRESSED_RGBA_BPTC_UNORMBC7
// Upload pre-compressed data
glCompressedTexImage2D(GL_TEXTURE_2D, mip, internalFormat,
                       width, height, 0, imageSize, data);

Texture Parameters

// Wrapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// DSA: glTextureParameteri(tex, GL_TEXTURE_WRAP_S, GL_REPEAT);

// Filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// Border color (used with GL_CLAMP_TO_BORDER)
float border[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);

// Anisotropic filtering (widely supported, core in GL 4.6)
float maxAniso;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &maxAniso);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, maxAniso);

// LOD clamp
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0.0f);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 1000.0f); // default
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.5f);  // sharper

// Swizzle (remap channels)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
// or all at once
GLint swiz[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; // R as grayscale
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swiz);

// Mip range
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 8);

Wrap modes

ValueBehavior
GL_REPEATTile (default)
GL_MIRRORED_REPEATTile with mirror on each repeat
GL_CLAMP_TO_EDGEClamp to edge texel
GL_CLAMP_TO_BORDERClamp; outside uses GL_TEXTURE_BORDER_COLOR
GL_MIRROR_CLAMP_TO_EDGEMirror once, then clamp

Filter modes

Min filterDescription
GL_NEARESTNearest texel
GL_LINEARBilinear
GL_NEAREST_MIPMAP_NEARESTNearest mip, nearest texel
GL_LINEAR_MIPMAP_NEARESTNearest mip, bilinear
GL_NEAREST_MIPMAP_LINEARTrilinear, nearest texel
GL_LINEAR_MIPMAP_LINEARTrilinear (best, default recommended)
Mag filterDescription
GL_NEARESTNearest texel
GL_LINEARBilinear

Gotcha: mag filter cannot be a mipmap filter — only GL_NEAREST or GL_LINEAR.

Binding to Texture Units

// Activate unit and bind
glActiveTexture(GL_TEXTURE0 + unit);  // unit = 0..GL_MAX_TEXTURE_IMAGE_UNITS-1
glBindTexture(GL_TEXTURE_2D, tex);

// Set sampler uniform to the unit index
glUniform1i(glGetUniformLocation(prog, "uAlbedo"), unit);

// DSA binding (GL 4.5+)
glBindTextureUnit(unit, tex);  // no glActiveTexture needed

Samplers

A sampler object decouples filter/wrap state from the texture object.

GLuint sampler;
glGenSamplers(1, &sampler);
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_REPEAT);
glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY, 16.0f);

glBindSampler(unit, sampler);  // sampler overrides texture's own params
glDeleteSamplers(1, &sampler);

Shadow / Depth Texture Comparison

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
// Returns 0.0 or 1.0 (or filtered PCF result) from sampler2DShadow
uniform sampler2DShadow uShadowMap;
float shadow = texture(uShadowMap, vec3(uv, compareDepth));

Cube Maps

glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &tex);
glTextureStorage2D(tex, mips, GL_RGB8, width, height);

// Upload each face
GLenum faces[] = {
    GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
    GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
};
for (int i = 0; i < 6; i++) {
    // Can use glTextureSubImage3D with zoffset=i for cube maps
    glTextureSubImage3D(tex, 0, 0, 0, i, width, height, 1,
                        GL_RGB, GL_UNSIGNED_BYTE, faceData[i]);
}
glTextureParameteri(tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTextureParameteri(tex, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
uniform samplerCube uCubemap;
vec3 color = texture(uCubemap, direction).rgb;

Texture Arrays

glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &tex);
glTextureStorage3D(tex, mips, GL_RGBA8, width, height, layerCount);
glTextureSubImage3D(tex, 0, 0, 0, layer, width, height, 1,
                    GL_RGBA, GL_UNSIGNED_BYTE, data);
uniform sampler2DArray uAtlas;
vec4 color = texture(uAtlas, vec3(uv, float(tileIndex)));

Image Units (for Compute / Load-Store)

// Bind a texture level to an image unit for shader read/write
glBindImageTexture(
    /*unit=*/0, tex, /*level=*/0,
    /*layered=*/GL_FALSE, /*layer=*/0,
    GL_READ_WRITE,    // GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
    GL_RGBA32F        // must match texture internal format
);
layout(rgba32f, binding = 0) uniform image2D uImage;
vec4 v = imageLoad(uImage, ivec2(gl_GlobalInvocationID.xy));
imageStore(uImage, ivec2(gl_GlobalInvocationID.xy), v * 2.0);

GLSL Sampler Types

TypeTexture
sampler1D / sampler2D / sampler3D1D/2D/3D
samplerCubeCube map
sampler1DArray / sampler2DArray1D/2D array
samplerCubeArrayCube map array
sampler2DRectRectangle texture
sampler2DMS / sampler2DMSArrayMSAA
samplerBufferBuffer texture
sampler1DShadow / sampler2DShadowDepth comparison
samplerCubeShadowCube shadow
sampler2DArrayShadowArray shadow
isampler2D / usampler2DInteger / unsigned samplers

Pixel Transfer

// Readback (slow — causes pipeline stall)
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

// Async readback with PBO
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0); // 0 = offset into PBO
// ... next frame ...
void* ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
memcpy(dest, ptr, size);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);

// Async upload with PBO
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glTextureSubImage2D(tex, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

Bindless Textures (ARB_bindless_texture)

GLuint64 handle = glGetTextureHandleARB(tex);
glMakeTextureHandleResidentARB(handle);

// Pass handle to shader via uniform/SSBO
glUniformHandleui64ARB(loc, handle);
#extension GL_ARB_bindless_texture : enable
layout(location = 0) uniform sampler2D uTex; // handle passed as uvec2 internally

Gotcha: Always call glMakeTextureHandleNonResidentARB before deleting the texture; resident textures cannot be deleted.