OpengL 我的广场在哪里?

OpengL Where is my square?

我不明白为什么 glDrawElements 不工作。我已经成功地使用了 glDrawArrays。但是当我尝试使用 glDrawElements 绘图时,它不起作用。

我正在关注 learnopengl.com 网站在 python 中的教程,所以这让我有点头疼。知道为什么这不起作用吗?我已经看了快一天了,看不出我的方法有什么错误。

import glfw
import numpy as np
import OpenGL

from OpenGL.GL import *
from OpenGL.GL import shaders, ArrayDatatype
from ctypes import sizeof, c_float, c_void_p

def main():
    width = 800
    height = 600
    title = 'Hello Triangle'

    vertex = """#version 410 core
        in vec3 aPos;
        void main() {
            gl_Position = vec4(aPos, 1.0);
        }"""
    fragment = """#version 410 core
        out vec4 FragColor;
        void main() {
            FragColor = vec4(1.0, 0.5, 0.2, 1.0);
        }"""

    if not glfw.init():
        raise TypeError('Unable to initalize glfw')

    glfw.window_hint(glfw.SAMPLES, 4)
    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 4)
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)
    glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
    glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True)
    glfw.window_hint(glfw.OPENGL_DEBUG_CONTEXT, True)

    window = glfw.create_window(width, height, title, None, None)
    if not window:
        raise TypeError('Unable to create the window')
    glfw.make_context_current(window)
    glfw.set_framebuffer_size_callback(window, framebuffer_size)

    verts = np.array([[-0.5, 0.5, 0.0], [-0.5, -0.5, 0.0], [0.5, -0.5, 0.0], [0.5, 0.5, 0.0]], dtype=np.float)
    indices = np.array([[0, 1, 3], [3, 1, 2]], dtype=np.uint)

    vertex_shader = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertex_shader, vertex)
    glCompileShader(vertex_shader)

    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragment_shader, fragment)
    glCompileShader(fragment_shader)

    shader_program = glCreateProgram()
    glAttachShader(shader_program, vertex_shader)
    glAttachShader(shader_program, fragment_shader)
    glLinkProgram(shader_program)

    glDeleteShader(vertex_shader)
    glDeleteShader(fragment_shader)

    vao_id = glGenVertexArrays(1)
    vbo_id = glGenBuffers(1)
    ebo_id = glGenBuffers(1)

    glBindVertexArray(vao_id)

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_id)
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW)
    #glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)

    glBindBuffer(GL_ARRAY_BUFFER, vbo_id)
    glBufferData(GL_ARRAY_BUFFER, verts, GL_STATIC_DRAW)
    glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)
    glEnableVertexAttribArray(0)

    #glBindBuffer(GL_ARRAY_BUFFER, 0)

    #glBindVertexArray(0)

    while not glfw.window_should_close(window):
        glClearColor(0.2, 0.3, 0.3, 1.0)
        glClear(GL_COLOR_BUFFER_BIT)

        glUseProgram(shader_program)
        glBindVertexArray(vao_id)
        glEnableVertexAttribArray(0)
        #glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
        glBindVertexArray(0)

        glfw.swap_interval(1)
        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.destroy_window(window)
    glfw.terminate()

def framebuffer_size(window, width, height):
    glViewport(0, 0, width, height)


if __name__ == '__main__':
    main()

这段代码中有两个棘手的问题需要解决,这两个问题都很微妙,python-specific。

首先,您应该将 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0) 中的 0 替换为 None。我怀疑这是因为 PyOpenGL 使用 ctypes 包装 OpenGL 并且建议 None 根据 ctypes documentation. If you need to use offsets for your buffers later, you should look at this answer.

表示 NULL 指针

其次,如果您只执行步骤 1 和 运行 代码,您可能会发现输出不是您所期望的:

我们的橙色矩形怎么了?好吧,这里的问题是我们传递给缓冲区对象的数据。如果您使用的是 64 位设备,则 numpy 数据类型 (dtype) 如果未完全指定,也将是 64 位的。 OpenGL 需要 32 位浮点数和整数而不是双精度数,因此我们需要使用 np.float32 代替。为了保持一致性,我也会使用 np.uint32 作为索引缓冲区,但这并不是绝对必要的。如果我们将您的 vertsindices 初始化语句修改为:

verts = np.array([[-0.5, 0.5, 0.0], [-0.5, -0.5, 0.0], [0.5, -0.5, 0.0], [0.5, 0.5, 0.0]], dtype=np.float32)
indices = np.array([[0, 1, 3], [3, 1, 2]], dtype=np.uint32)

结果应该更符合您的预期:

希望对您有所帮助!