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

Custom draw list - shape isn't rendered #6406

Closed
pavledev opened this issue May 5, 2023 · 5 comments
Closed

Custom draw list - shape isn't rendered #6406

pavledev opened this issue May 5, 2023 · 5 comments

Comments

@pavledev
Copy link

pavledev commented May 5, 2023

Version/Branch of Dear ImGui:

Version: 1.89.2
Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_win32.cpp + imgui_impl_dx11.cpp
Compiler: VS2022
Operating System: Windows 10

My Issue/Question:

I am trying to create custom draw list and I took code from here #1878 and I modified it for directx 11 but when I run app I don't see circle. Why it doesn't render circle?

ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();

static ImVec4 backgroundColor = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
static const float clearColorWithAlpha[4] = { backgroundColor.x * backgroundColor.w, backgroundColor.y * backgroundColor.w, backgroundColor.z * backgroundColor.w, backgroundColor.w };

d3dDeviceContext->ClearRenderTargetView(mainRenderTargetView, clearColorWithAlpha);
d3dDeviceContext->OMSetRenderTargets(1, &mainRenderTargetView, depthStencilView);

static ImDrawData drawData = ImDrawData();
drawData.DisplayPos = ImVec2(0, 0);
drawData.DisplaySize = ImVec2(viewport.Width, viewport.Height);
 drawData.FramebufferScale = ImVec2(1.0f, 1.0f);

static ImDrawListSharedData sharedData;
sharedData.ClipRectFullscreen = ImVec4(0, 0, viewport.Width, viewport.Height);
auto* drawList = new ImDrawList(&sharedData);

if (drawList->CmdBuffer.size() == 0)
    drawList->AddDrawCmd();

drawList->PushClipRectFullScreen();
drawList->PushTextureID(ImGui::GetDefaultFont()->ContainerAtlas->TexID);
drawList->AddText(ImGui::GetDefaultFont(), 13, ImVec2(10, 200), ImColor(0, 0, 0, 255), "Test Standalone ImGui DrawList");
drawList->PopTextureID();
drawList->PopClipRect();
drawList->AddCircleFilled(ImVec2(100, 100), 100, ImColor(122, 110, 80, 255), 12);

drawData.CmdLists = &drawList;
drawData.CmdListsCount = 1;
drawData.TotalIdxCount = drawList->IdxBuffer.size();
drawData.TotalVtxCount = drawList->VtxBuffer.size();
drawData.Valid = true;

ImGui_ImplDX11_RenderDrawData(&drawData);
delete drawList;

image

@pavledev pavledev changed the title Invisible shape Custom draw list - shape isn't rendered May 6, 2023
@ocornut
Copy link
Owner

ocornut commented May 25, 2023

Hello Pavle,

You are creating your own ImDrawListSharedData instance but it isn't setup properly.
It's quite complicated to setup but generally you can use ImGui's one ImGui::GetDrawListSharedData().

This works:

{
    // Create once
    static ImDrawList* drawList = new ImDrawList(ImGui::GetDrawListSharedData());

    // Init for the frame
    // (no need to PopTextureID()/PopClipRect()) since we reset every frame
    drawList->_ResetForNewFrame();
    drawList->PushClipRectFullScreen();
    drawList->PushTextureID(io.Fonts->TexID);

    // Submit contents
    drawList->AddText(ImGui::GetFont(), 13, ImVec2(10, 200), IM_COL32_WHITE, "Test Standalone ImGui DrawList");
    drawList->AddCircleFilled(ImVec2(100, 100), 100, ImColor(122, 110, 80, 255));

    // Create ImDrawData
    static ImDrawData drawData = ImDrawData();
    drawData.DisplayPos = ImGui::GetMainViewport()->Pos;
    drawData.DisplaySize = ImGui::GetMainViewport()->Size;
    drawData.FramebufferScale = ImVec2(1.0f, 1.0f);
    drawData.CmdLists = &drawList;
    drawData.CmdListsCount = 1;
    drawData.TotalIdxCount = drawList->IdxBuffer.size();
    drawData.TotalVtxCount = drawList->VtxBuffer.size();
    drawData.Valid = true;

    ImGui_ImplDX11_RenderDrawData(&drawData);
}

Note that:

  • Code is a little simpler.
  • Your AddCircleFilled() call was OUTSIDE the PushClipRectFullScreen() + PushTextureID() block. This texture atlas is required for shapes and not only fonts.
  • I am reusing ImDrawList instance. Creating one every frame is going to be very costly as it is designed to reuse/amortize buffer allocations.

Linking to #4586 and #1878.

I think we should later aim to make this simpler, by e.g. making it easier to create a ImDrawData or even append to an existing ImDrawData. Will post here if we can bring further simplications.

@ocornut
Copy link
Owner

ocornut commented Jul 12, 2023

I made changes in IMGUI_VERSION = "1.89.8 WIP", IMGUI_VERSION_NUM = 18973
Commits c649aca + 1a9ddd2 + dbeeeae

The example suggested above in #6406 (comment) won't compile anymore as one cannot assign ImDrawList::CmdLists directly, however the new version is now simpler:

{
    // Create once
    static ImDrawList* drawList = new ImDrawList(ImGui::GetDrawListSharedData());

    // Init for the frame
    // (no need to PopTextureID()/PopClipRect()) since we reset every frame
    drawList->_ResetForNewFrame();
    drawList->PushClipRectFullScreen();
    drawList->PushTextureID(io.Fonts->TexID);

    // Submit contents
    drawList->AddText(ImGui::GetFont(), 13, ImVec2(10, 200), IM_COL32_WHITE, "Test Standalone ImGui DrawList");
    drawList->AddCircleFilled(ImVec2(100, 100), 100, ImColor(122, 110, 80, 255));

    // Create ImDrawData
    static ImDrawData drawData = ImDrawData();
    drawData.Clear();
    drawData.Valid = true;
    drawData.DisplayPos = ImGui::GetMainViewport()->Pos;
    drawData.DisplaySize = ImGui::GetMainViewport()->Size;
    drawData.FramebufferScale = ImVec2(1.0f, 1.0f);
    drawData.AddDrawList(drawList);

    ImGui_ImplDX11_RenderDrawData(&drawData);
}

That's a create a full entire separate ImDrawData and renders it.

However you can also add to the existing ImDrawData:

{
    ImDrawData* draw_data = ImGui::GetDrawData();

    // Create once
    static ImDrawList* drawList = new ImDrawList(ImGui::GetDrawListSharedData());

    // Init for the frame
    // (no need to PopTextureID()/PopClipRect()) since we reset every frame
    drawList->_ResetForNewFrame();
    drawList->PushClipRectFullScreen();
    drawList->PushTextureID(io.Fonts->TexID);

    // Submit contents
    drawList->AddText(ImGui::GetFont(), 13, ImVec2(10, 200), IM_COL32_WHITE, "Test Standalone ImGui DrawList");
    drawList->AddCircleFilled(ImVec2(100, 100), 100, ImColor(122, 110, 80, 255));

    draw_data->AddDrawList(drawList);

    ImGui_ImplDX11_RenderDrawData(draw_data);
}

ocornut added a commit that referenced this issue Jul 12, 2023
…DrawData itself. Faclitate user-manipulation of the array (#6406, #4879, #1878) + deep swap. (#6597, #6475, #6167, #5776, #5109, #4763, #3515, #1860)

+ Metrics: avoid misleadingly iterating all layers of DrawDataBuilder as everything is flattened into Layers[0] at this point.

# Conflicts:
#	imgui.cpp
#	imgui_internal.h
ocornut added a commit that referenced this issue Jul 12, 2023
…rawList(). (#6406, #4879, #1878)

# Conflicts:
#	imgui.cpp
#	imgui_internal.h
ocornut added a commit that referenced this issue Jul 12, 2023
…s() rely on a valid command being there (especially in docking branch). (#6406, #4879, #1878)

Amend/fix dbeeeae for docking.
+ Build fix when using IMGUI_DISABLE_DEBUG_TOOLS
ocornut added a commit that referenced this issue Jul 12, 2023
…s() rely on a valid command being there (especially in docking branch). (#6406, #4879, #1878)

Amend/fix dbeeeae for docking.
+ Build fix when using IMGUI_DISABLE_DEBUG_TOOLS
@srwee
Copy link

srwee commented Sep 16, 2023

Hello, i want to swap one custom drawlist data to another and im using ImGui 18990 on win32_dx9 backend and this code result both linked below assertions for me after i use operator= on the drawlists, i guess there is a more proper way to do it?

https://github.com/ocornut/imgui/blob/master/imgui_draw.cpp#L1873-L1874

 // init drawlists once
 static ImDrawList* pThreadDrawList = new ImDrawList(ImGui::GetDrawListSharedData( ));
 static ImDrawList* pSafeDrawList = new ImDrawList(ImGui::GetDrawListSharedData( ));

 // should be somewhere, but now its in main function
 {
     pThreadDrawList->_ResetForNewFrame( );
     pThreadDrawList->PushClipRectFullScreen( );
     pThreadDrawList->PushTextureID(io.Fonts->TexID);

     // draw things
     pThreadDrawList->AddText(ImGui::GetFont( ), 13, ImVec2(10, 200), IM_COL32_WHITE, "Test Standalone ImGui DrawList");
     pThreadDrawList->AddCircleFilled(ImVec2(100, 100), 100, ImColor(122, 110, 80, 255));

     *pSafeDrawList = *pThreadDrawList; // results assertion, otherwise drawlist not being rendered obviously
 };

 ImDrawData* pDrawData= ImGui::GetDrawData( );
 pDrawData->AddDrawList(pSafeDrawList);
 ImGui_ImplDX9_RenderDrawData(pDrawData);

Thanks!

@ocornut
Copy link
Owner

ocornut commented Sep 16, 2023

There’s no = operator and you shouldn’t have to deep copy a ImDrawList this is going to be wasteful.

i want to swap one custom drawlist data to another

You always need to explain yourself and others WHY you are intending to do this.

I’m making guesses since you are not explaining your actual problem, but I believe your approach should be reworked as : when you are done with a drawlist and want to pass it to another thread, stop writing into it. In that situation you may eg instead swap pointers. But you may need better synchronization mechanism if those threads are working in parallel.

@srwee
Copy link

srwee commented Sep 16, 2023

There’s no = operator and you shouldn’t have to deep copy a ImDrawList this is going to be wasteful.

i want to swap one custom drawlist data to another

You always need to explain yourself and others WHY you are intending to do this.

I’m making guesses since you are not explaining your actual problem, but I believe your approach should be reworked as : when you are done with a drawlist and want to pass it to another thread, stop writing into it. In that situation you may eg instead swap pointers. But you may need better synchronization mechanism if those threads are working in parallel.

Sorry, im trying to implement thread-safe rendering drawlist, but for now, as im getting those assertions, im using single threaded imgui's backend test application.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants