diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp index 8e57564..3c35560 100644 --- a/FrameBuffer.cpp +++ b/FrameBuffer.cpp @@ -51,7 +51,7 @@ void FrameBuffer::init() glBindFramebuffer(GL_FRAMEBUFFER, framebufferid_); // take settings into account: no multisampling for level 0 - use_multi_sampling_ &= Settings::application.multisampling_level > 0; + use_multi_sampling_ &= Settings::application.render_multisampling > 0; if (use_multi_sampling_){ @@ -60,7 +60,7 @@ void FrameBuffer::init() glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, intermediate_textureid_); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Settings::application.multisampling_level, + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Settings::application.render_multisampling, use_alpha_ ? GL_RGBA : GL_RGB, attrib_.viewport.x, attrib_.viewport.y, GL_TRUE); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); diff --git a/RenderingManager.cpp b/RenderingManager.cpp index b732636..59bf33e 100644 --- a/RenderingManager.cpp +++ b/RenderingManager.cpp @@ -135,7 +135,7 @@ bool Rendering::init() // // OpenGL Multisampling main window // - glfwWindowHint(GLFW_SAMPLES, Settings::application.multisampling_level); + glfwWindowHint(GLFW_SAMPLES, Settings::application.render_multisampling); main_.init(0); // set application icon main_.setIcon("images/vimix_256x256.png"); @@ -209,23 +209,21 @@ void Rendering::pushBackDrawCallback(RenderingCallback function) void Rendering::draw() { - // Poll and handle events (inputs, window resize, etc.) - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. - glfwPollEvents(); + // operate on main window context main_.makeCurrent(); + // User Interface step 1 UserInterface::manager().NewFrame(); + // Custom draw std::list::iterator iter; for (iter=draw_callbacks_.begin(); iter != draw_callbacks_.end(); iter++) { (*iter)(); } + // User Interface step 2 UserInterface::manager().Render(); // perform screenshot if requested @@ -238,11 +236,18 @@ void Rendering::draw() // swap GL buffers glfwSwapBuffers(main_.window()); + // draw output window (and swap buffer output) + output_.draw( Mixer::manager().session()->frame() ); + + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + glfwPollEvents(); + // no g_main_loop_run(loop) : update global GMainContext g_main_context_iteration(NULL, FALSE); - - // draw output window - output_.draw( Mixer::manager().session()->frame() ); } @@ -523,11 +528,12 @@ bool RenderingWindow::init(int id, GLFWwindow *share) return false; } - // store global ref to pointers (used by callbacks) - GLFW_window_[window_] = this; - // set position glfwSetWindowPos(window_, winset.x, winset.y); + + /// CALLBACKS + // store global ref to pointers (used by callbacks) + GLFW_window_[window_] = this; // window position and resize callbacks glfwSetWindowSizeCallback( window_, WindowResizeCallback ); // glfwSetFramebufferSizeCallback( window_, WindowResizeCallback ); @@ -536,11 +542,11 @@ bool RenderingWindow::init(int id, GLFWwindow *share) // take opengl context ownership glfwMakeContextCurrent(window_); + // + // Initialize OpenGL loader on first call + // static bool glad_initialized = false; if ( !glad_initialized ) { - // - // Initialize OpenGL loader - // bool err = gladLoadGLLoader((GLADloadproc) glfwGetProcAddress) == 0; if (err) { Log::Error("Failed to initialize GLAD OpenGL loader."); @@ -566,7 +572,7 @@ bool RenderingWindow::init(int id, GLFWwindow *share) // no need for multisampling glDisable(GL_MULTISAMPLE); // clear to black - window_attributes_.clear_color = glm::vec4(0.f, 0.f, 0.f, 1.0); + window_attributes_.clear_color = glm::vec4(0.f, 0.f, 0.f, 1.f); // give back context ownership glfwMakeContextCurrent(master_); } @@ -574,12 +580,12 @@ bool RenderingWindow::init(int id, GLFWwindow *share) // Enable vsync on main window glfwSwapInterval(1); // enable Antialiasing multisampling - if (Settings::application.multisampling_level > 0) { + if (Settings::application.render_multisampling > 0) { glEnable(GL_MULTISAMPLE); glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); } // clear to grey - window_attributes_.clear_color = glm::vec4(COLOR_BGROUND, 1.0); + window_attributes_.clear_color = glm::vec4(COLOR_BGROUND, 1.f); } return true; @@ -635,7 +641,7 @@ void RenderingWindow::makeCurrent() void RenderingWindow::draw(FrameBuffer *fb) { - if (!window_) + if (!window_ || !fb) return; // only draw if window is not iconified @@ -651,84 +657,78 @@ void RenderingWindow::draw(FrameBuffer *fb) Rendering::manager().pushAttrib(window_attributes_); glClear(GL_COLOR_BUFFER_BIT); - // draw frame buffer provided - if (fb) { + // blit framebuffer + if (Settings::application.render_blit) { + static int attached_textureid_fbo_ = 0; + static uint local_fbo_ = 0; + if ( attached_textureid_fbo_ != fb->texture()) { - if (false) { - // VAO is not shared between multiple contexts of different windows - // so we have to create a new VAO for rendering the surface in this window - static WindowSurface *surface = new WindowSurface; - static glm::mat4 projection = glm::ortho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f); + // create a new fbo in this opengl context + if (local_fbo_ != 0) + glDeleteFramebuffers(1, &local_fbo_); + glGenFramebuffers(1, &local_fbo_); + glBindFramebuffer(GL_FRAMEBUFFER, local_fbo_); - // calculate scaling factor of frame buffer inside window - float windowAspectRatio = aspectRatio(); - float renderingAspectRatio = fb->aspectRatio(); - glm::vec3 scale; - if (windowAspectRatio < renderingAspectRatio) - scale = glm::vec3(1.f, windowAspectRatio / renderingAspectRatio, 1.f); - else - scale = glm::vec3(renderingAspectRatio / windowAspectRatio, 1.f, 1.f); + // attach the 2D texture to local FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture(), 0); + attached_textureid_fbo_ = fb->texture(); - // draw - ShadingProgram::enduse(); - glBindTexture(GL_TEXTURE_2D, fb->texture()); - // surface->shader()->color.a = 0.4f; // TODO alpha blending ? - surface->draw(glm::scale(glm::identity(), scale), projection); - - // done drawing - ShadingProgram::enduse(); - glBindTexture(GL_TEXTURE_2D, 0); + Log::Info("Blit to output window enabled."); } - else { - - static int attached_textureid_fbo_ = 0; - static uint local_fbo_ = 0; - if ( attached_textureid_fbo_ != fb->texture()) { - - // create a new fbo in this opengl context - if (local_fbo_ != 0) - glDeleteFramebuffers(1, &local_fbo_); - glGenFramebuffers(1, &local_fbo_); - glBindFramebuffer(GL_FRAMEBUFFER, local_fbo_); - - // attach the 2D texture to local FBO - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture(), 0); - attached_textureid_fbo_ = fb->texture(); - - Log::Info("Blit to output window enabled."); - } - - // calculate scaling factor of frame buffer inside window - int rx, ry, rw, rh; - float renderingAspectRatio = fb->aspectRatio(); - if (aspectRatio() < renderingAspectRatio) { - int nh = (int)( float(window_attributes_.viewport.x) / renderingAspectRatio); - rx = 0; - ry = (window_attributes_.viewport.y - nh) / 2; - rw = window_attributes_.viewport.x; - rh = (window_attributes_.viewport.y + nh) / 2; - } else { - int nw = (int)( float(window_attributes_.viewport.y) * renderingAspectRatio ); - rx = (window_attributes_.viewport.x - nw) / 2; - ry = 0; - rw = (window_attributes_.viewport.x + nw) / 2; - rh = window_attributes_.viewport.y; - } - - // select fbo texture read target - glBindFramebuffer(GL_READ_FRAMEBUFFER, local_fbo_); - - // select screen target - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - -// glBlitFramebuffer(0, 0, fb->width(), fb->height(), 0, 0, window_attributes_.viewport.x, window_attributes_.viewport.y, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBlitFramebuffer(0, fb->height(), fb->width(), 0, rx, ry, rw, rh, GL_COLOR_BUFFER_BIT, GL_LINEAR); + // calculate scaling factor of frame buffer inside window + int rx, ry, rw, rh; + float renderingAspectRatio = fb->aspectRatio(); + if (aspectRatio() < renderingAspectRatio) { + int nh = (int)( float(window_attributes_.viewport.x) / renderingAspectRatio); + rx = 0; + ry = (window_attributes_.viewport.y - nh) / 2; + rw = window_attributes_.viewport.x; + rh = (window_attributes_.viewport.y + nh) / 2; + } else { + int nw = (int)( float(window_attributes_.viewport.y) * renderingAspectRatio ); + rx = (window_attributes_.viewport.x - nw) / 2; + ry = 0; + rw = (window_attributes_.viewport.x + nw) / 2; + rh = window_attributes_.viewport.y; } + // select fbo texture read target + glBindFramebuffer(GL_READ_FRAMEBUFFER, local_fbo_); + + // select screen target + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + // glBlitFramebuffer(0, 0, fb->width(), fb->height(), 0, 0, window_attributes_.viewport.x, window_attributes_.viewport.y, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, fb->height(), fb->width(), 0, rx, ry, rw, rh, GL_COLOR_BUFFER_BIT, GL_LINEAR); + } - else { - Log::Info("No Framebuffer Provided to draw Rendering Window"); + // draw geometry + else + { + // VAO is not shared between multiple contexts of different windows + // so we have to create a new VAO for rendering the surface in this window + static WindowSurface *surface = new WindowSurface; + static glm::mat4 projection = glm::ortho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f); + + // calculate scaling factor of frame buffer inside window + float windowAspectRatio = aspectRatio(); + float renderingAspectRatio = fb->aspectRatio(); + glm::vec3 scale; + if (windowAspectRatio < renderingAspectRatio) + scale = glm::vec3(1.f, windowAspectRatio / renderingAspectRatio, 1.f); + else + scale = glm::vec3(renderingAspectRatio / windowAspectRatio, 1.f, 1.f); + + // draw + ShadingProgram::enduse(); + glBindTexture(GL_TEXTURE_2D, fb->texture()); + // surface->shader()->color.a = 0.4f; // TODO alpha blending ? + surface->draw(glm::scale(glm::identity(), scale), projection); + + // done drawing + ShadingProgram::enduse(); + glBindTexture(GL_TEXTURE_2D, 0); } // restore attribs diff --git a/Settings.cpp b/Settings.cpp index 89398ca..646a447 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -64,7 +64,8 @@ void Settings::Save() applicationNode->SetAttribute("toolbox", application.toolbox); applicationNode->SetAttribute("framebuffer_ar", application.framebuffer_ar); applicationNode->SetAttribute("framebuffer_h", application.framebuffer_h); - applicationNode->SetAttribute("multisampling_level", application.multisampling_level); + applicationNode->SetAttribute("multisampling_level", application.render_multisampling); + applicationNode->SetAttribute("render_blit", application.render_blit); pRoot->InsertEndChild(applicationNode); // bloc views @@ -169,7 +170,8 @@ void Settings::Load() pElement->QueryIntAttribute("stats_corner", &application.stats_corner); pElement->QueryIntAttribute("framebuffer_ar", &application.framebuffer_ar); pElement->QueryIntAttribute("framebuffer_h", &application.framebuffer_h); - pElement->QueryIntAttribute("multisampling_level", &application.multisampling_level); + pElement->QueryIntAttribute("multisampling_level", &application.render_multisampling); + pElement->QueryBoolAttribute("render_blit", &application.render_blit); // bloc windows { diff --git a/Settings.h b/Settings.h index 2563235..dd55f33 100644 --- a/Settings.h +++ b/Settings.h @@ -77,7 +77,8 @@ struct Application std::map views; int framebuffer_ar; int framebuffer_h; - int multisampling_level; + int render_multisampling; + bool render_blit; // multiple windows handling std::vector windows; @@ -100,7 +101,8 @@ struct Application current_view = 1; framebuffer_ar = 3; framebuffer_h = 1; - multisampling_level = 2; // todo GUI selection + render_multisampling = 2; // todo GUI selection + render_blit = false; std::vector second (4,100); windows = std::vector(3); windows[0].name = APP_NAME APP_TITLE; diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index 2673d21..fd441ff 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -678,14 +678,20 @@ void ToolBox::Render() // Menu Bar if (ImGui::BeginMenuBar()) { - if (ImGui::BeginMenu("Tools")) + if (ImGui::BeginMenu("Render")) { - if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Screenshot", NULL) ) + if ( ImGui::MenuItem( ICON_FA_CAMERA_RETRO " Screenshot") ) UserInterface::manager().StartScreenshot(); - ImGui::MenuItem("Dev", NULL, false, false); - ImGui::MenuItem("Icons", NULL, &show_icons_window); - ImGui::MenuItem("Demo ImGui", NULL, &show_demo_window); + ImGui::MenuItem("Blit", nullptr, &Settings::application.render_blit); + ImGui::MenuItem("Multisampling", nullptr, (Settings::application.render_multisampling > 0), false); + + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("Dev")) + { + ImGui::MenuItem("Icons", nullptr, &show_icons_window); + ImGui::MenuItem("Demo ImGui", nullptr, &show_demo_window); ImGui::EndMenu(); }