mosra / magnum-integration

Integration libraries for the Magnum C++11 graphics engine
https://magnum.graphics/
Other
99 stars 45 forks source link

Binding Images to Texture2D and then render using ImGui::Image() #108

Closed TrevorCash closed 2 months ago

TrevorCash commented 2 months ago

Hello,

I am trying to bind an image to a texture and then render using ImGui::Image() call.

The Code I am using is below (which loads a png image and then binds to texture when the button is pushed)

if (ImGui::Button("Load Test Zip Resource")) {
    auto manager = ControlSingleton::GetInstance()->zipResourceManager;
    size_t size;
    auto data = manager->AccessResource("product-icon.png", size);

    Magnum::PluginManager::Manager<Magnum::Trade::AbstractImporter> impManager;
    impManager.setPluginDirectory(getRuntimeDependancyPath());
    Magnum::Containers::Pointer<Magnum::Trade::AbstractImporter> importer =
            impManager.loadAndInstantiate("PngImporter");

    Corrade::Containers::ArrayView<char> dataView{data, size};

    bool s = importer->openData(dataView);

    auto image = importer->image2D(0);
    CORRADE_INTERNAL_ASSERT(image);
    logoTexture.setWrapping(Magnum::GL::SamplerWrapping::ClampToEdge)
            .setMagnificationFilter(Magnum::GL::SamplerFilter::Linear)
            .setMinificationFilter(Magnum::GL::SamplerFilter::Linear)
            .setStorage(1, Magnum::GL::textureFormat(image->format()), image->size())
            .setSubImage(0, {}, *image);

}
if(logoTexture.imageSize(0).x() > 0)
    ImGui::Image(ImTextureID(logoTexture.id()), ImVec2(100, 100));

The above code works fine.

later when imgui is drawn. in MagnumImGuiIntegration / Context.cpp / drawFrame()

I get a crash at this call (line 366) _shader .bindTexture(static_cast<GL::Texture2D>(pcmd->TextureId)) .draw(_mesh);

I think it may not be correctly converting to GL::Texture2D from pcmd->TextureId (which is 0x2)

Call stack

MagnumGL-d.dll!Magnum::GL::AbstractTexture::bind(int textureUnit) Line 344 C++ MagnumShaders-d.dll!Magnum::Shaders::FlatGL<2>::bindTexture(Magnum::GL::Texture<2> & texture) Line 772 C++ MagnumImGuiIntegration-d.dll!Magnum::ImGuiIntegration::Context::drawFrame() Line 366 C++ HC_API_Library_NATIVE.dll!Magnum::Examples::ControlInterfaceApp::drawEvent() Line 452 C++ HC_API_Library_NATIVE.dll!Magnum::Platform::GlfwApplication::mainLoopIteration() Line 784 C++ HC_API_Library_NATIVE.dll!ControlAPI::controlGuiInterface::update() Line 564 C++ HC_API_ControlStudio.exe!main() Line 30 C++ [External Code]

Is there some other step I should be doing to get a image to render with ImGui? I keep 1 Texture2D object around at all times.

Thanks for any help/tips in advance.

-Trevor

mosra commented 2 months ago

The code inside ImGuiIntegration assumes the texture ID is actually a pointer to the texture object, not the underlying OpenGL ID (which is possibly a bit silly, but that's what it is).

If you use the ImGuiIntegration::image() helper instead of ImGui::Image(), which wraps this in a safe way, it should work.

TrevorCash commented 2 months ago

I overlooked this in the docs. Thanks, it is working.

mosra commented 1 month ago

Just for the record, as of 1117d6f9b843aafe1fbd95bbadbc36e1180a488a the ImTextureID uses the underlying OpenGL ID (as you attempted to use here) and not a pointer to a live GL::Texture2D instance. It's much safer and makes the implementation simpler as well. Another such accidental crash was mosra/magnum#476.

No change is needed if you use the suggested image() and imageButton() utils, low-level code should use the new ImGuiIntegration::textureId() helper instead of a direct cast.