Search code examples
pythonopenglglut

Capture screen using Glut and OpenGL with Python


I'm using Python and OpenGL to make some calculations related to a physical system and then display them and be able to manipulate the image rotating it, translating it, ...

I'm not a professional programmer and I have little experience using OpenGL and I'm having some issues trying to get what I want. I would like to be able to save the window that I get as an output in a video file and to do so I've seen the possibility of using glReadPixels to capture each frame and then put them all together.

I am using right now something that looks like the following code and I want to be able to save the frames to images but, although I've been able to save to save the pixels to an array using glReadPixels, I don't know where nor how to call the function that I've defined as captureScreen. What should I do to get the output that I'm looking for?

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from PIL import Image
from scipy import *
import numpy as np
import random as rnd

def captureScreen(file_):

    glPixelStorei(GL_PACK_ALIGNMENT, 1)
    data = glReadPixels(0, 0, 800, 800, GL_RGBA, GL_UNSIGNED_BYTE)
    image = Image.fromstring("RGBA", (800, 800), data)
    image.save(file_, 'png')

def main():  

     glutInit(sys.argv)
     glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)
     glutInitWindowPosition(0, 0)
     glutInitWindowSize(800, 800)

     glutCreateWindow ("Test")

     glEnable(GL_DEPTH_TEST)
     glDepthMask(GL_TRUE)
     glEnable(GL_BLEND)
     glEnable(GL_TEXTURE_2D)
     glEnable(GL_COLOR_MATERIAL)
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
     glPointSize( 6.0 )
     glLineWidth( 2.0 )
     glEnable(GL_POINT_SMOOTH)
     glEnable(GL_LINE_SMOOTH)
     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
     glEnable(GL_POLYGON_SMOOTH)
     glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)

     glEnableClientState(GL_VERTEX_ARRAY)
     glEnableClientState(GL_COLOR_ARRAY)

     glClearColor(0.0, 0.0, 0.0, 0.0)

     glutFullScreen()
     glutKeyboardFunc(keyboard)
     glutIdleFunc(dynamics)
     glutDisplayFunc(display)
     glutMouseFunc(mouse)


     glutMainLoop()


if __name__ == '__main__':

     main()

keyboard, display, dynamics and mouse are functions previously defined.


Solution

  • You can call glReadPixels() just after glutSwapBuffers():

    glutSwapBuffers()
    glReadBuffer(GL_FRONT)
    glReadPixels(...)
    

    Or just before:

    glReadBuffer(GL_BACK)
    glReadPixels(...)
    glutSwapBuffers()
    

    So captureScreen() should be called from your "display" function which is probably the one which calls glutSwapBuffers()