我已经看到了很多最小的PyOpenGL示例,但是我发现没有一个使用VAO或glDrawArrays / glDrawElements。取而代之的是,它们都使用glVertex,过大的形状,有时还使用旧的glCallList函数。
我现在正在尝试编写一个最小的工作示例,该示例使用顶点数组和缓冲区存储顶点数据。如果我对PyOpenGL的理解正确,则以下代码应在屏幕上绘制一个白色三角形,但是却出现了空白屏幕。
我可能做错了什么?我在理解PyOpenGL documentation方面也遇到了一些困难。许多函数是用一种方法定义的,但是在许多地方使用并且以完全不同的方式工作,有些甚至似乎无法按照定义的方式工作(例如,glGenBuffers表示它接受两个参数,但似乎只接受其中一个并返回生成的缓冲区。
p.s。我没有使用numpy或pygame。
from OpenGL.GLUT import * from OpenGL.GLU import * from OpenGL.GL import * import ctypes import sys name = 'PyOpenGL Example' vao = None program = None def main(): glutInit(sys.argv) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) glutInitContextVersion(4,0) glutInitWindowSize(600,400) glutCreateWindow(name) print(glGetString(GL_VERSION)) glClearColor(0,0,0,1) glutDisplayFunc(display) # glutMouseFunc(callback) # glutMotionFunc(callback) # glutPassiveMotionFunc(callback) # glutKeyboardFunc(callback) # glutSpecialFunc(callback) vshader = glCreateShader(GL_VERTEX_SHADER) fshader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(vshader,[""" #version 400 uniform mat4 u_model; uniform mat4 u_view; in vec4 a_pos; in vec4 a_color; in vec4 a_normal; out vec4 v_color; out vec4 v_normal; void main() { gl_Position = a_pos; // * u_model * u_view; v_color = a_color; v_normal = normalize(a_normal); } """]) glCompileShader(vshader) msg = glGetShaderInfoLog(vshader) if msg: print(f"Failed to compile Vertex Shader: {msg}") exit(0) glShaderSource(fshader,[""" #version 400 uniform mat4 u_model; uniform mat4 u_view; in vec4 v_color; in vec4 v_normal; layout(location=0) out vec4 f_color; void main() { f_color = v_color; } """]) glCompileShader(fshader) msg = glGetShaderInfoLog(fshader) if msg: print(f"Failed to compile Fragment Shader: {msg}") exit(0) global program program = glCreateProgram() glAttachShader(program,vshader) glAttachShader(program,fshader) glLinkProgram(program) msg = glGetProgramInfoLog(program) if msg: print(f"Failed to link Program: {msg}") exit(0) glUseProgram(program) uniforms = { 'model': glGetUniformLocation(program,'u_model'), 'view': glGetUniformLocation(program,'u_view'), } print(uniforms) attrs = { 'pos': glGetAttribLocation(program,'a_pos'), 'color': glGetAttribLocation(program,'a_color'), 'normal': glGetAttribLocation(program,'a_normal'), } print(attrs) global vao vao = glGenVertexArrays(1) glBindVertexArray(vao) verts = [ -1, -1, 0, 1, 1, -1, 0, 1, 0, 1, 0, 1, ] colors = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ] normals = [ 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) identity = [ 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() return def display(): glUseProgram(program) glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) glViewport(0,0,600,400) print(vao) glBindVertexArray(vao) glDrawArrays(GL_TRIANGLES,0,3) glBindVertexArray(0) glutSwapBuffers() return def callback(*args): print(*args) if __name__ == '__main__': main()
答案 0 :(得分: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;