基本上,我试图提取一个深度图(我的意思是一个矩阵,其中z对应于GL.glVertex3dv(vertex)
调用中顶点的z坐标 - 很明显,对于平面像素进行插值) model(脚本从文件加载模型,路径指定为第一个命令行参数)。
有几个问题浮现在脑海中:
为什么glReadPixels
调用会返回形状为(width, shape)
而不是(height, width)
的numpy数组?
为什么它会返回一些垃圾,而不是连接到渲染的模型?
有一种简单的方法可以使用PyOpenGL框架获取OpenGL遗留代码的z坐标吗?
这是正确的,我可以得到的最大值是一些范围为[0; 1]
的数组,基本上是zNear和zFar之间的一小部分(并且由glReadPixels归一化,无论出于何种原因)?
代码本身:
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()
答案 0 :(得分:0)
运行代码为"Invalid Operation Error: 1282"
电话提供了一些glReadPixels
条消息。相反,这是一个我刚刚编写的简单演示,演示如何从OpenGL获取渲染三角形的颜色和深度缓冲区。我在这里做的是将FBO(帧缓冲对象)绑定到具有所需纹理附件的屏幕(用于接收颜色和深度数据)。然后我使用glGetTexImage
从GPU读出数据。使用纹理可能不是最快的方法,但这很简单,应该很好用。如果有任何不清楚之处,请告诉我,我会详细说明。
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()