我见过许多最小的PyOpenGL示例,但我发现的没有一个使用VAO或glDrawArrays/glDrawElements。相反,它们都使用 glVertex、glut 形状,偶尔还会使用旧的 glCallList 函数。
我现在正在尝试编写一个最小的工作示例,该示例使用顶点数组和缓冲区来处理顶点数据。如果我正确理解 PyOpenGL,下面的代码应该在屏幕上画一个白色三角形,但我得到一个空白屏幕。
我可能做错了什么?我也很难理解 PyOpenGL 文档。许多函数都是以一种方式定义的,但在很多地方使用并以完全不同的方式工作,有些甚至似乎没有按照定义的方式工作(例如glGenBuffers,它声明它接受两个参数,但似乎只接受一个并返回生成的缓冲区)。
附言我没有使用 numpy 或 pygame。
从 OpenGL.GLUT 导入 * 从 OpenGL.GLU 导入 * 从 OpenGL.GL 进口 * 导入 ctypes 导入系统 name = 'PyOpenGL Example' vao = 无 程序 = 无 def main(): glutInit(sys.argv) glutInitDisplayMode(GLUT_DOUBLE |GLUT_RGB |GLUT_DEPTH) glutInitContextVersion(4,0) 贪吃窗口大小(600,400) glutCreateWindow(name) print(glGetString(GL_VERSION)) glClearColor(0,0,0,1) 贪吃显示功能(显示) # glutMouseFunc(回调) # glutMotionFunc(回调) # glutPassiveMotionFunc(回调) # glutKeyboardFunc(回调) # glutSpecialFunc(回调) vshader = glCreateShader(GL_VERTEX_SHADER) fshader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(vshader,["" #version 400 均匀垫4 u_model; 均匀垫4 u_view; 在 VEC4 a_pos; 在 VEC4 a_color; 在 VEC4 a_normal; 出 VEC4 v_color; 出 VEC4 v_normal; void main() { gl_Position = a_pos;* u_model * u_view; v_color = a_color; v_normal = 规范化(a_normal); } """]) glCompileShader(vshader) msg = glGetShaderInfoLog(vshader) 如果味精: print(f"Failed to compile Vertex Shader: {msg}") 退出(0) glShaderSource(fshader,["" #version 400 均匀垫4 u_model; 均匀垫4 u_view; 在 VEC4 v_color; 在 VEC4 v_normal; 布局(位置=0) 输出 VEC4 f_color; void main() { f_color = v_color; } """]) glCompileShader(fshader) msg = glGetShaderInfoLog(fshader) 如果味精: print(f"无法编译片段着色器: {msg}") 退出(0) 全球计划 program = glCreateProgram() glAttachShader(program,vshader) glAttachShader(program,fshader) glLink程序(程序) msg = glGetProgramInfoLog(program) 如果味精: print(f"无法链接程序: {msg}") 退出(0) glUse程序(程序) 制服 = { 'model': glGetUniformLocation(program,'u_model'), 'view': glGetUniformLocation(program,'u_view'), } 印花(制服) 吸引力 = { 'pos': glGetAttribLocation(program,'a_pos'), 'color': glGetAttribLocation(program,'a_color'), 'normal': glGetAttribLocation(program,'a_normal'), } 打印(吸引力) 全球 VAO vao = glGenVertexArrays(1) glBindVertexArray(vao) 顶点 = [ -1, -1, 0, 1, 1, -1, 0, 1, 0, 1, 0, 1, ] 颜色 = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ] 法线 = [ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, ] vbuf,cbuf,nbuf = glGenBuffers(3) glBindBuffer(GL_ARRAY_BUFFER,vbuf) glBufferData(GL_ARRAY_BUFFER,(ctypes.c_float*len(verts))(*verts),GL_STATIC_DRAW) glVertexAttribPointer(attrs['pos'],4,GL_FLOAT,GL_FALSE,0,0) glEnableVertexAttribArray(attrs['pos']) glBindBuffer(GL_ARRAY_BUFFER,cbuf) glBufferData(GL_ARRAY_BUFFER,(ctypes.c_float*len(colors))(*colors),GL_STATIC_DRAW) glVertexAttribPointer(attrs['color'],4,GL_FLOAT,GL_FALSE,0,0) glEnableVertexAttribArray(attrs['color']) glBindBuffer(GL_ARRAY_BUFFER,nbuf) glBufferData(GL_ARRAY_BUFFER,(ctypes.c_float*len(normals))(*normals),GL_STATIC_DRAW) # glVertexAttribPointer(attrs['normal'],4,GL_FLOAT,GL_FALSE,0,0) # glEnableVertexAttribArray(attrs['normal']) glBindBuffer(GL_ARRAY_BUFFER,0) glBindVertexArray(0) 身份 = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, ] # glUniformMatrix4fv(uniforms['model'],1,GL_FALSE,(ctypes.c_float*16)(*identity)) # glUniformMatrix4fv(uniforms['view'],1,GL_FALSE,(ctypes.c_float*16)(*identity)) glutMainLoop() 返回 def display(): glUse程序(程序) glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) gl视口(0,0,600,400) 打印(VAO) glBindVertexArray(vao) glDrawArrays(GL_TRIANGLES,0,3) glBindVertexArray(0) glutSwapBuffers() 返回 def callback(*args): 打印(*参数) 如果__name__ == '__main__': main()
如果绑定了命名数组缓冲区对象,则glVertexAttribPointer
的最后一个参数(第 6 个参数)将被视为缓冲区对象数据存储中的字节偏移量。参数的数据类型必须ctypes.c_void_p
。
这意味着您必须使用ctypes.cast
:
例如
glVertexAttribPointer(attrs['pos'], 4, GL_FLOAT, GL_FALSE, 0,
ctypes.cast(0, ctypes.c_void_p))
或None
:
glVertexAttribPointer(attrs['pos'], 4, GL_FLOAT, GL_FALSE, 0, None)
进一步注意,如果在 GLSL 代码中进行矩阵变换,则必须将向量从右侧乘以矩阵。
请参阅 GLSL 编程/向量和矩阵运算
例如
gl_Position = u_view * u_model * a_pos;