【问题标题】:Trying to draw simple square using indices and vertices with PyOpengl尝试使用 PyOpengl 的索引和顶点绘制简单的正方形
【发布时间】:2021-02-10 19:59:15
【问题描述】:

我正在尝试使用 Pygame 创建一个 2D python 游戏。

但我意识到我可以使用 PyOpengl,所以我尝试学习如何使用它。我可以在我的屏幕上用顶点创建一个三角形条带。但是,我想使用索引来渲染这些三角形。在下面的代码中,我尝试渲染一个简单的正方形,其中包含 2 个三角形、一个列表中的 4 个顶点和另一个列表中的索引。不幸的是,我不明白为什么没有出现正方形。我可能对缓冲区、vaos、vbos 甚至 pyopengl 本身的处理有误解。 (我用 cmets 来解释我认为代码行的作用)

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, 0, 512, 512)

# Creating vertices and indices
vertices = [-0.5, 0.5,
            -0.5, -0.5,
            0.5, -0.5,
            0.5, 0.5]

indices = [0, 1, 3,
           3, 1, 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, 0, 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, 0, 0, 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()

【问题讨论】:

    标签: python opengl pygame pyopengl


    【解决方案1】:

    当命名缓冲区对象绑定到GL_ELEMENT_ARRAY_BUFFER 目标时,glDrawElements 的最后一个参数被视为缓冲区对象数据存储中的字节偏移量。但是,参数的类型无论如何都必须是指针(ctypes.c_void_p)。

    因此,如果偏移量为 0,那么最后一个参数可以是 Nonectypes.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, len(vertices) * 4, GL_UNSIGNED_SHORT, None)
    

    glDrawElements(GL_TRIANGLES, len(vertices) * 4, GL_UNSIGNED_SHORT, ctypes.c_void_p(0))
    

    【讨论】:

    • 我查看了我的代码,发现我将索引类型放入 "uint16" 而不是 "uint32"。我还修改了glDrawElements,它适用于Nonectypes.c_void_p(0)
    • @Thalrod_ GL_UNSIGNED_SHORT 而不是 GL_UNSIGNED_SHORT。我已经扩展了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    • 2017-02-03
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 2012-12-31
    相关资源
    最近更新 更多