简体   繁体   中英

Python, OpenGL: how to store vertex data on GPU

I need to display large amount of quads in 2D, what is the best way to make it with Python and OpenGL? The goal is not to send all the data to GPU when paintGL is called, cause it takes a lot of time... I guess that there has to be a possibility to store vertex data on GPU, how to make it in Python? Here is the working example of my problem:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from OpenGL.GL import *
from PyQt4 import QtGui, QtCore, QtOpenGL

def get_squares(squareCount, edgeSize):

    """
    Returns vertex list for a matrix of squares

    squareCount - number of squares on one edge
    edgeSize - size of the matrix edge
    """

    edgeLength = edgeSize/squareCount/2
    vertexList = []
    x = edgeLength/2
    y = edgeLength/2
    z = 0
    for i in range(squareCount):
        for j in range(squareCount):
            vertexList.append([x,y,z])
            y += edgeLength
            vertexList.append([x,y,z])
            x += edgeLength
            vertexList.append([x,y,z])
            y -= edgeLength
            vertexList.append([x,y,z])
            x += edgeLength
        x = edgeLength/2
        y += 2*edgeLength
    return vertexList


class OpenGLWidget(QtOpenGL.QGLWidget):
    def __init__(self, squareCount = 20, parent = None):
        QtOpenGL.QGLWidget.__init__(self, parent)
        self.squares = get_squares(squareCount, 50)

    def paintGL(self):
        glBegin(GL_QUADS)
        for point in self.squares:
            glVertex3f(*point)
        glEnd()

    def resizeGL(self, w, h):
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(0, 50, 0, 50, 0, 1)
        glViewport(0, 0, w, h)

    def initializeGL(self):
        glClearColor(0.0, 0.0, 0.0, 1.0)
        glClear(GL_COLOR_BUFFER_BIT)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication([])
    w = OpenGLWidget(squareCount = 20) # try increasing that number and resizing the window...
                                       # for me at squareCount = 200 (40000 squares) it's really slow
    w.show()
    sys.exit(app.exec_())

I use Python-OpenGL and numpy to do this. Sample code:

import numpy

Verts = numpy.array([
    ( -0.5,  0.5, -0.5 ),   # left top rear
    (  0.5,  0.5, -0.5 ),   # right top rear
    (  0.5, -0.5, -0.5 ),   # right bottom rear
    ( -0.5, -0.5, -0.5 ),   # left bottom rear
    ( -0.5,  0.5,  0.5 ),   # left top front
    (  0.5,  0.5,  0.5 ),   # right top front
    (  0.5, -0.5,  0.5 ),   # right bottom front
    ( -0.5, -0.5,  0.5 ),   # left bottom front
], dtype=numpy.float32)

Faces = numpy.array([
    7, 6, 5, 4,     # front
    6, 2, 1, 5,     # right
    3, 7, 4, 0,     # left
    5, 1, 0, 4,     # top
    3, 2, 6, 7,     # bottom
    2, 3, 0, 1,     # rear
], dtype=numpy.int16)

class Cube (object):
    "Wireframe cube implemented with VBOs"

    def __init__ (self, color = (0.0, 1.0, 0.0, 1.0)):
        self.vert = glGenBuffers(1)
        self.rgba = glGenBuffers(1)
        self.idx  = glGenBuffers(1)

        glBindBuffer(GL_ARRAY_BUFFER, self.vert)
        glBufferData(GL_ARRAY_BUFFER, Verts, GL_STATIC_DRAW)
        colorTable = numpy.array([color for n in range(0, len(Verts))], dtype=numpy.float32)
        glBindBuffer(GL_ARRAY_BUFFER, self.rgba)
        glBufferData(GL_ARRAY_BUFFER, colorTable, GL_STATIC_DRAW)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.idx)
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, Faces, GL_STATIC_DRAW)

    def draw (self):
        glBindBuffer(GL_ARRAY_BUFFER, self.vert)
        glVertexPointer(3, GL_FLOAT, 0, None)
        glBindBuffer(GL_ARRAY_BUFFER, self.rgba)
        glColorPointer(4, GL_FLOAT, 0, None)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.idx)
        glDrawElements(GL_QUADS, len(Faces), GL_UNSIGNED_SHORT, None)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM