Trouble initializing shaders before resize on wxGLCanvas - c++

wxGLCanvas seems to hate OpenGL shaders, by not providing an initialization callback function like the one in Qt; Making me unable to create the shaders even after creating the context myself in the constructor, like so:
m_context = new wxGLContext(this);
Also tried:
SetCurrent(*m_current);
Still no luck and GLEW keeps throwing "Missing GL Version" which indicates that the context has not been created (from Google).
I have tried:
Using WX_EVT() for show and activate events, still no luck.
Initializing shaders in the resize event, still no luck.
Is there any way to make wxGLCanvas call my initialization function before anything else?

There is no specific method to initialize OpenGL that gets called before everything else, but after the window was shown, in wxWidgets. You can roll your own with a member variable that indicates whether OpenGL has been initialized, and doing your initialization in the Paint event handler if the variable is false.
In my experience it is safest to issue all OpenGL commands only in the Paint event handler, so in your Size event handler, you should save the new viewport size and update the projection matrix in your Paint handler (or just query the viewport size using wxGLCanvas' GetClientRect() method).

In the examples in http://wiki.wxwidgets.org/WxGLCanvas it is suggested that you do the initialization on the paint event (EVT_PAINT(BasicGLPane::render)), as said by Kristian Duske in the comments above.
Instead you can initialize OpenGL in any other place, you just have to show the wxwidget window or frame first (e.g. frame->Show() ).
I do this:
initialize wxGLCanvas (in my case with a wxFrame frame as parent)
canvas = new Canvas( (wxFrame*) frame, args);
show window
frame->Show()
Now call your custom OpenGL initialization method in the canvas class (only once):
set context
wxGLCanvas::SetCurrent(*m_context);
initialize glew:
glewExperimental = GL_TRUE;
GLenum err = glewInit();
After this I compile the shaders etc.
In the paint event then only do the drawing: glDrawArrays() and SwapBuffers()

Related

when using ImGui with Glut it does not show any objects

I'm coding a rendering engine in C++ with OpenGL and GLUT and trying to integrate ImGUI into my engine, but I have a problem. it either renders the gui and only the background (no objects), or it only renders the objects and background (no GUI). This code:
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(sizeChange);
glutSpecialUpFunc(releaseKey);
glutSpecialFunc(pressKey);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsLight();
ImGui_ImplGLUT_Init();
ImGui_ImplGLUT_InstallFuncs();
ImGui_ImplOpenGL2_Init();
creates this:
and this code:
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsLight();
ImGui_ImplGLUT_Init();
ImGui_ImplGLUT_InstallFuncs();
ImGui_ImplOpenGL2_Init();
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(sizeChange);
glutSpecialUpFunc(releaseKey);
glutSpecialFunc(pressKey);
creates this:
The problem is that GLUT callback handlers in both of your examples are set both manually (glut...Func) and by ImGui via ImGui_ImplGLUT_InstallFuncs. The latter sets default ImGui handlers for many GLUT callbacks (see the source), in particular glutReshapeFunc is used to set current window resize callback to ImGui_ImplGLUT_ReshapeFunc (source), which sets internal ImGui display size according to given parameters.
When in the second example glutReshapeFunc(sizeChange) gets called, ImGui handler gets unset, so it doesn't get called during window resize (which, in particular, happens also before the first display according to the GLUT documentation), which leaves internal ImGui state not set properly. In the first example, the situation is reversed - your reshape handler sizeChange gets unset and replaced by ImGui one, so initialization and rendering of your cube doesn't go as intended because sizeChange never gets called.
To resolve this, you can omit ImGui_ImplGLUT_InstallFuncs and use your GLUT handlers while, apart from custom logic, calling default ImGui handlers from them if they are present and their functionality is needed (you can see what default handlers exist by inspecting the sources linked above). E.g. you can change sizeChange like this:
void sizeChange(int w, int h)
{
// Your logic
// ...
ImGui_ImplGLUT_ReshapeFunc(w, h);
}
If you want key presses and releases to be registered by ImGui as well as your own code, you may change releaseKey and pressKey in a similar way by adding, respectively, ImGui_ImplGLUT_SpecialUpFunc and ImGui_ImplGLUT_SpecialFunc calls to them.

I can't paint on QOpenGLWidget

I'm new in Qt and I'm making an app that generates a 3D object with some points the user provides in GUI. The user defines the points and then, in the same window, a QOpenGLWidget paints the final object. But then, the QOpenGLWindow doesn't draw the model (only the GlCLearColor). I've tried the same functions but called before app.exec() in main and it works fine.
I don't know what's happening. I've tried calling makeCurrent() before working with vao and vbo but it doesn't work.
I haven't created any thread neither fbo.
When I tried makeCurrent before working with vao and vbo I got:
"QOpenGLBuffer::bind: buffer is not valid in the current context"
"QOpenGLShaderProgram::bind: program is not valid in the current context."
EDIT I retried making current before vao, vbo and shader binding and that messages dissapeared but the widget isn't painting the object.
I've also tried QOPenGLWidget::update() after drawing. It doesn't draw with resizing.
I'm using OpenGL 4.1 Core Profile and Qt 5.12.3
I've already solved it! I just forgot to make current before setting uniform values in shaders.

Global OpenGL context for rendering in fbo to display in many QOpenGLWidget

I want to display a scene with different points of view in many QOpenGLWidget that are in the same window (separated with a QSplitter architecture).
The important thing is that I want to store my scene data (geometry and textures) only once on the GPU.
But, each QOpenGLWidget have there own QOpenGLContext.
My idea was to create an independant context that render scene into a FrameBufferObject (not QFrameBufferObject) and use the resulting texture in the concerned QOpenGLWidget.
More technically, my approach was to create a new QOpenGLContext and a QOffscreenSurface.
But when I want to use the resulting QOpenGLFunctions given by my QOpenGLContext, it stop with a segmentation fault even if I've checked that my created QOpenGlContext is valid.
In a more general way, it's hard to me to understand the role of the QOpenGLContext, the surface (QOffscreenSurface in my case) and the makeCurrent function.
My request is to understand what is the good way to do this and why I get a segmentation fault.
I come back with an answer of my problem.
In fact I've used my first initialized QOpenGLWidget's context as global context to avoid creating a new one.
The tricky part is to make the global context current everytime it's needed (adding data on GPU or using the fbo).
The paintGL steps are simple :
- Make the global context current.
- Start fbo recording.
- Render the scene.
- Stop the fbo recording.
- Make the QOpenGLWidget context current.
- Render the fbo result on the screen.
I've checked my memory using gDEBugger and all my memory is in the global context (and store only once).

SDL resetting glViewport

I'm testing supporting multiple resolutions in an application using SDL2 with OpenGL. To create my "letterbox" functionality I set my glViewport to an appropriate value and everything works perfectly.
However, if I create my window with the SDL_WINDOW_ALLOW_HIGHDPI flag set, whenever I move my window (after receiving the SDL_WINDOWEVENT_MOVED event) SDL modifies the viewport to the full size of the window, which can be verified by calling SDL_GL_GetDrawableSize during the event.
If I do not set SDL_WINDOW_ALLOW_HIGHDPI when creating the window, the viewport is not reset. I do believe this to be a bug, but cannot find anything through the SDL bugzilla so I thought to ask if anyone has seen similar behavior.
You may need to have a retina MacBook Pro to experience this behavior.
Just do what you should be doing anyway: Always re-/set the viewport at the beginning of drawing each frame. As soon as you want to implement a HUD, use framebuffer objects or similar things you'll have to set the viewport (several times) for drawing each frame.

pyqt : Why QGLWidget influenced by maya event?

openGL with maya
I made a openGL View with QGLWidget. It has a problem when work with Maya. As you see in video, when I click and move on a modelPanel within Maya, the QGLWidget get broken. And I found that the marquee rectangle is shown on my QGLWidget, not Maya. Why this problem happend?
To datenwolf
I tried to edit my code as you suggested. But... it doesn't call makeCurrent() and doneCurrent() at all. I expected that when I clicked on my maya modelPanel it could send me the message, but it didn't. What did I miss? Sorry for that.
def makeCurrent(self):
import OpenGL.WGL as wgl
print "MAKE CURRENT!!!"
self.prevHDC = wgl.wglGetCurrentDC()
self.prevHRC = wgl.wglGetCurretnContext()
super(GLWidget, self).makeCurrent()
def doneCurrent(self):
import OpenGL.WGL as wgl
print "DONE CURRENT!!!"
super(GLWidget, self).doneCurrent()
wgl.wglMakeCurrent(self.prevHDC, self.prevHRC)
I wrote just like above. But it never even show the "MESSAGE".
Most likely Qt and Maya's event loop are battling for processing event. Qt's paintGL does the right thing and makes the OpenGL context current whenever it is called. Maya however does not and so drawing commands of Maya end up in your OpenGL context.
Playing along with Maya is going to be tricky, because it requires storing which OpenGL/DC context was active before switching and restoring that once finished with one own's operations. You'll probably have to subclass QGLWidget and QGLContext to do this.
Update due to comment
Derive from QGLWidget, add two members HDC m_prevHDC and HRC m_prevHRC, override makeCurrent and doneCurrent
void QMyGLWidget::makeCurrent()
{
this->m_prevHDC = wglGetCurrentDC();
this->m_prevHRC = wglGetCurrentContext();
QGLWidget::makeCurrent();
}
void QMyGLWidget::doneCurrent()
{
QGLWidget::doneCurrent();
wglMakeCurrent(this->m_prevHDC, this->m_prevHRC);
}
Then derive your actual GLWidget from this intermediary class.