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
| Target | Meaning |
|---|---|
GL_FRAMEBUFFER | Both read and draw (most common) |
GL_DRAW_FRAMEBUFFER | Draw target only (glClear, draw calls) |
GL_READ_FRAMEBUFFER | Read target only (glReadPixels, glBlitFramebuffer) |
Attachment Points
| Attachment | Connected to |
|---|---|
GL_COLOR_ATTACHMENT0 … GL_COLOR_ATTACHMENT(n-1) | Color buffers (n = GL_MAX_COLOR_ATTACHMENTS) |
GL_DEPTH_ATTACHMENT | Depth buffer |
GL_STENCIL_ATTACHMENT | Stencil buffer |
GL_DEPTH_STENCIL_ATTACHMENT | Combined depth+stencil |
Framebuffer Completeness
glCheckFramebufferStatus returns one of:
| Status | Meaning |
|---|---|
GL_FRAMEBUFFER_COMPLETE | Ready to use |
GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT | An attachment is not complete |
GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT | No attachment present |
GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER | Draw buffer references missing attachment |
GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER | Read buffer references missing attachment |
GL_FRAMEBUFFER_UNSUPPORTED | Format combination not supported by driver |
GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE | Mixed MSAA sample counts |
GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS | Inconsistent 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. OnlyGL_COLOR_BUFFER_BITsupportsGL_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);