C++ OpenGL/GLFW Integration - Question on rendering
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);
}
-
-
sfernandez
Site Admin
- Posts: 3364
- Joined:
Re: C++ OpenGL/GLFW Integration - Question on rendering
Hi,
I don't understand why you need to clear the framebuffer after rendering, and don't know if that is your problem.
The render loop should be quite simple:
I don't understand why you need to clear the framebuffer after rendering, and don't know if that is your problem.
The render loop should be quite simple:
Code: Select all
LOOP START
{
// Game and input update
_noesisView->Update(timeInSeconds);
_noesisRenderer->UpdateRenderTree();
if (_noesisRenderer->NeedsOffscreen())
_noesisRenderer->RenderOffscreen();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset GL state to initialize anything that Noesis could have changed during RenderOffscreen
// Render your geometry
_noesisRenderer->Render();
glfwSwapBuffers(mWindow);
} LOOP ENDRe: C++ OpenGL/GLFW Integration - Question on rendering
Correct, I do not need to, I did this as an experiment.
Basically with the setup you just showed the screen will freeze for me. Even if I clear the screen, it will not show an empty screen. Somehow it still shows the image generated by _noesisRenderer->Render(); even thought I tell the FBO to clear. I'm quite sure it's some OpenGL setting somewhere which causes this and I was hoping someone here might know the answer to it.
Basically with the setup you just showed the screen will freeze for me. Even if I clear the screen, it will not show an empty screen. Somehow it still shows the image generated by _noesisRenderer->Render(); even thought I tell the FBO to clear. I'm quite sure it's some OpenGL setting somewhere which causes this and I was hoping someone here might know the answer to it.
-
-
sfernandez
Site Admin
- Posts: 3364
- Joined:
Re: C++ OpenGL/GLFW Integration - Question on rendering
If you comment all the noesis calls, are you able to render your 3D scene correctly, without freezing?
Then if you add the Noesis's Update, UpdateRenderTree and Render calls (without RenderOffscreen), are you able to render everything correctly?
NOTE: Start with a simple xaml with a red Rectangle and without opacity groups:
Is the RenderOffscreen, when added, the one causing your screen to freeze?
Then if you add the Noesis's Update, UpdateRenderTree and Render calls (without RenderOffscreen), are you able to render everything correctly?
NOTE: Start with a simple xaml with a red Rectangle and without opacity groups:
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Rectangle Width="200" Height="100" Fill="Red"/>
</Grid>Re: C++ OpenGL/GLFW Integration - Question on rendering
If I comment out all the Noesis calls the 3D scene renders correctly and doesn't freeze, this is correct. I'm unable to test your suggestions at this moment but will be back in a few hours with the results of the suggested steps. I'll also use the xaml provided, as I'm currently using something similar to test anyway.
Re: C++ OpenGL/GLFW Integration - Question on rendering
Well I'm happy to say that using the xaml data you provided actually fixes the issue.
Though my confusion still haunts me as to why, for reference, this is the .xaml file saved from Blend:
I did some tinkering with it (removing variables bit by bit) and the Width="75" part is which break the entire thing, not sure if that's my doing with Blend or an issue in the system? I do know is that all I did in Blend was drag a button in somewhere in the window and save it. I can supply the Blend project if desired.
Edit: For more info, an example provided in the documentation which uses Width does work:
And adding a Height value to my original xaml doesn't solve it.
Edit 2: Even more info: After using the button example from the documentation I noticed that if I take the above xaml and change the "OK" Content to something larger (which doesn't fit in the button) I get screen freeze again.
So this doesn't work for me:
Though my confusion still haunts me as to why, for reference, this is the .xaml file saved from Blend:
Code: Select all
<Window x:Class="NoesisUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:NoesisUI"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="Test Button" HorizontalAlignment="Left" Margin="347.941,200.236,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
Edit: For more info, an example provided in the documentation which uses Width does work:
Code: Select all
<Grid>
<Button Width="60" Height="40" Content="OK">
<Button.ToolTip>
Clicking this will submit your request
</Button.ToolTip>
</Button>
</Grid>
Edit 2: Even more info: After using the button example from the documentation I noticed that if I take the above xaml and change the "OK" Content to something larger (which doesn't fit in the button) I get screen freeze again.
So this doesn't work for me:
Code: Select all
<Grid>
<Button Width="60" Height="40" Content="OK OK OK OK OK OK">
<Button.ToolTip>
Clicking this will submit your request
</Button.ToolTip>
</Button>
</Grid>
Last edited by TheMPC on 11 Jun 2018, 19:50, edited 1 time in total.
-
-
sfernandez
Site Admin
- Posts: 3364
- Joined:
Re: C++ OpenGL/GLFW Integration - Question on rendering
If you set the Button's Width="300", then what happens? is it working fine?
My guess is that the problem is something related with the stencil buffer. We use stencil buffer when we need to do clipping, and maybe in your original xaml Button's width was not enough to fit the text "Test Button", so clipping was activated.
You need to create a stencil buffer for the main window surface and clear it on each frame.
My guess is that the problem is something related with the stencil buffer. We use stencil buffer when we need to do clipping, and maybe in your original xaml Button's width was not enough to fit the text "Test Button", so clipping was activated.
You need to create a stencil buffer for the main window surface and clear it on each frame.
Re: C++ OpenGL/GLFW Integration - Question on rendering
"You need to create a stencil buffer for the main window surface" This part for sure then! I did read about this in the rendering integration but didn't know how to achieve this, nor that it could cause such severe issues, I expected just to see no clipping instead of freezing I guess.
This solves everything, thank you for your time an patience!
This solves everything, thank you for your time an patience!
-
-
sfernandez
Site Admin
- Posts: 3364
- Joined:
Re: C++ OpenGL/GLFW Integration - Question on rendering
Great, glad to hear it is finally working. I'm setting this thread as solved.
Re: C++ OpenGL/GLFW Integration - Question on rendering
If you don't mind indulging me with some more info on the stencil buffer, which of the FBOs requires the stencil buffer, the one used by _noesisRenderer->Render(); or _noesisRenderer->RenderOffscreen();? As the following code does detail the default (0) FBO has an 8-bit stencil buffer:
Code: Select all
GLint stencil_bits;
glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits);
Who is online
Users browsing this forum: No registered users and 5 guests