mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-04 03:58:47 +02:00
ImDrawList: Added ImDrawCmd::VtxOffset value to support large meshes (64k+ vertices) using 16-bits indices. To enable the feature, the renderer back-end needs to set 'io.BackendFlags |= ImGuiBackendFlags_HasVtxOffset' and honor the ImDrawCmd::VtxOffset field. Otherwise the value will always be zero. This has the advantage of preserving smaller index buffers and allowing to execute on hardware that do not support 32-bits indices.
ImDrawList: Added ImDrawCmd::IdxOffset value, equivalent to summing element count for each draw command. This is provided for convenience and consistency with VtxOffset. (#2591)
This commit is contained in:
44
imgui.cpp
44
imgui.cpp
@ -3502,7 +3502,13 @@ void ImGui::NewFrame()
|
||||
IM_ASSERT(g.Font->IsLoaded());
|
||||
g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
|
||||
g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
|
||||
g.DrawListSharedData.InitialFlags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
|
||||
g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
|
||||
if (g.Style.AntiAliasedLines)
|
||||
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
|
||||
if (g.Style.AntiAliasedFill)
|
||||
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
|
||||
if (g.IO.BackendFlags & ImGuiBackendFlags_HasVtxOffset)
|
||||
g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
|
||||
|
||||
g.BackgroundDrawList.Clear();
|
||||
g.BackgroundDrawList.PushTextureID(g.IO.Fonts->TexID);
|
||||
@ -3774,19 +3780,28 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. May trigger for you if you are using PrimXXX functions incorrectly.
|
||||
// Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
||||
// May trigger for you if you are using PrimXXX functions incorrectly.
|
||||
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
|
||||
IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
|
||||
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
|
||||
if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset))
|
||||
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
|
||||
|
||||
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
|
||||
// If this assert triggers because you are drawing lots of stuff manually:
|
||||
// A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use the Metrics window to inspect draw list contents.
|
||||
// B) If you need/want meshes with more than 64K vertices, uncomment the '#define ImDrawIdx unsigned int' line in imconfig.h to set the index size to 4 bytes.
|
||||
// You'll need to handle the 4-bytes indices to your renderer. For example, the OpenGL example code detect index size at compile-time by doing:
|
||||
// glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
// Your own engine or render API may use different parameters or function calls to specify index sizes. 2 and 4 bytes indices are generally supported by most API.
|
||||
// C) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists.
|
||||
// - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
|
||||
// Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents.
|
||||
// - If you want large meshes with more than 64K vertices, you can either:
|
||||
// (A) Handle the ImDrawCmd::VtxOffset value in your renderer back-end, and set 'io.BackendFlags |= ImGuiBackendFlags_HasVtxOffset'.
|
||||
// Most example back-ends already support this from 1.71. Pre-1.71 back-ends won't.
|
||||
// Some graphics API such as GL ES 1/2 don't have a way to offset the starting vertex so it is not supported for them.
|
||||
// (B) Or handle 32-bits indices in your renderer back-end, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h.
|
||||
// Most example back-ends already support this. For example, the OpenGL example code detect index size at compile-time:
|
||||
// glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
||||
// Your own engine or render API may use different parameters or function calls to specify index sizes.
|
||||
// 2 and 4 bytes indices are generally supported by most graphics API.
|
||||
// - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
|
||||
// the 64K limit to split your draw commands in multiple draw lists.
|
||||
if (sizeof(ImDrawIdx) == 2)
|
||||
IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
|
||||
|
||||
@ -9790,9 +9805,10 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
continue;
|
||||
}
|
||||
ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
|
||||
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()),
|
||||
"Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
|
||||
pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", (void*)(intptr_t)pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
|
||||
char buf[300];
|
||||
ImFormatString(buf, IM_ARRAYSIZE(buf), "Draw %4d triangles, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
|
||||
pcmd->ElemCount/3, (void*)(intptr_t)pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
|
||||
bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf);
|
||||
if (show_drawcmd_clip_rects && fg_draw_list && ImGui::IsItemHovered())
|
||||
{
|
||||
ImRect clip_rect = pcmd->ClipRect;
|
||||
@ -9806,11 +9822,11 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
continue;
|
||||
|
||||
// Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
|
||||
ImGui::Text("ElemCount: %d, ElemCount/3: %d, VtxOffset: +%d, IdxOffset: +%d", pcmd->ElemCount, pcmd->ElemCount/3, pcmd->VtxOffset, pcmd->IdxOffset);
|
||||
ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
|
||||
while (clipper.Step())
|
||||
for (int prim = clipper.DisplayStart, idx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++)
|
||||
{
|
||||
char buf[300];
|
||||
char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf);
|
||||
ImVec2 triangles_pos[3];
|
||||
for (int n = 0; n < 3; n++, idx_i++)
|
||||
@ -9819,7 +9835,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImDrawVert& v = draw_list->VtxBuffer[vtx_i];
|
||||
triangles_pos[n] = v.pos;
|
||||
buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n",
|
||||
(n == 0) ? "idx" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
|
||||
(n == 0) ? "elem" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
|
||||
}
|
||||
ImGui::Selectable(buf, false);
|
||||
if (fg_draw_list && ImGui::IsItemHovered())
|
||||
|
Reference in New Issue
Block a user