Búfer de profundidad de lectura con PyOpenGL

Básicamente, estoy tratando de extraer un mapa de profundidad (con esto me refiero a una matriz con z correspondiente a las coordenadas z para los vértices en la GL.glVertex3dv(vertex) – obviamente, interpolada para píxeles del plano) después de renderizar un modelo (el script es cargando el modelo desde el archivo con la ruta especificada como el primer argumento de la línea de comando).

Hay varias preguntas que vienen a la mente:

El código en sí:

 import sys import argparse import pyassimp from pyassimp.postprocess import aiProcess_JoinIdenticalVertices, aiProcess_Triangulate import numpy as np import matplotlib.pyplot as plt from collections import namedtuple from OpenGL import GL, GLUT Mesh = namedtuple('Mesh', ('vertices', 'faces')) def load_mesh(filename): scene = pyassimp.load(filename, processing=aiProcess_JoinIdenticalVertices | aiProcess_Triangulate) mesh = scene.mMeshes[0].contents def get_vector_array(vector): return [vector.x, vector.y, vector.z] def get_face_array(face): return [face.mIndices[i] for i in xrange(face.mNumIndices)] vertices = np.array([get_vector_array(mesh.mVertices[i]) for i in xrange(mesh.mNumVertices)]) faces = np.array([get_face_array(mesh.mFaces[i]) for i in xrange(mesh.mNumFaces)]) pyassimp.release(scene) return Mesh(vertices, faces) def load_ortho(): GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glOrtho(-1, 1, -1, 1, -1, 1) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() mesh = None width, height = 1920, 1080 def draw_mesh(): global mesh, width, height GL.glClearColor(0, 0, 0, 0) GL.glClearDepth(0.5) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) GL.glDepthMask(GL.GL_TRUE) load_ortho() for face in mesh.faces: GL.glBegin(GL.GL_POLYGON) for vertex in mesh.vertices[face]: GL.glVertex3dv(vertex) GL.glEnd() GLUT.glutSwapBuffers() d = GL.glReadPixels(0, 0, width, height, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT) plt.imshow(d) plt.show() def reshape(w, h): GL.glViewport(0, 0, w, h) GLUT.glutDisplayFunc(draw_mesh) GLUT.glutPostRedisplay() def init(width, height): GLUT.glutInit(sys.argv) GLUT.glutInitDisplayMode(GLUT.GLUT_RGBA | GLUT.GLUT_DOUBLE) GLUT.glutInitWindowSize(width, height) GLUT.glutInitWindowPosition(0, 0) GLUT.glutCreateWindow("test") # GLUT.glutDisplayFunc(draw_mesh) # GLUT.glutIdleFunc(draw_mesh) GLUT.glutReshapeFunc(reshape) GLUT.glutIdleFunc(GLUT.glutPostRedisplay) def keyPressed(self, *args): if args[0] == '\033': sys.exit() GLUT.glutKeyboardFunc(keyPressed) if __name__ == '__main__': parser = argparse.ArgumentParser("Test on extracting depth while rendering a model with PyOpenGL") parser.add_argument("model", type=str) args = parser.parse_args() global mesh mesh = load_mesh(args.model) init(width, height) draw_mesh() 

El archivo modelo que utilicé personalmente para la prueba: bunny.obj El resultado del fragmento está aquí

Ejecutar su código me dio algunos mensajes de "Invalid Operation Error: 1282" glReadPixels "Invalid Operation Error: 1282" para la llamada a glReadPixels . En su lugar, aquí hay una simple demostración que acabo de escribir que muestra cómo obtener el color y el búfer de profundidad de OpenGL para un triángulo renderizado. Lo que hago aquí es enlazar un FBO (objeto framebuffer) a la pantalla con los adjuntos de textura deseados (para recibir los datos de color y profundidad). Luego leí los datos de la GPU usando glGetTexImage . Usar texturas puede que no sea el enfoque más rápido, pero es bastante simple y debería funcionar bien. Déjame saber si algo de esto no está claro y lo explicaré.

 from OpenGL.GL import * from OpenGL.GLUT import * import numpy as np import sys def draw_scene(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glBegin(GL_TRIANGLES) glColor3f(1, 0, 0) glVertex3f(-1, -1, 0) glColor3f(0, 1, 0) glVertex3f(0, 1, 0) glColor3f(0, 0, 1) glVertex3f(1, -1, 0) glEnd() def draw_texture(): global color_texture glColor3f(1, 1, 1) glBindTexture(GL_TEXTURE_2D, color_texture) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glBegin(GL_QUADS) glTexCoord2f(0, 0) glVertex3f(-1, -1, 0) glTexCoord2f(0, 1) glVertex3f(-1, 1, 0) glTexCoord2f(1, 1) glVertex3f(1, 1, 0) glTexCoord2f(1, 0) glVertex3f(1, -1, 0) glEnd() glBindTexture(GL_TEXTURE_2D, 0) def update_display(): global fbo, color_texture, depth_texture #Render the scene to an offscreen FBO glBindFramebuffer(GL_FRAMEBUFFER, fbo) draw_scene() glBindFramebuffer(GL_FRAMEBUFFER, 0) #Then render the results of the color texture attached to the FBO to the screen draw_texture() #Obtain the color data in a numpy array glBindTexture(GL_TEXTURE_2D, color_texture) color_str = glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE) glBindTexture(GL_TEXTURE_2D, 0) color_data = np.fromstring(color_str, dtype=np.uint8) #Obtain the depth data in a numpy array glBindTexture(GL_TEXTURE_2D, depth_texture) depth_str = glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT) glBindTexture(GL_TEXTURE_2D, 0) depth_data = np.fromstring(depth_str, dtype=np.float32) print(np.min(depth_data), np.max(depth_data))#This is just to show the normalized range of depth values obtained glutSwapBuffers() width, height = 800, 600 fbo = None color_texture = None depth_texture = None if __name__ == '__main__': glutInit([]) glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE) glutInitWindowSize(width, height) glutInitWindowPosition(0, 0) glutCreateWindow("Triangle Test") glEnable(GL_TEXTURE_2D)#not needed if using shaders... glEnable(GL_DEPTH_TEST) color_texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, color_texture) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, None) glBindTexture(GL_TEXTURE_2D, 0) depth_texture = glGenTextures(1) glBindTexture(GL_TEXTURE_2D, depth_texture) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None) glBindTexture(GL_TEXTURE_2D, 0) fbo = glGenFramebuffers(1) glBindFramebuffer(GL_FRAMEBUFFER, fbo) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture, 0) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0) glBindFramebuffer(GL_FRAMEBUFFER, 0) glutDisplayFunc(update_display) glutIdleFunc(glutPostRedisplay) glutMainLoop()