使用 python 的 OpenGL 屏幕截图

Screenshots in OpenGL using python

我们如何使用 python 截取 OpenGL windows 的屏幕截图?使用 jupyter、opengl 和 pygame。 代码是:

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
from math import *


a=[[cos(0.5*pi/180),sin(0.5*pi/180),0],
       [-sin(0.5*pi/180),cos(0.5*pi/180),0],
       [0,0,1]]
def zarb_matris(p,b): 
         c=[b[0][0]*p[0][0]+b[0][1]*p[1][0]+b[0][2]*p[2][0], 
            b[1][0]*p[0][0]+b[1][1]*p[1][0]+b[1][2]*p[2][0], 
            b[2][0]*p[0][0]+b[2][1]*p[1][0]+b[2][2]*p[2][0]] 
         return c 
          
verticies= [ 
         [1, -1, -1], 
         [1, 1, -1], 
         [-1, 1, -1], 
         [-1, -1, -1], 
         [1, -1, 1], 
         [1, 1, 1], 
         [-1, -1, 1], 
         [-1, 1, 1] 
         ] 
      
      
edges = ( 
         (0,1), 
         (0,3), 
         (0,4), 
         (2,1), 
         (2,3), 
         (2,7), 
         (6,3), 
         (6,4), 
         (6,7), 
         (5,1), 
         (5,4), 
         (5,7), 
         ) 
      
surfaces= ( 
         (0,1,2,3), 
         (3,2,7,6), 
         (6,7,5,4), 
         (4,5,1,0), 
         (1,5,7,2), 
         (4,0,3,6) 
         ) 
      
colors = ( 
         (0.9,0,0), 
         (0,1,0), 
         (0.75,0.38,0), 
         (0,0,1), 
         (1,1,0), 
         (1,1,1),    
         (1,0,0), 
         (0,1,0), 
         (0.75,0.38,0), 
         (0,0,1), 
         (1,1,0), 
         (0.9,1,1) 
         ) 
      
      
def Cube(): 
    global verticies 
    glBegin(GL_QUADS) 
    x = 0 
    for surface in surfaces: 
        x+=1 
      
       for vertex in surface: 
            glColor3fv(colors[x]) 
            glVertex3fv(verticies[vertex]) 
    glEnd() 
    glBegin(GL_LINES) 
    glColor3fv((1,1,1)) 
    for edge in edges: 
        for vertex in edge: 
            glVertex3fv(verticies[vertex]) 
    glEnd() 
      
      
def main(): 
    global s 
    pygame.init() 
    display = (800,600) 
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL) 
    glEnable(GL_DEPTH_TEST) 
    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0) 
      
    glTranslatef(1,1, -10) 
      
    while True: 
        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                pygame.quit() 
                quit() 
        glRotatef(1, 12, 0,55115 ) 
        for i in range(8): 
            s=[] 
            for j in verticies[i]: 
                s.append([j]) 
            k=zarb_matris(s,a) 
            verticies[i]=k 
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) 
        Cube() 
        pygame.display.flip() 
        pygame.time.wait(10) 
        
main()

我尝试了几种方法,但 none 似乎可行,或者需要对当前代码进行大量修改。是否有任何可用于对代码进行最低限度更改的东西,或者存在的库或文档,以便我可以尝试实现它?

使用 glReadPixels before the display is updated (before pygame.display.flip() or pygame.display.update()). Use pygame.image.fromstring() 读取帧缓冲区以从缓冲区创建新的 Surfaces。最后,将 Surface 保存到文件中:

def main(): 
    # [...]
      
    while True: 
        screenshot = False
        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                pygame.quit() 
                quit() 
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_s:
                    screenshot = True
        
        glRotatef(1, 12, 0,55115 ) 
        for i in range(8): 
            s=[] 
            for j in verticies[i]: 
                s.append([j]) 
            k=zarb_matris(s,a) 
            verticies[i]=k 

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) 
        Cube() 

        if screenshot:
            screen = pygame.display.get_surface()
            size = screen.get_size()
            buffer = glReadPixels(0, 0, *size, GL_RGBA, GL_UNSIGNED_BYTE)
            screen_surf = pygame.image.fromstring(buffer, size, "RGBA")
            pygame.image.save(screen_surf, "screenshot.jpg")

        pygame.display.flip() 
        pygame.time.wait(10)