So I recently started to use PyOpenGL's GLUT module and cannot find any simple tutorials on it (links to any would be appreciated) and I just want to create a glut window using glutCreateWindow('window'), but as soon as the window pops up it disappears. I tried using glutMainLoop() in my main function but it just gives an error.
from OpenGL.GLU import *
from OpenGL.GL import *
glutInit()
def main():
glutCreateWindow('window')
glutMainLoop()
if __name__=='__main__':main()
You must set glutDisplayFunc callback. The glut main loop invokes the display call back.
Minimal example:
from OpenGL.GLUT import *
from OpenGL.GLU import *
from OpenGL.GL import *
glutInit()
def display():
glClearColor(1, 0, 0, 0) # red
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
# your rendering goes here
# [...]
glutSwapBuffers()
glutPostRedisplay()
def main():
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA)
glutCreateWindow('window')
glutDisplayFunc(display)
glutMainLoop()
if __name__=='__main__':
main()
glutInitDisplayMode sets the initial display mode. glutSwapBuffers swaps the buffers of the current window ant and thus updates the display. glutPostRedisplay marks the current window as redisplayed and therefore causes the display to be continuously redrawn, which is necessary for animations.
See also Immediate mode and legacy OpenGL
Related
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 want to create the opengGL context using freeglut. I will first decide the which context to by checking the supporting version using glew and some other parameters. I know for glew to work, it needs a opengl context. So I first create a context using glutCreateWindow, then check the supported version and then set the version required using the glutInitContextVersion() and destroy the previous window using glutDestroyWindow and recreate the new window by using glutCreateWindow. I get this error Freeglut error: ERROR: No display callback registered for window 1 (I checked 1 is ID for my previous window which I destroyed) . Following is my code
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(900, 600);
int winID = glutCreateWindow("Rotating Cube"); //winID is 1 here
glewExperimental = GL_TRUE;
glewInit();
//I decide the context on some other parameters also except the supported version reported by glew.
//I have tested this with opengl 3.2 core profile as well.
//This is not working even if I forcefully set the opengl version to 2.0
if (glewIsSupported("GL_VERSION_3_1"))
{
glutInitContextVersion (3, 1);
glutInitContextFlags (GLUT_FORWARD_COMPATIBLE);
//glutInitContextVersion (3, 2);
//glutInitContextFlags (GLUT_CORE_PROFILE);
}
else if (glewIsSupported("GL_VERSION_2_0"))
{
glutInitContextVersion (2, 0);
}
glutDestroyWindow(winID);
winID = glutCreateWindow("Rotating Cube"); //winID is 2 here
glutSetWindow(winID);
glutDisplayFunc(RenderScene);
glutIdleFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutKeyboardFunc(ProcessNormalKeys);
glutSpecialFunc(ProcessSpecialKeys);
glutMainLoop();
I think I need to do this as a openGL context is always required for glew to work. I already tried setting the display function on first window as well (though I know I am going to destroy it) but that also didn't work. I am setting the current window to new window and then calling the glutMainLoop. So I think this should work
According to answer by rhashimoto, I tried to put the destroy command at different positions
if (g_winID>=0)
{
glutDestroyWindow(g_winID);
g_winID = -1;
}
I put the destroy command at begining of reshape callback
ERROR: No display callback registered for window 1
The I put the destroy command at beginning of display function
ERROR: Function <glutSwapBuffers> called with no current window defined.
If I put this at end of Display callback, it does not give error but the displayed scene is not correct. Somethings are missing from the scene
So is there some specific callback function I need to put this display command? I dont think there is any destroy callback I can set. yes there is glutCloseFunc but I think that is meant to be called when window is being destroyed that is when glutDestroyWindow has been called on window
I think you can argue that this is a FreeGLUT bug, either in the implementation or the documentation. It looks like glutDestroyWindow() needs to be called from a GLUT callback to work properly.
glutDestroyWindow() mainly puts the window on a list to be destroyed, as well as clearing all callbacks (except a destroy callback). This is probably why setting the display function didn't work for you - it was removed when you called glutDestroyWindow().
Windows are actually destroyed at the end of each main loop. So on the first time through the loop, your window still exists. The fact that it has no display callback makes GLUT unhappy.
The best workaround is probably to arrange to call glutDestroyWindow() only via one of the GLUT callbacks. I don't know if this will make the window briefly flash on the screen. My guess is it won't, but it might depend on the platform.
I have reinstalled devcpp 4.9.9.2 on windows xp virtualbox and installed glut and glew.
My original program just used glut, and shows some spheres bouncing around a room. My problem is that once I add in the line
glGenFramebuffers(1, &myBuffer);
my program fails to run. It compiles just fine. But when I run it says "Ass1.exe has encountered a problem and needs to close. We are sorry for the inconvenience.".
If I comment out this line then it works just fine, with balls bouncing around. The glGenFramebuffers is at the bottom of my setup method.
Here is a link to my code. https://dl.dropboxusercontent.com/u/13330596/Exercise1.cpp
This is the code just before I now call glewInit();
// Initialize GLUT.
glutInit(&argc, argv);
// Set display mode with an RGB colour buffer, double buffering and a depth buffer..
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
// Set OpenGL window size
glutInitWindowSize(1000, 1000);
// Set position of OpenGL window upper-left corner
glutInitWindowPosition(100, 100);
// Create OpenGL window with title
glutCreateWindow("Dissertation");
glewInit();
You must call glewInit(); before you can use extended functionality. Probably you didn't so the functions pointers are still null pointer. glewInit must be called after a context has been created and bound. In the case of using GLUT this is right after glutCreateWindow(…);
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.
I have a main window which has both a glut UI in the top 10% of the screen, and the openGL world in the bottom 90% of the screen. Every time my cursor starts hovering over the GLUT portion, openGL rendering will freeze. It resumes only when the cursor exits the GLUT area.
This is because as long as the cursor is hovering over the GLUT area, presumably glutIdleFunc is never called because glut is not "idle", so openGL stuff is not rendered.
I already tried making a new unrelated thread that just calls the display code and/or glutPostRedisplay but I got a framerate of whopping 20 fps as opposed to the 100+ fps the normal way. I don't know exactly why. (In this test I also disabled glutIdleFunc so there is no idle func, just the separate thread calling the display)
Ways to get around this (other than "stop using glut" which I might do in the future but for now I would like a temporary solution)?
I know this is an old question, but I was having a similar issue and wanted to share how I solved it.
Basically, in your idle function, you should manually set the window to your normal window ID. Thanks to Joel Davis' HexPlanet code ( https://github.com/joeld42/hexplanet/ ) for demonstrating this:
void glut_Idle( void )
{
// According to the GLUT specification, the current window is
// undefined during an idle callback. So we need to explicitly change
// it if necessary
if ( glutGetWindow() != g_glutMainWin )
{
glutSetWindow(g_glutMainWin);
}
...
}
Create a callback for passive motion func:
void passiveMouseFunc(int,int){
glutPostRedisplay();
}
And register it using:
glutPassiveMotionFunc(passiveMouseFunc);