PyOpenGL - 最小的glDrawArrays示例

问题描述 投票:1回答:1

我已经看过许多最小的PyOpenGL示例,但我找到的没有一个使用VAO或glDrawArrays / glDrawElements。相反,他们都使用glVertex,过剩形状,偶尔使用旧的glCallList函数。

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

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

附:我不是在使用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()
python opengl glsl pyopengl opengl-4
1个回答
1
投票

如果绑定了命名数组缓冲区对象,则glVertexAttribPointer的最后一个参数(第6个参数)将被视为缓冲区对象数据存储中的字节偏移量。参数的数据类型必须是ctypes.c_void_p

这意味着你必须使用ctypes.cast

EG

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

EG

gl_Position = u_view * u_model * a_pos;
© www.soinside.com 2019 - 2024. All rights reserved.