如何解决尝试使用 PyOpengl 的索引和顶点绘制简单的正方形
我正在尝试使用 Pygame 创建一个 2D Python 游戏。
但我意识到我可以使用 PyOpengl,所以我尝试学习如何使用它。我可以在我的屏幕上用顶点创建一个三角形条。但是,我想使用索引来渲染这些三角形。在下面的代码中,我尝试渲染一个简单的正方形,它有 2 个三角形,一个列表中有 4 个顶点,另一个列表中有索引。不幸的是,我不明白为什么广场没有出现。我可能误解了缓冲区、vaos、vbos 甚至 pyopengl 本身的处理。 (我用注释来解释我认为代码行的作用)
import numpy as np
import pygame
from OpenGL.GL import *
vaos = []
vbos = []
pygame.init()
screen = pygame.display.set_mode((512,512),pygame.OPENGL | pygame.DOUBLEBUF)
pygame.display.set_caption("With OpenGl")
glViewport(0,512,512)
# Creating vertices and indices
vertices = [-0.5,0.5,-0.5,0.5]
indices = [0,1,3,2]
# Creating VAO and binding it
vaoID = glGenVertexArrays(1)
vaos.append(vaoID)
glBindVertexArray(vaoID)
# Creating VBO for verticices and binding it
verticesID = glGenBuffers(1)
vbos.append(verticesID)
glBindBuffer(GL_ARRAY_BUFFER,verticesID)
# Creating bufferData to store vertices position
verticesBuffer = np.array(vertices,dtype='f')
glBufferData(GL_ARRAY_BUFFER,verticesBuffer,GL_STATIC_DRAW)
glVertexAttribPointer(0,2,GL_FLOAT,False,None)
glBindBuffer(GL_ARRAY_BUFFER,0)
# Creating VBO for indices and binding it
indicesID = glGenBuffers(1)
vbos.append(indicesID)
# Creating bufferData to store indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indicesID)
indicesBuffer = np.array(indices,dtype='uint16')
glBufferData(GL_ELEMENT_ARRAY_BUFFER,indicesBuffer,GL_STATIC_DRAW)
# unbind VAO because I finished to use it
glBindVertexArray(0)
run = True
clock = pygame.time.Clock()
while run:
clock.tick(60)
for e in pygame.event.get():
if e.type == pygame.QUIT:
run = False
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_o:
run = False
# Preparing screen
glClear(GL_COLOR_BUFFER_BIT)
glClearColor(1,1)
# Rendering
# binding VAO
glBindVertexArray(vaoID)
# enabling VertexAttribArray to get vertices
glEnabLevertexAttribArray(0)
# draw elements
glDrawElements(GL_TRIANGLES,len(vertices) * 4,GL_UNSIGNED_INT,0)
# disabling VertexAttribArray and unbind VAO because I finished to use them
gldisabLevertexAttribArray(0)
glBindVertexArray(0)
pygame.display.flip()
# Cleanup
for vao in vaos:
glDeleteVertexArrays(1,vao)
for vbo in vbos:
glDeleteBuffers(1,vbo)
pygame.quit()
解决方法
当命名缓冲区对象绑定到 GL_ELEMENT_ARRAY_BUFFER
目标时,glDrawElements
的最后一个参数被视为缓冲区对象数据存储中的字节偏移量。但是,参数的类型无论如何都必须是指针(ctypes.c_void_p
)。
因此,如果偏移量为 0,则最后一个参数可以是 None
或 ctypes.c_void_p(0)
,否则必须将偏移量强制转换为 ctypes.c_void_p
。
此外,类型参数必须与缓冲区中索引的类型相匹配。由于索引的类型是 'uint16'
,因此类型参数必须是 GL_UNSIGNED_SHORT
而不是 GL_UNSIGNED_INT
。
索引类型和类型参数的 3 种可能组合是:
- 'uint8' -
GL_UNSIGNED_BYTE
- 'uint16' -
GL_UNSIGNED_SHORT
- 'uint32' -
GL_UNSIGNED_INT
正确的代码是
glDrawElements(GL_TRIANGLES,len(vertices) * 4,GL_UNSIGNED_INT,0)
glDrawElements(GL_TRIANGLES,GL_UNSIGNED_SHORT,None)
或
glDrawElements(GL_TRIANGLES,ctypes.c_void_p(0))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。