PyOpenGL - 最小 glDrawArrays 示例

Posted

技术标签:

【中文标题】PyOpenGL - 最小 glDrawArrays 示例【英文标题】:PyOpenGL - Minimal glDrawArrays Example 【发布时间】:2019-09-08 04:42:33 【问题描述】:

我见过很多最小的 PyOpenGL 示例,但我发现没有一个使用 VAO 或 glDrawArrays / glDrawElements。相反,它们都使用 glVertex、glut 形状,偶尔还会使用旧的 glCallList 函数。

我现在正在尝试编写一个使用顶点数组和缓冲区来存储顶点数据的最小工作示例。如果我正确理解 PyOpenGL,下面的代码应该在屏幕上绘制一个白色三角形,但我得到的是一个空白屏幕。

我可能做错了什么?我也很难理解PyOpenGL documentation。许多函数以一种方式定义,但在许多地方使用并以完全不同的方式工作,有些甚至似乎不像它们定义的方式工作(例如glGenBuffers,它声明它接受两个参数,但是似乎只接受一个并返回生成的缓冲区)。

附言我没有使用 numpy 也没有使用 pygame。

从 OpenGL.GLUT 导入 * 从 OpenGL.GLU 导入 * 从 OpenGL.GL 导入 * 导入 ctypes 导入系统 名称 = 'PyOpenGL 示例' vao = 无 程序 = 无 定义主(): glutInit(sys.argv) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) glutInitContextVersion(4,0) glutInitWindowSize(600,400) 过剩创建窗口(名称) 打印(glGetString(GL_VERSION)) glClearColor(0,0,0,1) glutDisplayFunc(显示) # glutMouseFunc(回调) # glutMotionFunc(回调) # glutPassiveMotionFunc(回调) # glutKeyboardFunc(回调) # glutSpecialFunc(回调) vshader = glCreateShader(GL_VERTEX_SHADER) fshader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(vshader,[""" #版本 400 统一 mat4 u_model; 统一 mat4 u_view; 在 vec4 a_pos; 在 vec4 a_color; 在 vec4 a_normal; 出 vec4 v_color; 出 vec4 v_normal; 无效的主要() gl_Position = a_pos; // * u_model * u_view; v_color = a_color; v_normal = normalize(a_normal); """]) glCompileShader(vshader) 味精 = glGetShaderInfoLog(vshader) 如果味精: print(f"编译顶点着色器失败:msg") 退出(0) glShaderSource(fshader,[""" #版本 400 统一 mat4 u_model; 统一 mat4 u_view; 在 vec4 v_color; 在 vec4 v_normal; layout(location=0) out vec4 f_color; 无效的主要() f_color = v_color; """]) glCompileShader(fshader) 味精 = glGetShaderInfoLog(fshader) 如果味精: print(f"编译片段着色器失败:msg") 退出(0) 全球计划 程序 = glCreateProgram() glAttachShader(程序,vshader) glAttachShader(程序,fshader) glLinkProgram(程序) 味精 = glGetProgramInfoLog(程序) 如果味精: print(f"链接程序失败:msg") 退出(0) glUseProgram(程序) 制服 = '模型':glGetUniformLocation(程序,'u_model'), '视图':glGetUniformLocation(程序,'u_view'), 打印(制服) 属性 = 'pos':glGetAttribLocation(程序,'a_pos'), '颜色':glGetAttribLocation(程序,'a_color'), '正常':glGetAttribLocation(程序,'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)) 过剩主循环() 返回 默认显示(): glUseProgram(程序) glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) glViewport(0,0,600,400) 打印(vao) glBindVertexArray(vao) glDrawArrays(GL_TRIANGLES,0,3) glBindVertexArray(0) glutSwapBuffers() 返回 def 回调(*args): 打印(*参数) 如果 __name__ == '__main__': main()

【问题讨论】:

【参考方案1】:

如果绑定了命名数组缓冲区对象,则 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 Programming/Vector and Matrix Operations

例如

gl_Position = u_view * u_model * a_pos;

【讨论】:

就是这样!?有用!哇,非常感谢。 =D也感谢矩阵提示。应该很明显:)

以上是关于PyOpenGL - 最小 glDrawArrays 示例的主要内容,如果未能解决你的问题,请参考以下文章

Python安装PyOpenGL

pyopengl 帧缓冲区

如何将 PYopenGL 写入 JPG 图像

PyOpenGL 无头渲染

我应该使用几个 glDrawArrays() 还是将所有顶点收集到一个大 glDrawArrays 调用?

Pyopengl 黑屏