В этом семестре я знакомлюсь с компьютерной графикой, в настоящее время изучаю использование 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
glGetString(GL_VERSION);
. Я знаю, что некоторые операционные системы, такие как OSX, могут быть придирчивыми и требовать, чтобы вы указали основную и дополнительную версии OpenGL для вашего приложения, чтобы создать соответствующий контекст, или они по умолчанию будут использовать устаревший контекст, такой как 2.1. Я думаю, что это может иметь место здесь, посколькуglGenVertexArrays
в конце концов является функцией OpenGL 3.0... - person CodeSurgeon   schedule 30.03.2017glGetString(GL_VERSION)
. Я получаю ошибкуProcess finished with exit code 139 (interrupted by signal 11: SIGSEGV)
даже в небольшой программе отладки, где я импортирую * из OpenGL.GL. - person Jesse Richmond   schedule 31.03.2017glGetString(GL_VERSION)
? Вы пытались поместить его в свою функциюpaintGL
? Кроме того, что интересно, я наконец установил Qt и PyQt5, и когда я запускаю ваш код (в Windows 10), я просто получаю черный экран и пустой файлtriangle.jpg
, записанный на мой жесткий диск... - person CodeSurgeon   schedule 31.03.2017