redpenguiney2
redpenguiney2

Reputation: 21

PyOpenGL code with vbos for rendering tile-based game creating blank screen

I have been, with pygame and pyopengl (oh and obviously Python), been trying to make a little tile-based 2D game, but I'm having trouble with the rendering using VBOs and glMultiDrawArray().

The program runs without errors, but I don't see any geometry drawn, so it's just a blank screen.

I've tried using glTranslate to see if maybe the geometry is being drawn, but I can't see it, as well as changing between using GluPerspective() and glOrthro2D(). No luck. I've pored over the code to see where it isn't working, but I have no clue what could be wrong. I'm still struggling to understand OpenGL and VBOs.

Here are the relevant bits of my code:

The Chunk class. Every chunk has its own VBO for vertices and textures (textures are currently unused)

class Chunk():

def __init__(self, position):
    self.Position = position

    self.VertexVBOId = _get_chunk_id()
    self.VertexVBO = glGenBuffers(self.VertexVBOId)
    self.TextureVBOId = _get_chunk_id()
    self.TextureVBO = glGenBuffers(self.TextureVBOId)
    
    Chunks[str(position)] = self

    self.__updateVertexArray()
   # glBindBuffer (GL_ARRAY_BUFFER, self.VertexVBO)
    #self.__updateVertexArray()


def __getvertices(self):
    vertices = []

    for x in range(self.Position.x, self.Position.x + 16):
        for y in range(self.Position.y, self.Position.y + 16):
            pos = Vector2(x, y)
            tile = GetTile(pos)
            if tile != "air":
                vertices.append(x+1)
                vertices.append(y)

                vertices.append(x+1)
                vertices.append(y+1)

                vertices.append(x)
                vertices.append(y+1)

                vertices.append(x)
                vertices.append(y)

    return vertices

def __updateVertexArray(self): #This will be called when a change is made the the chunk, as well as once initially
    print("UPDATING VERTEX ARRAY")
    vertices = self.__getvertices()
    glBindBuffer (GL_ARRAY_BUFFER, self.VertexVBOId)
    glBufferData (GL_ARRAY_BUFFER, len(vertices)*4, (c_float*len(vertices))(*vertices), GL_DYNAMIC_DRAW)

And here is the rendering loop:

def main():
    print("Started")
    pygame.init()
    global displaySize
    global SCREENSIZE
    global PIXELS_PER_TILE

    pygame.display.set_mode(displaySize, DOUBLEBUF|OPENGL)
    #gluOrtho2D(-SCREENSIZE[0]/2, SCREENSIZE[0]/2, -SCREENSIZE[1]/2, SCREENSIZE[1]/2)
    gluPerspective(180, 2, 0.1, 100)

    ... some other stuff ...

    while True:
        #Drawing 
        glClearColor(0.7, 0.7, 1, 0)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

       cameraTranslateX = (camera.Position.x % 1) * PIXELS_PER_TILE
        cameraTranslateY = (camera.Position.y % 1) * PIXELS_PER_TILE

        #Figure out which chunks to render
        botLeft = camera.Position - Vector2(SCREENSIZE[0]/2, SCREENSIZE[1]/2) + Vector2(cameraTranslateX, cameraTranslateY)
        topRight = camera.Position + Vector2(SCREENSIZE[0]/2, SCREENSIZE[1]/2) + Vector2(cameraTranslateX, cameraTranslateY)

        FirstChunkPos = (botLeft/16).floor()

        TotalChunksX = (topRight/16).ceil().x - FirstChunkPos.x
        TotalChunksY = (topRight/16).ceil().y - FirstChunkPos.y

        for x in range(TotalChunksX):
            for y in range(TotalChunksY):
                pos = Vector2(x + FirstChunkPos.x, y + FirstChunkPos.y)
                chunk = Chunks.get(str(pos))
                if not chunk:
                    chunk = Chunk(pos)

                VertexVBO = chunk.VertexVBOId

                glBindBuffer (GL_ARRAY_BUFFER, VertexVBO)
                glVertexPointer (2, GL_FLOAT, 0, None)

                TextureVBO = chunk.TextureVBOId

                glMultiDrawArrays (GL_POLYGON, vertexArrayThingy1, vertexArrayThingy2, 255)

               # glUnmapBuffer(GL_ARRAY_BUFFER,VertexVBO)

        pygame.display.flip ()

Upvotes: 1

Views: 87

Answers (1)

Rabbid76
Rabbid76

Reputation: 210909

The 2nd and 3rd arguments of glMultiDrawArrays are of type const GLint* and const GLsizei*. This function cannot draw from different buffers. There is no glDraw* command that can use multiple vertex buffers for drawing. All vertecx attributes must be in one and the same buffer. glMultiDrawArrays should draw different ranges from the buffer. Suppose you want to draw the following 3 attribute ranges [3:6], [18:27], [30:36]:

first = [3, 18, 30]
count = [3, 9, 6]
glMultiDrawArrays(GL_TRIANGLES, first, count, 3)

If you want to draw multiple lists of indices you have to use glMultiDrawElements and you have to create an array of pointers to arrays of indices:

import ctypes
ia1 = (GLuint * 6)(0, 1, 2, 0, 2, 3)
ia2 = (GLuint * 6)(12, 13, 14, 12, 14, 15)
counts = [6, 6]
indexPtr = (GLvoidp * 2)(ctypes.addressof(ia1), ctypes.addressof(ia2))
glMultiDrawElements(GL_TRIANGLES, counts, GL_UNSIGNED_INT, indexPtr, 2)

Upvotes: 1

Related Questions