当前位置: 首页 > 知识库问答 >
问题:

如何在imgui窗口中使用opengl glfw3渲染?

施琦
2023-03-14

我正在通过glfw3库学习OpenGL,我正在使用imgui制作一个有趣的应用程序。

我想做一个小引擎或CAD工具。

问题是我不能在imgui窗口中呈现我想要的。

我搜索了谷歌,找到了以下链接:

  1. https://gamedev.stackexchange.com/questions/150214/render-in-a-imgui-window
  2. https://gamedev.stackexchange.com/questions/140693/how-can-i-render-an-opengl-scene-into-an-imgui-window

我尝试了大约两天,我已经在imgui窗口中呈现了一个三角形。
但是当我尝试呈现此链接(教程和代码)显示的内容时。

imgui窗口中的框不会旋转!!!

我试过连续几天,我打算放弃,我真的需要你的帮助。

\define \uu abc\uuu是要测试的值。Xhader。h也是教程中的头文件。vs和。fs文件。不同之处在于教程使用了glad。h和我使用glew。h类

#define __abc__
#define STB_IMAGE_IMPLEMENTATION
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"

#include "Xhader.h"



void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);

GLFWwindow* Proinit();
void imguiSetup(GLFWwindow* window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;


int main()
{
    GLFWwindow* window = Proinit();
    imguiSetup(window);

    int view3d_width = 100;
    int view3d_height = 200;



    // configure global opengl state
    // -----------------------------
    glEnable(GL_DEPTH_TEST);

    // build and compile our shader zprogram
    // ------------------------------------
    Xhader ourShader("shader/vs.txt", "shader/fs.txt");

    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float vertices[] = {
            -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
            0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,

            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
            -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,

            -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,

            0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f,

            -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
            0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
            0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,

            -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
            -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
    };

    GLuint VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);


    //---------------------------------------    FBO    -----------------------------//
#ifdef __abc__
    unsigned int fbo;
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    GLuint TOF;
    glGenTextures(1, &TOF);
    glBindTexture(GL_TEXTURE_2D, TOF);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 400, 300, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#else
    ;
#endif


    // load and create a texture 
    // -------------------------
    unsigned int texture1, texture2;
    // texture 1
    // ---------
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    // set the texture wrapping parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // set texture filtering parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // load image, create texture and generate mipmaps
    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
    std::string s1 = "resources/textures/container.jpg";
    std::string s2 = "resources/textures/awesomeface.png";
    unsigned char* data = stbi_load(s1.c_str(), &width, &height, &nrChannels, 0);
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);
    // texture 2
    // ---------
    glGenTextures(1, &texture2);
    glBindTexture(GL_TEXTURE_2D, texture2);
    // set the texture wrapping parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // set texture filtering parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // load image, create texture and generate mipmaps
    data = stbi_load(s2.c_str(), &width, &height, &nrChannels, 0);
    if (data)
    {
        // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }
    stbi_image_free(data);

    // tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
    // -------------------------------------------------------------------------------------------
    ourShader.use();
    ourShader.setInt("texture1", 0);
    ourShader.setInt("texture2", 1);


    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {

#ifdef __abc__
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, TOF, 0);
#endif
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
            std::cout << "FRAMEBUFFER SUCCESS" << std::endl;
            glViewport(0, 0, 400, 300);
            // render
            // ------
            glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now!
            // bind textures on corresponding texture units
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, texture1);
            glActiveTexture(GL_TEXTURE1);
            glBindTexture(GL_TEXTURE_2D, texture2);
            // activate shader
            ourShader.use();
            // create transformations
            glm::mat4 model = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
            glm::mat4 view = glm::mat4(1.0f);
            glm::mat4 projection = glm::mat4(1.0f);
            float time = (float)glfwGetTime();
            std::cout << time << std::endl;
            model = glm::rotate(model,time , glm::vec3(0.5f, 1.0f, 0.0f));

            view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
            projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
            // retrieve the matrix uniform locations
            unsigned int modelLoc = glGetUniformLocation(ourShader.ID, "model");
            unsigned int viewLoc = glGetUniformLocation(ourShader.ID, "view");
            // pass them to the shaders (3 different ways)
            glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
            glUniformMatrix4fv(viewLoc, 1, GL_FALSE, &view[0][0]);
            // note: currently we set the projection matrix each frame, 
            //but since the projection matrix rarely changes it's often best practice 
            //to set it outside the main loop only once.
            ourShader.setMat4("projection", projection);
            // render box
            glBindVertexArray(VAO);
            glDrawArrays(GL_TRIANGLES, 0, 36);

#ifdef __abc__
            glBindFramebuffer(GL_FRAMEBUFFER, 0);   
#endif
        }
        else {
            std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
        }
#ifdef __abc__
        // Start the Dear ImGui frame
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();
        bool View_3D = true;
        if (View_3D) {
            ImGui::Begin("3D View", &View_3D);
            view3d_height = ImGui::GetWindowSize().x;
            view3d_width = ImGui::GetWindowSize().y;
            ImVec2 pos = ImGui::GetCursorScreenPos();
            ImGui::GetWindowDrawList()->AddImage(
                (void*)TOF,
                ImVec2(ImGui::GetCursorScreenPos()),
                ImVec2(ImGui::GetCursorScreenPos().x + ImGui::GetWindowSize().x - 15,
                    ImGui::GetCursorScreenPos().y + ImGui::GetWindowSize().y - 35),
                ImVec2(0, 1),
                ImVec2(1, 0)
            );
            ImGui::End();
        }



        // input
        // -----
        processInput(window);


        ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
        // render
        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#endif

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow* window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and 
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}


GLFWwindow* Proinit() {
//glfwSetErrorCallback(glfw_error_callback);
    if (!glfwInit()) return (GLFWwindow*)1;
#ifdef __APPLE__
    // GL 3.2 + GLSL 150
    const char* glsl_version = "#version 150";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // Required on Mac
#else
    const char* glsl_version = "#version 130";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // 3.0+ only
#endif
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Shader3D", NULL, NULL);
    if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return (GLFWwindow*)-1; }
    glfwMakeContextCurrent(window);
    //glfwSwapInterval(1); // Enable vsync
    //glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
#if defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
    bool err = glewInit() != GLEW_OK;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
    bool err = gladLoadGL() == 0;
#else
    bool err = false;
#endif
    if (err) { fprintf(stderr, "Failed to initialize OpenGL loader!\n"); return (GLFWwindow*)1; }


    return window;
}



void imguiSetup(GLFWwindow* window) {
    // Setup Dear ImGui context  
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;
    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls 
    //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls  
    ImGui::StyleColorsDark();
    ImGui_ImplGlfw_InitForOpenGL(window, true);         //Setup Platform bindings
#ifdef __APPLE__
    ImGui_ImplOpenGL3_Init("#version 150");             //Setup Renderer bindings
#else
    ImGui_ImplOpenGL3_Init("#version 130");
#endif

}

共有1个答案

郝池暝
2023-03-14

首先,您应该创建一个帧缓冲区和一个类似f\u tex的纹理

    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    f_tex = CreateTexture(512, 512, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, f_texture, 
    GLuint depthrenderbuffer;
    glGenRenderbuffers(1, &depthrenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 512, 512);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);

然后,将f\u tex的指针指向绘图列表-

    ImGui::Begin("Game Window");
    ImVec2 pos = ImGui::GetCursorScreenPos();
    ImDrawList* drawList = ImGui::GetWindowDrawList();
    auto app = SSEngine::App::main;
    uint f_tex = app->getFrameBuffer();
    drawList->AddImage((void*)f_tex,
        pos,
        ImVec2(pos.x + 512, pos.y + 512),
        ImVec2(0, 1),
        ImVec2(1, 0));
    ImGui::End();

我的项目中的示例:https://i.stack.imgur.com/365De.png

 类似资料:
  • 是否可以创建没有背景或窗口的ImGui屏幕?它只是可以在屏幕上拖动的ImGui窗口。它看起来像这样,但不是蓝色背景,您只会看到它下面的应用程序。

  • 目前,如果我的窗口足够小,我亲爱的ImGui应用程序(主要是带有一些自定义OpenGL渲染的演示窗口)运行速度大约为2000 fps。如何将此限制为监视器刷新率(甚至仅为60fps)? 我当前的代码如下所示: 如您所见,它与ImGui示例中给出的GLFW和OpenGL 3的原始示例代码没有任何区别(几乎没有任何区别),除了我使用限制刷新率的尝试没有成功,我了解到这只会影响全屏模式下的窗口。此外,我

  • 我写了一个< code>OpenGL代码用于在屏幕上渲染图像。我使用< code>GLUT来创建一个窗口和回调,但是我想在< code>win32窗口中而不是在< code>GLUT中呈现图像,基本上我们有一个< code > CreateWindowEx() API来在< code>win32中创建窗口,并且我们有一个< code>HWND(句柄),以便我们可以将此句柄传递给< code>HDC

  • 我不是Vulkan方面的专家。我想知道如何在常规场景渲染的顶部显示Vulkan帧(提交每帧记录的especif commandBuffer以绘制UI更改)。所以在本例中,我有两个renderPasses,一个用于场景,另一个用于ImGui,还有两个commandBuffers。在尝试发送这两个commandBuffers时,只显示最后一个,因为它们使用的是swapchain映像。我错过了什么?im

  • 我正在寻找一些关于渲染子窗口的信息,特别是关于OpenGL如何与GDI互操作的信息。我的问题是,我基本上有两个窗口,首先,主窗口是在qt中创建的,而在qt内部,子窗口是利用OpenGL渲染器托管的。 现在我想做的是在我的OpenGL窗口顶部托管一个覆盖,所以我用它来覆盖OpenGL窗口。我遇到的问题是,当我使用OpenGL渲染时,OpenGL生成的图形似乎模糊了图形区域,包括并有效地撤消了由qt合

  • 问题内容: 我正在尝试将某些Windows函数(和)用于数据框,但我不知道如何使用它们。 有人可以帮我吗?在Python API文档 中,没有关于它的示例。 具体来说,我正在尝试获取数据框中数字字段的分位数。 我正在使用Spark 1.4.0。 问题答案: 要使用窗口功能,您必须先创建一个窗口。定义与普通SQL几乎相同,这意味着您可以定义顺序,分区或同时定义两者。首先让我们创建一些虚拟数据: 确保