Python 如何在PyOpenGL中使用顶点数组对象和元素绘制

Python 如何在PyOpenGL中使用顶点数组对象和元素绘制,python,opengl,pyopengl,vao,Python,Opengl,Pyopengl,Vao,我有下面的代码,只需在屏幕上画一个绿色三角形。它使用顶点数组对象和索引缓冲区来绘制,并且拥有我能制作的最简单的着色器 起初,我没有使用索引缓冲区,只是简单地使用glDrawArrays进行draw调用,效果很好,但当我将其更改为使用glDrawElements时,屏幕上没有任何内容(它完全是黑色的) 如果我只是注释掉glDrawElements并取消注释glDrawArrays行,那么它工作正常,至少顶点VBO输入正确 我做错了什么?我能找到的所有OpenGL文档都表明我做得很正确,所以我显然误

我有下面的代码,只需在屏幕上画一个绿色三角形。它使用顶点数组对象和索引缓冲区来绘制,并且拥有我能制作的最简单的着色器

起初,我没有使用索引缓冲区,只是简单地使用
glDrawArrays
进行draw调用,效果很好,但当我将其更改为使用
glDrawElements
时,屏幕上没有任何内容(它完全是黑色的)

如果我只是注释掉
glDrawElements
并取消注释
glDrawArrays
行,那么它工作正常,至少顶点VBO输入正确

我做错了什么?我能找到的所有OpenGL文档都表明我做得很正确,所以我显然误解了OpenGL本身或PyOpenGL包装器

编辑

将VAO设置更改为使用更直接的OpenGL函数,而不是VBO包装,如:

vertices = np.array([[0,1,0],[-1,-1,0],[1,-1,0]], dtype='f')
vertexPositions = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vertexPositions)
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW)

#Create the index buffer object
indices = np.array([0,1,2], dtype='uint16')
indexPositions = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexPositions)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW)

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexPositions)
glBindBuffer(GL_ARRAY_BUFFER, vertexPositions)

glEnableVertexAttribArray(0) # from 'location = 0' in shader
glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)

glBindVertexArray(0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
glBindBuffer(GL_ARRAY_BUFFER, 0)

没什么区别
glDrawArrays
仍然有效,
glDrawElements
仍然无效。

谢谢@Nicolabolas。他激励我实际使用这个代码并使其工作。而不是理论化:) 我已经删除了vertexArrayObject(它是冗余的,因为我们已经有了用于顶点和索引的VBO)。 所以在调用glDraw*之前,只需绑定索引和顶点缓冲区(以及属性)。 当然,将
None
(空指针)传递到
glpaurements
索引,而不是
0
,这一点非常重要

from OpenGL.GL import shaders
from OpenGL.arrays import vbo
from OpenGL.GL import *
from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, \
                                                  glBindVertexArray

import pygame

import numpy as np

def run():
    pygame.init()
    screen = pygame.display.set_mode((800,600), pygame.OPENGL|pygame.DOUBLEBUF)

    #Create the VBO
    vertices = np.array([[0,1,0],[-1,-1,0],[1,-1,0]], dtype='f')
    vertexPositions = vbo.VBO(vertices)

    #Create the index buffer object
    indices = np.array([[0,1,2]], dtype=np.int32)
    indexPositions = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER)

    #Now create the shaders
    VERTEX_SHADER = shaders.compileShader("""
    #version 330
    layout(location = 0) in vec4 position;
    void main()
    {
        gl_Position = position;
    }
    """, GL_VERTEX_SHADER)

    FRAGMENT_SHADER = shaders.compileShader("""
    #version 330
    out vec4 outputColor;
    void main()
    {
        outputColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
    }
    """, GL_FRAGMENT_SHADER)

    shader = shaders.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)

    #The draw loop
    while True:
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        glUseProgram(shader)

        indexPositions.bind()

        vertexPositions.bind()
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)

        #glDrawArrays(GL_TRIANGLES, 0, 3) #This line still works
        glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, None) #This line does work too!

        # Show the screen
        pygame.display.flip()

run()

它似乎没有改变任何事情。我看到的所有文档(如)都建议,count是要使用的索引数。此外,我认为如果使用设置了
GL\u ELEMENT\u ARRAY\u BUFFER
1的VAO,我不必指定索引
glpaurements
获取从
索引
数组中提取的索引数。@nicolas-ok。看来你是对的。可能是这样的
glpaurements(GL\u三角形,索引)
?太棒了。现在可以了。似乎我犯过的两个主要错误是
索引的类型是
uint16
而不是
uint32
,并且我将
0
而不是
None
传递给
gldrawerelements
。我也可以将您的代码与VAO一起使用(因为它们正是我今后计划使用的)。当然,VAO是一条可行的道路。我假设vbo.vbo已经在使用它了。我错了…又错了!这些函数的作用还不清楚:
indexPositions.bind()
@nicolabolas抱歉,它们是PyOpenGL的东西。它们在内部所做的只是调用
glBindBuffer
(分别解除绑定)。类似地,
vbo.vbo()
调用
glGenBuffers
glBindBuffer
glBufferData
@nicolabolas我尝试过用实际的OpenGL命令交换这些调用(如问题编辑中所示),但似乎没有什么不同。
from OpenGL.GL import shaders
from OpenGL.arrays import vbo
from OpenGL.GL import *
from OpenGL.raw.GL.ARB.vertex_array_object import glGenVertexArrays, \
                                                  glBindVertexArray

import pygame

import numpy as np

def run():
    pygame.init()
    screen = pygame.display.set_mode((800,600), pygame.OPENGL|pygame.DOUBLEBUF)

    #Create the VBO
    vertices = np.array([[0,1,0],[-1,-1,0],[1,-1,0]], dtype='f')
    vertexPositions = vbo.VBO(vertices)

    #Create the index buffer object
    indices = np.array([[0,1,2]], dtype=np.int32)
    indexPositions = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER)

    #Now create the shaders
    VERTEX_SHADER = shaders.compileShader("""
    #version 330
    layout(location = 0) in vec4 position;
    void main()
    {
        gl_Position = position;
    }
    """, GL_VERTEX_SHADER)

    FRAGMENT_SHADER = shaders.compileShader("""
    #version 330
    out vec4 outputColor;
    void main()
    {
        outputColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
    }
    """, GL_FRAGMENT_SHADER)

    shader = shaders.compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)

    #The draw loop
    while True:
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        glUseProgram(shader)

        indexPositions.bind()

        vertexPositions.bind()
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)

        #glDrawArrays(GL_TRIANGLES, 0, 3) #This line still works
        glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, None) #This line does work too!

        # Show the screen
        pygame.display.flip()

run()