【发布时间】:2018-06-19 15:45:11
【问题描述】:
基本上,我正在尝试在渲染模型(脚本为从文件加载模型,路径指定为第一个命令行参数)。
我想到了几个问题:
为什么
glReadPixels调用返回一个形状为(width, shape)的numpy 数组,而不是(height, width)?为什么它返回一些垃圾,没有连接到渲染模型?
有没有一种简单的方法可以使用 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()
【问题讨论】:
-
在正交投影中,Z 坐标被线性映射到深度值(参见this question)。深度值在 [0.0, 1.0] 范围内。所以视图空间中的 Z 坐标是
z = -near - depth*(far-near)。在您的情况下,它是z = 1 - 2*depth;。因为您没有设置任何模型视图矩阵(GL_MODELVIEW),所以视图空间等于世界空间。 -
也可能是愚蠢的问题:看起来您没有在任何地方调用
glClear来清除颜色和深度缓冲区。glClearColor和glClearDepth只是设置清除应该执行的值,但实际上并不执行缓冲区本身的清除。这或许可以解释您所看到的“垃圾”。 -
@CodeSurgeon 这没有帮助。相应地更新了 sn-p。还添加了 sn-p 的输出。