Я пытаюсь создать 2D-игру на Python с Pygame.

Но я понял, что могу использовать 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, 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()

2
Thalrod_ 10 Фев 2021 в 22:59

1 ответ

Лучший ответ

Когда именованный буферный объект привязан к цели 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.

Три возможных комбинации типа индекса и аргумента типа:

  • '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))
2
Rabbid76 10 Фев 2021 в 20:28