C++ OpenGL/GLFW Integration - Question on rendering
Posted: 09 Jun 2018, 17:02
Hi people,
I've started integrating Noesis GUI into my project which uses an OpenGL/GLFW rendering structure and I am using the sample GLRenderDevice for now until I got this working and can start to tinker with it, mostly this is going alright without many issues (took a few seconds to realize I had to reset OpenGL states after updating the RenderTree and Offscreen Render but that was it so far).
But now I've come across an issue I'm hard-pressed to find the solution to on my own and I'm hoping I could get some advice on this here.
The issue basically is that as soon as I call: UpdateRenderTree + RenderOffscreen + (My Rendering) + Render on the IRenderer interface, my application will refuse to show any updates to the FrameBufferObject. This causes it to look as if the application froze, but it's still running, just not showing changes made to the FBO.
I've done numerous tests to track down the issue, but to no avail, some things I've tried to narrow down the issue are:
In the code above mInGameMode defaults to false and is set to true on a hotkey, and resets back to false on another hotkey.
In my opinion this should always show a blank screen when mInGameMode is true, and it does do this when I disable the UIManager sections of the code.
For reference, the UIManager code:
Any help or suggestions are appreciated.
I've started integrating Noesis GUI into my project which uses an OpenGL/GLFW rendering structure and I am using the sample GLRenderDevice for now until I got this working and can start to tinker with it, mostly this is going alright without many issues (took a few seconds to realize I had to reset OpenGL states after updating the RenderTree and Offscreen Render but that was it so far).
But now I've come across an issue I'm hard-pressed to find the solution to on my own and I'm hoping I could get some advice on this here.
The issue basically is that as soon as I call: UpdateRenderTree + RenderOffscreen + (My Rendering) + Render on the IRenderer interface, my application will refuse to show any updates to the FrameBufferObject. This causes it to look as if the application froze, but it's still running, just not showing changes made to the FBO.
I've done numerous tests to track down the issue, but to no avail, some things I've tried to narrow down the issue are:
- Run without rendering my own geometry so only UI is visible
- Bind a different FBO before calling Render, this didn't render the UI into the default FBO (0) but the screen still froze.
- Clear the FBO just before swapping the buffers
Code: Select all
while (!glfwWindowShouldClose(mWindow))
{
// New Frame Stuff
...
// ~New Frame Stuff
PROFILE_CUSTOM("Main Loop");
{
PROFILE_CUSTOM("GLFW");
// Clear the colorbuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Events
glfwPollEvents();
}
// Game update
...
// ~Game update
// UI Update
if (mInGameMode)
{
// This is the part where UpdateRenderTree + RenderOffscreen are called.
PROFILE_CUSTOM("UIManager Update");
UIManager::GetInstance().Update();
}
// Render update
// Also resets the OpenGL state as it was modified by Noesis GUI
...
// ~Render update
// UI Render
if (mInGameMode)
{
// This is the part where Render is called.
PROFILE_CUSTOM("UIManager Render");
UIManager::GetInstance().Render();
}
//End of loop, swap buffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (mInGameMode)
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
glfwSwapBuffers(mWindow);
}
In my opinion this should always show a blank screen when mInGameMode is true, and it does do this when I disable the UIManager sections of the code.
For reference, the UIManager code:
Code: Select all
void UIManager::Initialize()
{
GUI::Init(
[](const char* file, uint32_t line, const char* message, bool fatal)
{
Logger::Log(fatal ? Logger::ELogSeverity::FatalError : Logger::ELogSeverity::Error, "Noesis UI", message);
},
[](const char* filename, uint32_t line, uint32_t level, const char* channel, const char* message)
{
Logger::Log(Logger::ELogSeverity::Log, "Noesis UI", message);
},
nullptr
);
GUI::SetXamlProvider(MakePtr<UI_XamlProvider>());
//GUI::SetTextureProvider(MakePtr<>());
//GUI::SetFontProvider(MakePtr<>());
NoesisApp::Launcher::RegisterAppComponents();
NsRegisterComponent<NoesisUI::App>();
NsRegisterComponent<NoesisUI::MainWindow>();
int width, height;
glfwGetFramebufferSize(OpenGLEngine::GetInstance().GetWindow(), &width, &height);
Noesis::Ptr<Noesis::RenderDevice> device = NoesisApp::GLFactory::CreateDevice();
device->SetGlyphCacheWidth(1024);
device->SetGlyphCacheHeight(1024);
device->SetGlyphCacheMeshThreshold(48);
Ptr<FrameworkElement> xaml = Noesis::GUI::LoadXaml<FrameworkElement>("MainWindow");
view = Noesis::GUI::CreateView(xaml);
view->SetIsPPAAEnabled(true);
view->GetRenderer()->Init(device);
view->SetSize(width, height);
RestoreValues();
}
void UIManager::Update()
{
double time = glfwGetTime();
view->Update(time);
// Offscreen rendering phase populates textures needed by the on-screen rendering
view->GetRenderer()->UpdateRenderTree();
view->GetRenderer()->RenderOffscreen();
// If you are going to render here with your own engine you need to restore the GPU state
// because noesis changes it. The framebuffer and viewport are restored here
glBindFramebuffer(GL_FRAMEBUFFER, 0);
int width, height;
glfwGetFramebufferSize(OpenGLEngine::GetInstance().GetWindow(), &width, &height);
glViewport(0, 0, width, height);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
RestoreValues();
}
void UIManager::Render()
{
view->GetRenderer()->Render();
RestoreValues();
}
void UIManager::RestoreValues()
{
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glDisable(GL_SCISSOR_TEST);
glStencilMask(0);
}