Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Polyline rendering #7972

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
4 changes: 4 additions & 0 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,7 @@ ImGuiStyle::ImGuiStyle()
AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU.
AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
LegacyPolyline = false; // Enable fallback to legacy AddPolyline() to trade feature and precission for speed.
CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.

Expand Down Expand Up @@ -4774,8 +4775,11 @@ static void SetupDrawListSharedData()
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex;
if (g.Style.AntiAliasedFill)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
if (g.Style.LegacyPolyline)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_LegacyPolyline;
if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
g.DrawListSharedData.InitialFringeScale = g.IO.DisplayFramebufferScale.x ? 1.0f / g.IO.DisplayFramebufferScale.x : 1.0f;
}

void ImGui::NewFrame()
Expand Down
26 changes: 23 additions & 3 deletions imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ struct ImDrawData; // All draw command lists required to render
struct ImDrawList; // A single draw command list (generally one per window, conceptually you may see this as a dynamic "mesh" builder)
struct ImDrawListSharedData; // Data shared among multiple draw lists (typically owned by parent ImGui context, but you may create one yourself)
struct ImDrawListSplitter; // Helper to split a draw list into different layers which can be drawn into out of order, then flattened back.
struct ImDrawListPolyline; // Helper to draw a polyline
struct ImDrawVert; // A single vertex (pos + uv + col = 20 bytes by default. Override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT)
struct ImFont; // Runtime data for a single font within a parent ImFontAtlas
struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader
Expand Down Expand Up @@ -2178,6 +2179,7 @@ struct ImGuiStyle
bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList).
bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
bool LegacyPolyline; // Enable fallback to legacy AddPolyline() to trade feature and precission for speed.
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
ImVec4 Colors[ImGuiCol_COUNT];
Expand Down Expand Up @@ -2998,6 +3000,18 @@ enum ImDrawFlags_
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
ImDrawFlags_JoinMiter = 1 << 9, // PathStroke(), AddPolyline(): join vertices with a sharp (i.e. not rounded) corner. When miter length exceed miter limit join is converted to Bevel
ImDrawFlags_JoinMiterClip = 2 << 9, // PathStroke(), AddPolyline(): as above but clipped at the miter limit (reduces visual artifacts at junctions)
ImDrawFlags_JoinBevel = 3 << 9, // PathStroke(), AddPolyline(): join vertices with a beveled corner (i.e. not rounded)
ImDrawFlags_JoinRound = 4 << 9, // PathStroke(), AddPolyline(): join vertices with a rounded corner
ImDrawFlags_JoinDefault_ = ImDrawFlags_JoinMiter, // Default to Miter join
ImDrawFlags_JoinMask_ = 7 << 9,
ImDrawFlags_CapNone = 1 << 12, // PathStroke(), AddPolyline(): do not render end caps
ImDrawFlags_CapButt = 2 << 12, // PathStroke(), AddPolyline(): render end caps as a rectangle for anti-aliased polyline, otherwise same as CapNone for aliased polyline
ImDrawFlags_CapSquare = 3 << 12, // PathStroke(), AddPolyline(): render end caps as a square
ImDrawFlags_CapRound = 4 << 12, // PathStroke(), AddPolyline(): render end caps as a semi-circle
ImDrawFlags_CapDefault_ = ImDrawFlags_CapNone, // Default to no cap
ImDrawFlags_CapMask_ = 7 << 12,
};

// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
Expand All @@ -3009,6 +3023,7 @@ enum ImDrawListFlags_
ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles).
ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled.
ImDrawListFlags_LegacyPolyline = 1 << 4, // (Legacy) For AddPolyline() to trade features and precission for a bit of extra performance.
};

// Draw command list
Expand Down Expand Up @@ -3081,8 +3096,9 @@ struct ImDrawList

// General polygon
// - Only simple polygons are supported by filling functions (no self-intersections, no holes).
// - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience fo user but not used by main library.
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
// - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience of user but not used by main library.
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness, float miter_limit = -1.0f);
IMGUI_API void AddPolylineLegacy(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);

Expand All @@ -3102,7 +3118,7 @@ struct ImDrawList
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
inline void PathFillConcave(ImU32 col) { AddConcavePolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; }
inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f, float miter_limit = -1.0f) { if (Flags & ImDrawListFlags_LegacyPolyline) AddPolylineLegacy(_Path.Data, _Path.Size, col, flags, thickness); else AddPolyline(_Path.Data, _Path.Size, col, flags, thickness, miter_limit); _Path.Size = 0; }
IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0);
IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
IMGUI_API void PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse
Expand Down Expand Up @@ -3156,6 +3172,10 @@ struct ImDrawList
IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const;
IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step);
IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments);
IMGUI_API void _PolylineEmitArcs(const ImDrawListPolyline& polyline, int arc_count, float core_radius, float fringe_radius);
IMGUI_API void _PolylineThinAntiAliased(const ImDrawListPolyline& polyline);
IMGUI_API void _PolylineThickAntiAliased(const ImDrawListPolyline& polyline);
IMGUI_API void _PolylineAliased(const ImDrawListPolyline& polyline);
};

// All draw data to render a Dear ImGui frame
Expand Down
7 changes: 6 additions & 1 deletion imgui_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8021,6 +8021,11 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");

ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);

ImGui::Checkbox("Legacy polyline", &style.LegacyPolyline);
ImGui::SameLine();
HelpMarker("Legacy polyline is faster for drawing lots of geometry, but does lack of features and robustness.");

ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
Expand Down Expand Up @@ -9351,7 +9356,7 @@ static void ShowExampleAppCustomRendering(bool* p_open)
static int curve_segments_override_v = 8;
static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 100.0f, "%.0f");
ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
ImGui::DragFloat("Thickness", &thickness, 0.05f, 0.0f, 8.0f, "%.02f");
ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
Expand Down
Loading
Loading