如何在PyOpenGL中使用顶点数组对象和glDrawElements进行绘制
我有以下代码,应该在屏幕上简单地绘制一个绿色三角形。它使用顶点数组对象和索引缓冲区进行绘制,并且具有我可以制作的最简单的着色器。
最初,我没有使用索引缓冲区,只是简单地进行了绘画调用,glDrawArrays
但工作正常,但是当我将其更改为使用时,glDrawElements
则屏幕上没有任何内容绘制出来(它完全是黑色的)。
from OpenGL.GL import shadersfrom 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)
#Create the Vertex Array Object
vertexArrayObject = GLuint(0)
glGenVertexArrays(1, vertexArrayObject)
glBindVertexArray(vertexArrayObject)
#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='uint16')
indexPositions = vbo.VBO(indices, target=GL_ELEMENT_ARRAY_BUFFER)
indexPositions.bind()
vertexPositions.bind()
glEnableVertexAttribArray(0) # from 'location = 0' in shader
glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)
glBindVertexArray(0)
vertexPositions.unbind()
indexPositions.unbind()
#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:
glUseProgram(shader)
glBindVertexArray(vertexArrayObject)
#glDrawArrays(GL_TRIANGLES, 0, 3) #This line works
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0) #This line does not
glBindVertexArray(0)
glUseProgram(0)
# Show the screen
pygame.display.flip()
run()
如果我只是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
但仍然没有。
回答:
谢谢@NicolBolas。他激励我真正采用此代码并使之生效。而不是理论化:)我删除了vertexArrayObject(它是多余的,因为我们已经有用于顶点和索引的VBO)。因此,您只需在调用glDraw
*之前绑定索引和顶点缓冲区(以及属性)即可。当然,将None
(空指针)传递给glDrawElements
索引而不是0
!非常重要。
from OpenGL.GL import shadersfrom 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()
以上是 如何在PyOpenGL中使用顶点数组对象和glDrawElements进行绘制 的全部内容, 来源链接: utcz.com/qa/400733.html