我本学期开始介绍计算机图形学,目前正在使用PyOpenGL和PyQt5来探索重心坐标。我的同学使用Windows机器能够运行以下代码而没有开箱即用的问题,但OSX上的所有人都遇到了同样的问题。我希望那里的其他人有更多这种环境的经验,可能会想到我们如何解决这些问题;我们已经做了大量的谷歌搜索,没有结果。谢谢!
代码:
import sys from array import array from ctypes import c_void_p from OpenGL.GL import * from OpenGL.GLU import * from PyQt5.QtGui import QImage, qRgb from PyQt5.QtOpenGL import QGLWidget from PyQt5.QtWidgets import QApplication from textwrap import dedent # create a function that draws a triangle via software rasterization def softwareRasterization(width, height, vertices, colors): image = QImage(width, height, QImage.Format_RGB32) # TODO: compute the bounding box around the given vertices # TODO: compute the barycentric coordinates for each point in the box # TODO: color the points that are inside of the triangle if image.save("triangle.jpg", None, 100): print("Output triangle.jpg") else: print("Unable to save triangle.jpg") # extend QGLWidget to draw a triangle via hardware rasterization class HardwareRasterizationWidget(QGLWidget): def __init__(self, vertices, colors, *args, **kwargs): super().__init__(*args, **kwargs) self.vertices = array('f') # TODO: convert the input coordinate to normalized device coordinates self.colors = array('f', colors) def _sizeof(self, a): return a.itemsize * len(a) def initializeGL(self): verticesSize = self._sizeof(self.vertices) # create a new Vertex Array Object on the GPU which saves the attribute # layout of our vertices vao = glGenVertexArrays(1) glBindVertexArray(vao) # create a buffer on the GPU for position and color data dataBuffer = glGenBuffers(1) # upload the data to the GPU, storing it in the buffer we just created # TODO: upload the color data into the GPU buffer as well glBindBuffer(GL_ARRAY_BUFFER, dataBuffer) glBufferData( GL_ARRAY_BUFFER, verticesSize, None, GL_STATIC_DRAW ) glBufferSubData( GL_ARRAY_BUFFER, 0, verticesSize, self.vertices.tostring() ) # load our vertex and fragment shaders into a program object on the GPU program = self.loadShaders() # bind the attribute "position" (defined in our vertex shader) to the # currently bound buffer object, which contains our position data # this information is stored in our vertex array object position = glGetAttribLocation(program, 'position') glEnableVertexAttribArray(position) glVertexAttribPointer( position, 3, GL_FLOAT, GL_FALSE, 0, c_void_p(0) ) # TODO: bind the attribute "color" to the buffer object def loadShaders(self): # create a GL Program Object program = glCreateProgram() # vertex shader # TODO: add a color input and color output vs_source = dedent(""" #version 330 in vec3 position; void main() { gl_Position = vec4(position, 1.0); }\ """) vs = glCreateShader(GL_VERTEX_SHADER) glShaderSource(vs, vs_source) glCompileShader(vs) glAttachShader(program, vs) if glGetShaderiv(vs, GL_COMPILE_STATUS) != GL_TRUE: raise RuntimeError(glGetShaderInfoLog(vs)) # fragment shader # TODO: add a color input with the same name as the vertex output fs_source = dedent(""" #version 330 void main() { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }\ """) fs = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(fs, fs_source) glCompileShader(fs) glAttachShader(program, fs) if glGetShaderiv(fs, GL_COMPILE_STATUS) != GL_TRUE: raise RuntimeError(glGetShaderInfoLog(fs)) # use the program glLinkProgram(program) glUseProgram(program) return program def paintGL(self): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glDrawArrays(GL_TRIANGLES, 0, 3) def resizeGL(self, width, height): glViewport(0, 0, width, height) if __name__ == "__main__": width = 640 height = 480 # TODO: prompt the user for 3 points and colors separated by spaces # TODO: validate input and parse into the vertices and colors lists vertices = [ 50, 50, 0, # vertice 1 600, 20, 0, # vertice 2 300, 400, 0 # vertice 3 ] colors = [ 1, 0, 0, # color 1 0, 1, 0, # color 2 0, 0, 1 # color 3 ] softwareRasterization(width, height, vertices, colors) app = QApplication(sys.argv) w = HardwareRasterizationWidget(vertices, colors) pRatio = w.devicePixelRatio() w.resize(width/pRatio, height/pRatio) w.show() sys.exit(app.exec_())
错误:
Traceback (most recent call last): File "/Users/JesseRichmond/vEnvPyCharm/lib/python3.5/site-packages/OpenGL/latebind.py", line 41, in __call__ return self._finalCall( *args, **named ) TypeError: 'NoneType' object is not callable During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/Users/JesseRichmond/Desktop/Spring 2017 Academics/Projects/310/rasterization.py", line 45, in initializeGL vao = glGenVertexArrays(1) File "/Users/JesseRichmond/vEnvPyCharm/lib/python3.5/site-packages/OpenGL/latebind.py", line 45, in __call__ return self._finalCall( *args, **named ) File "/Users/JesseRichmond/vEnvPyCharm/lib/python3.5/site-packages/OpenGL/wrapper.py", line 657, in wrapperCall result = wrappedOperation( *cArguments ) File "/Users/JesseRichmond/vEnvPyCharm/lib/python3.5/site-packages/OpenGL/platform/baseplatform.py", line 407, in __call__ self.__name__, self.__name__, OpenGL.error.NullFunctionError: Attempt to call an undefined function glGenVertexArrays, check for bool(glGenVertexArrays) before calling