TileMaps very slooooow
Hi, im learning opengl, and starting some games in 2D, actually im stuck with tilemaps, im only acheiving 20fps or less with a simple map 60x40 the tiles are 16x16, so this give us a simple 960x640 pixels map.
Im currently using the vertex arrays, so i draw all the tile quads with only one gl call, and im using a tileAtlas.
Also im only drawing the visible tiles on the screen to gain some performance, but im really disappointed with the result.
My code is based on the opengl template wich comes with xcode.
This is the function im using to draw maps, the maps are stored in an array 3d, level[layers][rows][columns]
Then i only need to call this to draw the map on screen
Any ideas?
Regards,
Im currently using the vertex arrays, so i draw all the tile quads with only one gl call, and im using a tileAtlas.
Also im only drawing the visible tiles on the screen to gain some performance, but im really disappointed with the result.
My code is based on the opengl template wich comes with xcode.
This is the function im using to draw maps, the maps are stored in an array 3d, level[layers][rows][columns]
Code:
-(void) DrawLevel:(Texture2D *)Surf_Draw CameraX:(float)CameraX CameraY:(float)CameraY Layer:(int)Layer IndexQuad:(int)indexquad
{
int index = 0;
int x,y;
int xtile, ytile, xpos,ypos;
//add calculations to achieve smooth scroll
xtile = CameraX / TileSize;
ytile = CameraY / TileSize;
xpos = (int)CameraX & TileSize-1;
ypos = (int)CameraY & TileSize-1;
//we only want to render the visible screen plus 1 tile in each direcction
// if map its more bigger than the screen resolution, that extra tile its
//for smooth scroll, so we only scan the screen resolution
for (int i = 0; i < (SCREENY/TileSize)+1; i ++)
{
for (int j = 0; j < (SCREENX/TileSize)+1; j++)
{
//loop through the map
index = level[Layer][i+ytile][j+xtile].Tilenum;
//convert map coords into pixels coords
x=(j*TileSize) - xpos;
y=(i*TileSize) - ypos;
//add only visible tiles to the vertex array
if (level[Layer][i][j].visible == YES)
[Surf_Draw UpdateQuadsAt:CGRectMake(x, y, TileSize, TileSize)
OffsetPoint:CGPointMake((index%columns) *TileSize, (index/columns) * TileSize)
SubTextureWidth:TileSize
SubTextureHeight:TileSize
Flip:1
withIndex:indexquad];
indexquad++;
}
}
}Then i only need to call this to draw the map on screen
Code:
-(void) drawNumberOfQuads: (NSUInteger)n
{
glColor4f(colourFilter[0], colourFilter[1], colourFilter[2], colourFilter[3]);
if(_name != [sharedGameState currentlyBoundTexture]) {
[sharedGameState setCurrentlyBoundTexture:_name];
glBindTexture(GL_TEXTURE_2D, _name);
}
glVertexPointer(2, GL_FLOAT, 0, verticesTileSheet);
glTexCoordPointer(2, GL_FLOAT, 0, texCoordsTileSheet);
glDrawElements(GL_TRIANGLES, n*6, GL_UNSIGNED_SHORT, indicesTileSheet);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}Any ideas?
Regards,
Could you tell what is that Surf_Draw and what exactly you do with:
[Surf_Draw UpdateQuadsAt:CGRectMake(x, y, TileSize, TileSize)
OffsetPoint:CGPointMake((index%columns) *TileSize, (index/columns) * TileSize)
SubTextureWidth:TileSize
SubTextureHeight:TileSize
Flip:1
withIndex:indexquad];
indexquad++;
[Surf_Draw UpdateQuadsAt:CGRectMake(x, y, TileSize, TileSize)
OffsetPoint:CGPointMake((index%columns) *TileSize, (index/columns) * TileSize)
SubTextureWidth:TileSize
SubTextureHeight:TileSize
Flip:1
withIndex:indexquad];
indexquad++;
Of course, Surf_draw its a pointer to a texture2d image, im using texture2d class from apple, and here is the updatequads function
Quad2, is only a simple struct
Regards,
Code:
-(void) UpdateQuadsAt:(CGRect)rect OffsetPoint:(CGPoint)offsetPoint SubTextureWidth:(GLfloat)SubTextureWidth SubTextureHeight:(GLfloat)SubTextureHeight Flip:(int)flip withIndex:(int)idx
{
Quad2 texCoord;
Quad2 vertex;
//calculate the quad dimensions
GLfloat texWidthRatio = 1.0f / (float)_width ;
GLfloat texHeightRatio = 1.0f / (float)_height;
GLfloat cx = texWidthRatio * offsetPoint.x; // X Position of sprite
GLfloat cy = texHeightRatio * offsetPoint.y; // Y Position of sprite
// top left
//top right
//bottom left
//bottom right
texCoord.tl_x = cx;
texCoord.tl_y = cy;
texCoord.tr_x = (texWidthRatio * SubTextureWidth) + cx;
texCoord.tr_y = cy;
texCoord.bl_x = cx;
texCoord.bl_y = (texHeightRatio * SubTextureHeight) + cy;
texCoord.br_x = (texWidthRatio * SubTextureWidth) + cx;
texCoord.br_y = (texHeightRatio * SubTextureHeight) + cy;
if (flip == 1)
{
vertex.tl_x = rect.origin.x;
vertex.tl_y = rect.origin.y;
vertex.tr_x = rect.origin.x + rect.size.width;
vertex.tr_y = rect.origin.y;
vertex.bl_x = rect.origin.x;
vertex.bl_y = rect.origin.y + rect.size.height;
vertex.br_x = rect.origin.x + rect.size.width;
vertex.br_y = rect.origin.y + rect.size.height;
}else{
vertex.tl_x = rect.origin.x + rect.size.width;
vertex.tl_y = rect.origin.y;
vertex.tr_x = rect.origin.x;
vertex.tr_y = rect.origin.y;
vertex.bl_x = rect.origin.x + rect.size.width;
vertex.bl_y = rect.origin.y + rect.size.height;
vertex.br_x = rect.origin.x;
vertex.br_y = rect.origin.y + rect.size.height;
}
[self updateQuadWithTexture:&texCoord vertexQuad:&vertex atIndex:idx];
}Quad2, is only a simple struct
Code:
typedef struct _Quad2 {
float tl_x, tl_y;
float tr_x, tr_y;
float bl_x, bl_y;
float br_x, br_y;
} Quad2;Regards,
I forgot post the updatequadwithtexture function
I dont know why a simple map is rendered too slow
Code:
-(void) updateQuadWithTexture: (Quad2*)quadT vertexQuad:(Quad2*)quadV atIndex:(NSUInteger)n
{
texCoordsTileSheet[n] = *quadT;
verticesTileSheet[n] = *quadV;
}I dont know why a simple map is rendered too slow
So you reconstruct texture and vertices arrays every frame including only visible quads.
I can not see any reason why it should slow down to 20 fps.
Make sure thumb option for compilation is disabled.
Anyway, there is no need to reconstruct whole array every frame. I believe you could construct array only once and then draw only visible part of them in few draw calls by setting up vertex offset argument in glDrawArray and even without indices.
I can not see any reason why it should slow down to 20 fps.
Make sure thumb option for compilation is disabled.
Anyway, there is no need to reconstruct whole array every frame. I believe you could construct array only once and then draw only visible part of them in few draw calls by setting up vertex offset argument in glDrawArray and even without indices.
Have you used either Instruments or Shark to determine where the CPU time is being spent?
If the answer is No, then you're just trying random shots in the dark, and you really should reconsider.
If the answer is No, then you're just trying random shots in the dark, and you really should reconsider.
Yes I try instruments to see, and the drawquads function actually are using a 90%, the renderscene is wasting around 7%. The thumb support is also disabled.
Even updating the texture and vertex array in every frame, it shouldnt be too slow
Even updating the texture and vertex array in every frame, it shouldnt be too slow
Try increasing the tile size -- something like 128x128 or even larger will work much better from my experience. Let me know if that helps
Deactivating glblend and reducing the total number of tiles was the key to solve this problem
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Question about tmx files (tilemaps) and resolution for Iphone 3gs, Ipad, and Retina | appsolutecreations | 10 | 13,326 |
May 19, 2012 10:02 AM Last Post: tapouillo |
|

