OpenGL Cheatsheet

Framebuffers

Use this OpenGL reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Framebuffer Basics

The default framebuffer is provided by the windowing system (GLFW). Custom framebuffer objects (FBOs) let you render to textures or renderbuffers.

GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);  // binds for both read and draw

// Attach a texture
glFramebufferTexture2D(GL_FRAMEBUFFER,
                       GL_COLOR_ATTACHMENT0,
                       GL_TEXTURE_2D, colorTex, /*mip=*/0);

// Attach a renderbuffer for depth
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                          GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);

// Check completeness (must check before first use)
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) { /* handle error */ }

glBindFramebuffer(GL_FRAMEBUFFER, 0);  // rebind default framebuffer

DSA (GL 4.5+) — preferred

GLuint fbo;
glCreateFramebuffers(1, &fbo);
glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, colorTex, 0);
glNamedFramebufferRenderbuffer(fbo, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
GLenum status = glCheckNamedFramebufferStatus(fbo, GL_FRAMEBUFFER);

Framebuffer Bind Targets

TargetMeaning
GL_FRAMEBUFFERBoth read and draw (most common)
GL_DRAW_FRAMEBUFFERDraw target only (glClear, draw calls)
GL_READ_FRAMEBUFFERRead target only (glReadPixels, glBlitFramebuffer)

Attachment Points

AttachmentConnected to
GL_COLOR_ATTACHMENT0GL_COLOR_ATTACHMENT(n-1)Color buffers (n = GL_MAX_COLOR_ATTACHMENTS)
GL_DEPTH_ATTACHMENTDepth buffer
GL_STENCIL_ATTACHMENTStencil buffer
GL_DEPTH_STENCIL_ATTACHMENTCombined depth+stencil

Framebuffer Completeness

glCheckFramebufferStatus returns one of:

StatusMeaning
GL_FRAMEBUFFER_COMPLETEReady to use
GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENTAn attachment is not complete
GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENTNo attachment present
GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFERDraw buffer references missing attachment
GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFERRead buffer references missing attachment
GL_FRAMEBUFFER_UNSUPPORTEDFormat combination not supported by driver
GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLEMixed MSAA sample counts
GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETSInconsistent layered attachments

Renderbuffer Objects (RBO)

Renderbuffers are faster than textures for attachments you don't need to sample (depth, stencil).

GLuint rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
                          GL_RENDERBUFFER, rbo);

// MSAA renderbuffer
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, w, h);

// DSA
glCreateRenderbuffers(1, &rbo);
glNamedRenderbufferStorage(rbo, GL_DEPTH24_STENCIL8, width, height);
glNamedRenderbufferStorageMultisample(rbo, 4, GL_DEPTH24_STENCIL8, w, h);

Attaching Textures

// 2D texture
glFramebufferTexture2D(target, attachment, GL_TEXTURE_2D, tex, mipLevel);

// Cube map face
glFramebufferTexture2D(target, attachment,
                       GL_TEXTURE_CUBE_MAP_POSITIVE_X, tex, 0);

// Layered attachment — geometry shader selects gl_Layer
glFramebufferTexture(target, attachment, tex, mipLevel);

// Specific layer of a 3D or array texture
glFramebufferTextureLayer(target, attachment, tex, mipLevel, layer);

// DSA versions
glNamedFramebufferTexture(fbo, attachment, tex, mipLevel);
glNamedFramebufferTextureLayer(fbo, attachment, tex, mipLevel, layer);

Multiple Render Targets (MRT)

Write to multiple color attachments simultaneously (used in deferred rendering).

// Tell which attachments are active draw buffers
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, drawBuffers);  // or glNamedFramebufferDrawBuffers(fbo, 3, drawBuffers)
// Fragment shader — write to each
layout(location = 0) out vec4 gPosition;
layout(location = 1) out vec3 gNormal;
layout(location = 2) out vec4 gAlbedoSpec;
// Select which attachment to read from
glReadBuffer(GL_COLOR_ATTACHMENT0);          // for FBO
glNamedFramebufferReadBuffer(fbo, GL_COLOR_ATTACHMENT0);

Blitting Between Framebuffers

Copies a region from the read FBO to the draw FBO — supports format conversion and multi-sample resolve.

glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFBO);
glBlitFramebuffer(
    srcX0, srcY0, srcX1, srcY1,   // source rectangle
    dstX0, dstY0, dstX1, dstY1,   // destination rectangle
    mask,                           // GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT
    filter                          // GL_LINEAR or GL_NEAREST (depth/stencil must use GL_NEAREST)
);

// DSA
glBlitNamedFramebuffer(srcFBO, dstFBO, /* same args */);

Gotcha: Depth and stencil blits require GL_NEAREST. Only GL_COLOR_BUFFER_BIT supports GL_LINEAR.

Reading Pixels

// Synchronous (causes GPU stall — avoid in render loop)
glReadBuffer(GL_BACK);  // or GL_COLOR_ATTACHMENTn for FBO
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

// Asynchronous via PBO (pipeline-friendly)
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0); // async
// ... do other work ...
void* data = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
memcpy(dest, data, size);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);

Post-Processing Pipeline

// Full-screen quad FBO pass
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderScene();                          // writes to colorTex

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(postProcessProg);
glBindTextureUnit(0, colorTex);
drawFullScreenTriangle();               // applies effect
// Full-screen vertex shader (no VBO needed)
void main() {
    vec2 positions[3] = vec2[](vec2(-1,-1), vec2(3,-1), vec2(-1,3));
    vec2 uvs[3]       = vec2[](vec2(0,0),   vec2(2,0),  vec2(0,2));
    vUV        = uvs[gl_VertexID];
    gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0);
}

MSAA Framebuffer

// Create MSAA color texture
glCreateTextures(GL_TEXTURE_2D_MULTISAMPLE, 1, &msTex);
glTextureStorage2DMultisample(msTex, 4, GL_RGBA8, width, height, GL_TRUE);

// Create MSAA FBO
glCreateFramebuffers(1, &msFBO);
glNamedFramebufferTexture(msFBO, GL_COLOR_ATTACHMENT0, msTex, 0);

GLuint msRBO;
glCreateRenderbuffers(1, &msRBO);
glNamedRenderbufferStorageMultisample(msRBO, 4, GL_DEPTH24_STENCIL8, width, height);
glNamedFramebufferRenderbuffer(msFBO, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, msRBO);

// Resolve to single-sample FBO
glBlitNamedFramebuffer(msFBO, resolveFBO,
    0, 0, width, height, 0, 0, width, height,
    GL_COLOR_BUFFER_BIT, GL_NEAREST);

Framebuffer Invalidation

Tells the driver it can discard contents (especially useful on tiled GPUs / mobile).

GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
glInvalidateSubFramebuffer(GL_FRAMEBUFFER, 2, attachments, x, y, w, h);
glInvalidateNamedFramebufferData(fbo, 2, attachments);

Framebuffer Parameters (GL 4.3+)

Set FBO size/samples without any attachments (useful for layered/sparse rendering).

glNamedFramebufferParameteri(fbo, GL_FRAMEBUFFER_DEFAULT_WIDTH,  800);
glNamedFramebufferParameteri(fbo, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 600);
glNamedFramebufferParameteri(fbo, GL_FRAMEBUFFER_DEFAULT_SAMPLES, 4);
glNamedFramebufferParameteri(fbo, GL_FRAMEBUFFER_DEFAULT_LAYERS,  6);

Common FBO Configurations

Color-only (no depth)

glCreateTextures(GL_TEXTURE_2D, 1, &colorTex);
glTextureStorage2D(colorTex, 1, GL_RGBA8, w, h);
glCreateFramebuffers(1, &fbo);
glNamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0, colorTex, 0);
// No depth attachment — disable depth test when rendering to this FBO

Depth-only (shadow map)

glCreateTextures(GL_TEXTURE_2D, 1, &depthTex);
glTextureStorage2D(depthTex, 1, GL_DEPTH_COMPONENT24, w, h);
glTextureParameteri(depthTex, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTextureParameteri(depthTex, GL_TEXTURE_COMPARE_FUNC, GL_LESS);

glCreateFramebuffers(1, &shadowFBO);
glNamedFramebufferTexture(shadowFBO, GL_DEPTH_ATTACHMENT, depthTex, 0);

GLenum none = GL_NONE;
glNamedFramebufferDrawBuffers(shadowFBO, 1, &none);
glNamedFramebufferReadBuffer(shadowFBO, GL_NONE);

HDR color + depth

glCreateTextures(GL_TEXTURE_2D, 1, &hdrTex);
glTextureStorage2D(hdrTex, 1, GL_RGBA16F, w, h);  // float for HDR values

glCreateRenderbuffers(1, &rbo);
glNamedRenderbufferStorage(rbo, GL_DEPTH24_STENCIL8, w, h);

glCreateFramebuffers(1, &hdrFBO);
glNamedFramebufferTexture(hdrFBO, GL_COLOR_ATTACHMENT0, hdrTex, 0);
glNamedFramebufferRenderbuffer(hdrFBO, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

Cube map FBO (for point shadows / env capture)

glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &cubeTex);
glTextureStorage2D(cubeTex, 1, GL_DEPTH_COMPONENT24, w, h);
glCreateFramebuffers(1, &cubeFBO);
// Layered attachment — geometry shader renders all 6 faces in one pass
glNamedFramebufferTexture(cubeFBO, GL_DEPTH_ATTACHMENT, cubeTex, 0);
GLenum none = GL_NONE;
glNamedFramebufferDrawBuffers(cubeFBO, 1, &none);
glNamedFramebufferReadBuffer(cubeFBO, GL_NONE);

Cleanup

glDeleteFramebuffers(1, &fbo);
glDeleteRenderbuffers(1, &rbo);
// Textures attached to FBOs are NOT auto-deleted — delete manually
glDeleteTextures(1, &colorTex);