PyOpenGL - Пример минимального glDrawArrays - PullRequest
1 голос
/ 18 апреля 2019

Я видел много минимальных примеров PyOpenGL, но ни один из тех, что я нашел, не использует VAO или glDrawArrays / glDrawElements.Вместо этого все они используют glVertex, формы переизбытка и иногда старую функцию glCallList.

Я сейчас пытаюсь написать минимальный рабочий пример, который использует массивы вершин и буферы для данных вершин.Если я правильно понимаю PyOpenGL, следующий код должен нарисовать один белый треугольник на экране, но вместо этого я получаю пустой экран.

Что я могу делать неправильно?У меня также возникли трудности с пониманием документации PyOpenGL .Многие из функций определены одним способом, но используются во многих местах и ​​работают совершенно по-другому, а некоторые даже не работают так, как они определены (например, glGenBuffers , которая утверждает, что принимаетдва аргумента, но, похоже, принимает только один и возвращает сгенерированные буферы).

ps Я не использую ни 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()

1 Ответ

1 голос
/ 18 апреля 2019

Если указанный буферный объект массива связан, то последний параметр (6-й параметр) glVertexAttribPointer обрабатывается как смещение байта в хранилище данных объекта буфера. Тип данных параметра должен быть ctypes.c_void_p.

Это означает, что вы должны использовать ctypes.cast:

1010 *, например *

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 / Векторные и матричные операции

* * 1 022, например,
gl_Position = u_view * u_model * a_pos;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...