Skip to content Skip to sidebar Skip to footer

Reading Depth Buffer With PyOpenGL

Basically, I'm trying to extract a depth map (by this I mean a matrix with z corresponding to z-coordinates for vertices in GL.glVertex3dv(vertex) call - obviously, interpolated fo

Solution 1:

Running your code gave me some "Invalid Operation Error: 1282" messages for the glReadPixels call. Instead, here is a simple demo I just wrote that shows how to obtain the color and the depth buffer from OpenGL for a rendered triangle. What I do here is bind an FBO (framebuffer object) to the screen with the desired texture attachments (for receiving the color and depth data). I then read out the data from the GPU using glGetTexImage. Using textures might not be the fastest approach, but this is pretty simple and should work nicely. Let me know if anything in this is unclear and I will elaborate on it.

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()

Post a Comment for "Reading Depth Buffer With PyOpenGL"