These functions form the backbone of the Dear ImGui render loop. Call them in sequence each frame to process input, build your UI, and generate draw commands for rendering.
Frame Lifecycle
The typical Dear ImGui frame consists of:
- NewFrame() - Start a new frame, process input
- UI Code - Build your user interface
- Render() - Finalize draw data
- GetDrawData() - Retrieve draw commands
- Backend Rendering - Submit to graphics API
while (running) {
ImGui::NewFrame();
// Your UI code here
ImGui::Begin("My Window");
ImGui::Text("Hello, world!");
ImGui::End();
ImGui::Render();
ImGui_ImplXXX_RenderDrawData(ImGui::GetDrawData());
}
NewFrame
Starts a new Dear ImGui frame. Call this at the beginning of each frame before submitting any UI commands.
Description
This function:
- Processes input from
ImGuiIO (mouse, keyboard, gamepad)
- Updates internal state and timing
- Prepares for new UI commands
- Clears the previous frame’s data
Example
void GameLoop() {
while (!glfwWindowShouldClose(window)) {
// Poll events and update ImGui backends
glfwPollEvents();
ImGui_ImplGlfw_NewFrame();
ImGui_ImplOpenGL3_NewFrame();
// Start Dear ImGui frame
ImGui::NewFrame();
// Build UI
ImGui::ShowDemoWindow();
// Render
ImGui::Render();
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
}
Always call your backend’s NewFrame() functions (e.g., ImGui_ImplGlfw_NewFrame()) before calling ImGui::NewFrame().
EndFrame
Ends the Dear ImGui frame. Automatically called by Render(), but can be called manually if you want to skip rendering.
Description
This function:
- Finalizes the current frame’s state
- Updates window positions and sizes
- Handles end-of-frame operations
If you call EndFrame() without rendering, you’ll waste CPU cycles. It’s better to not create any windows and skip NewFrame() entirely if you don’t need to render.
Example
// Skip rendering when window is minimized
if (isMinimized) {
ImGui::NewFrame();
ImGui::EndFrame();
// Don't call Render() or GetDrawData()
} else {
ImGui::NewFrame();
// ... UI code ...
ImGui::Render();
ImGui_ImplXXX_RenderDrawData(ImGui::GetDrawData());
}
Render
Ends the Dear ImGui frame and finalizes draw data. Call this after submitting all UI commands.
Description
This function:
- Calls
EndFrame() internally
- Finalizes all draw lists
- Prepares
ImDrawData for rendering
- Sorts draw commands by texture and layer
Example
ImGui::NewFrame();
// Build your UI
ImGui::Begin("Control Panel");
ImGui::Button("Click Me");
ImGui::End();
ImGui::Begin("Debug Info");
ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate);
ImGui::End();
// Finalize frame
ImGui::Render();
// Now you can retrieve draw data
ImDrawData* draw_data = ImGui::GetDrawData();
You must call Render() before calling GetDrawData(). The draw data is only valid after finalization.
GetDrawData
Retrieves the draw data generated by the current frame. Pass this to your rendering backend.
ImDrawData* GetDrawData();
Returns
Pointer to the draw data structure containing all draw commands for the frame. Returns NULL if Render() hasn’t been called yet.
Description
The returned ImDrawData contains:
- All draw commands organized by command lists
- Vertex and index buffers
- Texture bindings
- Clipping rectangles
- Display position and size
Example
// After calling Render()
ImDrawData* draw_data = ImGui::GetDrawData();
if (draw_data != nullptr) {
// Pass to your rendering backend
ImGui_ImplOpenGL3_RenderDrawData(draw_data);
// or
ImGui_ImplDX11_RenderDrawData(draw_data);
// or
ImGui_ImplVulkan_RenderDrawData(draw_data);
}
Validation
ImDrawData* draw_data = ImGui::GetDrawData();
if (draw_data && draw_data->Valid) {
printf("Total draw commands: %d\n", draw_data->TotalVtxCount);
printf("Display size: %.0fx%.0f\n",
draw_data->DisplaySize.x,
draw_data->DisplaySize.y);
for (int n = 0; n < draw_data->CmdListsCount; n++) {
const ImDrawList* cmd_list = draw_data->CmdLists[n];
printf("Command list %d: %d vertices, %d indices\n",
n, cmd_list->VtxBuffer.Size, cmd_list->IdxBuffer.Size);
}
}
The draw data is only valid until the next call to NewFrame(). Don’t cache this pointer across frames.
Complete Example
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <GLFW/glfw3.h>
int main() {
// Initialize GLFW and OpenGL
glfwInit();
GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui Example", NULL, NULL);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
// Setup backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 130");
// Main loop
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
// Start ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Build UI
ImGui::Begin("Hello, ImGui!");
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
1000.0f / io.Framerate, io.Framerate);
ImGui::End();
// Render
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
}
// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}