Skip to main content

ImDrawCmd Structure

struct ImDrawCmd
{
    ImVec4          ClipRect;           // Clipping rectangle (x1, y1, x2, y2)
    ImTextureRef    TexRef;             // Texture reference
    unsigned int    VtxOffset;          // Start offset in vertex buffer
    unsigned int    IdxOffset;          // Start offset in index buffer
    unsigned int    ElemCount;          // Number of indices (multiple of 3)
    ImDrawCallback  UserCallback;       // Custom callback function
    void*           UserCallbackData;   // User data for callback
    
    ImTextureID GetTexID() const;       // Get texture ID for this command
};
Typically, 1 command = 1 GPU draw call (unless it’s a callback).
ClipRect
ImVec4
Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in viewport coordinates.
TexRef
ImTextureRef
Reference to font/texture atlas or user-provided texture ID.
VtxOffset
unsigned int
Start offset in vertex buffer. Always 0 unless ImGuiBackendFlags_RendererHasVtxOffset is enabled.
ElemCount
unsigned int
Number of indices to render (multiple of 3 for triangles).

Polygon Primitives

AddPolyline

void AddPolyline(const ImVec2* points, int num_points, ImU32 col, 
                 ImDrawFlags flags, float thickness);
Draw a polyline (connected line segments).
points
const ImVec2*
Array of points
num_points
int
Number of points in array
col
ImU32
Color
flags
ImDrawFlags
Flags (e.g., ImDrawFlags_Closed to close the polyline)
thickness
float
Line thickness
Example:
ImVec2 points[] = {
    ImVec2(100, 100),
    ImVec2(150, 150),
    ImVec2(200, 100),
    ImVec2(150, 50)
};
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddPolyline(points, 4, IM_COL32(255, 0, 0, 255), ImDrawFlags_Closed, 2.0f);

AddConvexPolyFilled

void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
Draw a filled convex polygon. Fast O(N) algorithm.
Only simple polygons are supported (no self-intersections, no holes). Polygon must be convex.

AddConcavePolyFilled

void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
Draw a filled concave polygon. Slower O(N²) algorithm.
Concave polygon fill is more expensive than convex. Only simple polygons are supported (no self-intersections, no holes).

Image Primitives

AddImage

void AddImage(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, 
              const ImVec2& uv_min = ImVec2(0, 0), const ImVec2& uv_max = ImVec2(1, 1), 
              ImU32 col = IM_COL32_WHITE);
Draw a textured rectangle.
tex_ref
ImTextureRef
Texture reference
p_min
const ImVec2&
Top-left corner position
p_max
const ImVec2&
Bottom-right corner position
uv_min
const ImVec2&
default:"(0, 0)"
Top-left UV coordinate
uv_max
const ImVec2&
default:"(1, 1)"
Bottom-right UV coordinate
col
ImU32
default:"IM_COL32_WHITE"
Tint color
Using (0,0)->(1,1) texture coordinates will generally display the entire texture.
Example:
ImDrawList* draw_list = ImGui::GetWindowDrawList();
ImVec2 p_min = ImGui::GetCursorScreenPos();
ImVec2 p_max = ImVec2(p_min.x + 100, p_min.y + 100);
draw_list->AddImage(my_texture, p_min, p_max);

AddImageQuad

void AddImageQuad(ImTextureRef tex_ref, 
                  const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, 
                  const ImVec2& uv1 = ImVec2(0, 0), const ImVec2& uv2 = ImVec2(1, 0), 
                  const ImVec2& uv3 = ImVec2(1, 1), const ImVec2& uv4 = ImVec2(0, 1), 
                  ImU32 col = IM_COL32_WHITE);
Draw a textured quadrilateral (allows perspective distortion).
p1, p2, p3, p4
const ImVec2&
Four corner positions
uv1, uv2, uv3, uv4
const ImVec2&
UV coordinates for each corner

AddImageRounded

void AddImageRounded(ImTextureRef tex_ref, const ImVec2& p_min, const ImVec2& p_max, 
                     const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, 
                     float rounding, ImDrawFlags flags = 0);
Draw a textured rectangle with rounded corners.
rounding
float
Corner rounding radius
flags
ImDrawFlags
Flags to control which corners are rounded

Path API

The path API allows building complex shapes by accumulating points, then rendering them.
Important: Filled shapes must always use clockwise winding order! Counter-clockwise shapes will have “inward” anti-aliasing.

PathClear

void PathClear();
Clear the current path (remove all accumulated points).

PathLineTo

void PathLineTo(const ImVec2& pos);
Add a point to the current path.
pos
const ImVec2&
Point position

PathLineToMergeDuplicate

void PathLineToMergeDuplicate(const ImVec2& pos);
Add a point to path only if it’s different from the last point.

PathFillConvex

void PathFillConvex(ImU32 col);
Fill the current path as a convex polygon and clear the path.
col
ImU32
Fill color

PathFillConcave

void PathFillConcave(ImU32 col);
Fill the current path as a concave polygon and clear the path. Slower than PathFillConvex().

PathStroke

void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f);
Stroke the current path and clear it.
col
ImU32
Stroke color
flags
ImDrawFlags
Flags (e.g., ImDrawFlags_Closed)
thickness
float
default:"1.0f"
Line thickness

Path Arcs

void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, 
               int num_segments = 0);

void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12);

void PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, 
                         float a_min, float a_max, int num_segments = 0);
Add arc segments to the path.
center
const ImVec2&
Arc center
radius
float
Arc radius
a_min
float
Start angle in radians
a_max
float
End angle in radians
PathArcToFast() uses precomputed angles for a 12-step circle. a_min_of_12 and a_max_of_12 are in range 0-11.

Path Bezier Curves

void PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, 
                            int num_segments = 0);

void PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0);
Add Bezier curve segments to the path. Example - Custom Shape with Path API:
ImDrawList* draw_list = ImGui::GetWindowDrawList();
ImVec2 center = ImGui::GetCursorScreenPos();

// Draw a star shape
draw_list->PathClear();
for (int i = 0; i < 10; i++)
{
    float angle = (i * 2.0f * IM_PI) / 10.0f;
    float radius = (i % 2 == 0) ? 40.0f : 20.0f;
    ImVec2 pos = ImVec2(
        center.x + cosf(angle) * radius,
        center.y + sinf(angle) * radius
    );
    draw_list->PathLineTo(pos);
}
draw_list->PathFillConvex(IM_COL32(255, 255, 0, 255));

PathRect

void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, 
              float rounding = 0.0f, ImDrawFlags flags = 0);
Add a rectangle to the path.

Advanced: Draw Callbacks

AddCallback

void AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size = 0);
Add a custom callback to alter render state or emit custom rendering commands.
callback
ImDrawCallback
Function pointer to callback
userdata
void*
User data to pass to callback
userdata_size
size_t
default:"0"
Size of data to copy (0 = just copy pointer)
Be mindful of the difference:
  • If userdata_size == 0: Copy/store the pointer as-is
  • If userdata_size > 0: Copy userdata_size bytes into an internal buffer
Example:
void MyCallback(const ImDrawList* parent_list, const ImDrawCmd* cmd)
{
    // Change render state
    MyEngine::SetBlendMode(BLEND_ADDITIVE);
}

draw_list->AddCallback(MyCallback, nullptr);
// ... draw commands with additive blending ...
draw_list->AddCallback(ImDrawCallback_ResetRenderState, nullptr);

AddDrawCmd

void AddDrawCmd();
Force creation of a new draw call. Useful for dependent rendering / blending. Otherwise primitives are merged into the same draw call.

Channels (Advanced)

Channels allow splitting render into layers that can be drawn out-of-order.
void ChannelsSplit(int count);
void ChannelsMerge();
void ChannelsSetCurrent(int n);
Prefer using your own persistent instance of ImDrawListSplitter instead of the channel functions.

See Also

Build docs developers (and LLMs) love