8
\$\begingroup\$

The picture rapresents what i want to achieve. ImGui window placed over custom drawing.

I read, somewhere on the Internet, that you can render the fbo and pass that fbo as a texture to render into the ImGui window. The problem is that I don't even know what an FBO is, and how to create it. I just want to have the scene rendered into my ImGui window (just like the scene window in Unity)

How do i do it?

\$\endgroup\$

2 Answers 2

7
\$\begingroup\$

First you need to render you scene to a Frame Buffer Object (here is a good course on FBO: https://learnopengl.com/#!Advanced-OpenGL/Framebuffers)

After that you will end up with a Texture (of type GLuint) containing your rendered scene. To print it into Dear imGUI, just call a Draw Image Command.

EDIT New (simpler) Example:

ImGui::Begin("GameWindow");
{
  // Using a Child allow to fill all the space of the window.
  // It also alows customization
  ImGui::BeginChild("GameRender");
  // Get the size of the child (i.e. the whole draw size of the windows).
  ImVec2 wsize = ImGui::GetWindowSize();
  // Because I use the texture from OpenGL, I need to invert the V from the UV.
  ImGui::Image((ImTextureID)tex, wsize, ImVec2(0, 1), ImVec2(1, 0));
  ImGui::EndChild();
}
ImGui::End();

Previous Version

Here is an example:

// My Game has a different viewport than the editor's one:
const int W = 1080 / 2;
const int H = 1920 / 2;
// We set the same viewport size (plus margin) to the next window (if first use)
ImGui::SetNextWindowSize(ImVec2(W + 10, H + 10),
                           ImGuiSetCond_FirstUseEver);
  ImGui::Begin("Game rendering");
  {
    // Get the current cursor position (where your window is)
    ImVec2 pos = ImGui::GetCursorScreenPos();

    // A boolean to allow me to stop the game rendering
    if (runApp) {
      glViewport(0, 0, W, H);
      // Render the scene into an FBO
      game->render(time);
      // Restore previous viewport
      glViewport(0, 0, w, h);
    }
    // Get the texture associated to the FBO
    auto tex = game->getRendered();

    // Ask ImGui to draw it as an image:
    // Under OpenGL the ImGUI image type is GLuint
    // So make sure to use "(void *)tex" but not "&tex"
    ImGui::GetWindowDrawList()->AddImage(
        (void *)tex, ImVec2(ImGui::GetItemRectMin().x + pos.x,
                            ImGui::GetItemRectMin().y + pos.y),
        ImVec2(pos.x + h / 2, pos.y + w / 2), ImVec2(0, 1), ImVec2(1, 0));
  }
  ImGui::End();
\$\endgroup\$
6
  • \$\begingroup\$ I don't understand what the the last two parameters of AddImage mean \$\endgroup\$
    – tuket
    Sep 27, 2017 at 9:32
  • \$\begingroup\$ These two ImVec2 are UV mapping \$\endgroup\$
    – FloFu
    Sep 28, 2017 at 8:57
  • \$\begingroup\$ but shouldn't it be (0, 0), (1, 1) instead? \$\endgroup\$
    – tuket
    Sep 28, 2017 at 10:16
  • \$\begingroup\$ In my case UV mapping required to be flipped. Sorry for the late answer. \$\endgroup\$
    – FloFu
    Oct 29, 2017 at 13:44
  • \$\begingroup\$ What is ImVec2(ImGui::GetItemRectMin().x + pos.x, ImGui::GetItemRectMin().y + pos.y), and ImVec2(pos.x + h / 2, pos.y + w / 2) ? I got working the fbo and the texture is correct(i applied it to a quad) but the imGui window is not displaying it correctly.. \$\endgroup\$
    – user100681
    Nov 1, 2017 at 9:19
2
\$\begingroup\$

Rendering to a FBO and using as a texture is just fancy speak for rendering to texture and then using that texture in a subsequent render. All geometry generated by imgui are just texture triangles.

FBO stands for FrameBuffer Object, it is a collection of images that you can use as a rendertarget. Opengl is initialized with the window as the default target FBO.

\$\endgroup\$

You must log in to answer this question.