Reputation: 21
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
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