8
\$\begingroup\$

How do i render my game scene into an imgui window?

I want to get from this:

enter image description here

to this :

enter image description here

\$\endgroup\$
9
\$\begingroup\$

First of all we need to create what is called Frame Buffer Object, or FBO for short. I'll leave you a great tutorial on (pretty much everything regarding OpenGL)FBOs right here: https://learnopengl.com/#!Advanced-OpenGL/Framebuffers

Now that we created an FBO, we should have a texture. This texture contains the image of what is rendered on the FBO. At this point all we need to do is to "put" this image inside of a dear ImGui Window. Let's see how to do this:

//this is our main game loop
while (!window.Closed())
{
    //we need to clear the window,
    //This is how the clear method is structured:
    //void Window::Clear(float x, float y, float z, bool enableGLDepth,bool clearImGUIframe)const
    //{
    //  //clear the color of the window with an alpha value of 1.0f
    //  glClearColor(x, y, z, 1.0f);    
    //  if (clearImGUIframe)
    //  {
    //      ImGui_ImplGlfwGL3_NewFrame();
    //  }
    //  if (enableGLDepth)
    //  {
    //      //enable the GL_DEPTH_TEST to be able to see 3D object correctly
    //      glEnable(GL_DEPTH_TEST);
    //      //clear both the color buffer bit and the depth buffer bit
    //      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //  }
    //  else
    //  {
    //      //clear just the color buffer bit
    //      glClear(GL_COLOR_BUFFER_BIT);
    //  }
    //}

    window.Clear(0.5f, 0.5f, 0.5f,true,true);

    //switch to our custom FBO
    //window.bindFBO is the same as writing glBindFramebuffer(GL_FRAMEBUFFER,FBO);
    window.bindFBO();

    //we need to call clear twice
    window.Clear(1.0f, 1.0f, 1.0f, true, false);
    //Draw our simple triangle
    shader.Use();
    glBindVertexArray(Tvao);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    //switch to the default FBO
    //again, unbindFBO() is the same as glBindFramebuffer(GL_FRAMEBUFFER,0)
    window.unbindFBO();

    //create our ImGui window
    ImGui::Begin("Scene Window");
    //get the mouse position
    ImVec2 pos = ImGui::GetCursorScreenPos();

    //pass the texture of the FBO
    //window.getRenderTexture() is the texture of the FBO
    //the next parameter is the upper left corner for the uvs to be applied at
    //the third parameter is the lower right corner
    //the last two parameters are the UVs
    //they have to be flipped (normally they would be (0,0);(1,1) 
    ImGui::GetWindowDrawList()->AddImage(
        (void *)window.getRenderTexture(), 
ImVec2(ImGui::GetCursorScreenPos()),
        ImVec2(ImGui::GetCursorScreenPos().x + window.getWidth()/2, 
ImGui::GetCursorScreenPos().y + window.getHeight()/2), ImVec2(0, 1), ImVec2(1, 0));

    //we are done working with this window
    ImGui::End();
    //swap the buffers and check for events
    window.Update();
}

after all this you should get this result:

enter image description here

Hope this helped someone! I'll also leave the entire code i am using down here:

Main.cpp

#include "Engine.h"

using namespace Engine;
using namespace graphics;

int main()
{
Window window("Advent3D", 800,600, false);
Shader shader("Res/Shaders/Unlit.shader");

//TRIANGLE CREATION//
float Tvertices[] = {-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f,0.0f,  0.5f, 0.0f};

unsigned int Tvbo, Tvao;
glGenVertexArrays(1, &Tvao);
glGenBuffers(1, &Tvbo);
glBindVertexArray(Tvao);
glBindBuffer(GL_ARRAY_BUFFER, Tvbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(Tvertices), Tvertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindVertexArray(0);


while (!window.Closed())
{
    //we need to clear the window, 
    window.Clear(0.5f, 0.5f, 0.5f,true,true);

    //switch to the custom fbo
    window.bindFBO();

    window.Clear(1.0f, 1.0f, 1.0f, true, false);

    shader.Use();
    glBindVertexArray(Tvao);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    //switch to the default fbo
    window.unbindFBO();

    ImGui::Begin("Scene Window");

    ImVec2 pos = ImGui::GetCursorScreenPos();

    ImGui::GetWindowDrawList()->AddImage(
        (void *)window.getRenderTexture(), ImVec2(ImGui::GetCursorScreenPos()),
        ImVec2(ImGui::GetCursorScreenPos().x + window.getWidth()/2, ImGui::GetCursorScreenPos().y + window.getHeight()/2), ImVec2(0, 1), ImVec2(1, 0));

    ImGui::End();

    window.Update();
}   

}

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy