Sign in to follow this  
d h k

SDL too slow for a high-res RTS game? [SOLVED]

Recommended Posts

Hello, I know, I know... YET another thread about SDL and its performance by me. I apologize for that. Anyways, maybe you remember me posting about speed-issues before, but now it's got me again. This is the situation: I want to draw isometric tiles sized 128x64 for a 1280x1024 game. This means (I checked via debug-features in my project) around 400 tiles on the screen at a time out of 1200 for example for a 50x30 sized map (in tiles). This already slows my SDL application down to 20 to 25 frames. My computer is four years old, but shouldn't it be able to run faster? Here is some code from the tile drawing for you to check for any errors: Note that my tiles do not use an alpha-channel, in that case, I'd know why it's slow... sprite.cpp
void csprite::init ( const char *filename, bool alpha_channel )
// initializes the sprite
{
	if ( alpha_channel )
	// if the image has an alpha-channel
		// load the bitmap
		bitmap = IMG_Load ( filename );

	else
	// if the image does not have an alpha-channel
	{
		SDL_Surface* temp;

		// load temp
		temp = SDL_LoadBMP ( filename );

		if ( temp == NULL )
		// if there was an error
			return_error ( "Failed to initialize sprite..." );

		// load the bitmap
		bitmap = SDL_DisplayFormat ( temp );

		// free temp	
		SDL_FreeSurface ( temp );

		// activate color keying
		if ( SDL_SetColorKey ( bitmap, SDL_SRCCOLORKEY, SDL_MapRGB ( bitmap->format, 255, 0, 128 ) ) < 0 )
		// if there was an error
			return_error ( "Failed to colorkey sprite..." );
	}

	if ( bitmap == NULL )
	// if there was an error
		return_error ( "Failed to initialize sprite..." );

	// set up other variables
	width = bitmap->w;
	height = bitmap->h;
}

void csprite::init ( const char *filename, bool alpha_channel, int _width, int _height )
// initializes the sprite
{
	// initialize sprite
	init ( filename, alpha_channel );

	// set up other variables
	width = _width;
	height = _height;
}

void csprite::draw ( )
// draws the sprite to the screen
{
	// create a source rectangle
	SDL_Rect source;
	source.x = 0;
	source.y = 0;
	source.w = bitmap->w;
	source.h = bitmap->h;
	
	// create a destination rectangle
	SDL_Rect destination;
	destination.x = ( int ) x;
	destination.y = ( int ) y;
	destination.w = width;
	destination.h = height;

	// blit the bitmap to the screen
	if ( SDL_BlitSurface ( bitmap, &source, SDL_GetVideoSurface ( ), &destination ) < 0 )
	// if there was an error
		return_error ( "Failed to draw sprite..." );
}

void csprite::draw ( float _x, float _y )
// draws the sprite to the screen at a given location
{
	// position the sprite
	x = _x;
	y = _y;
	
	// draw it
	draw ( );
}

void csprite::draw ( int _x, int _y )
// draws the sprite to the screen at a given location
{
	// create a source rectangle
	SDL_Rect source;
	source.x = 0;
	source.y = 0;
	source.w = bitmap->w;
	source.h = bitmap->h;
	
	// create a destination rectangle
	SDL_Rect destination;
	destination.x = _x;
	destination.y = _y;
	destination.w = width;
	destination.h = height;

	// blit the bitmap to the screen
	if ( SDL_BlitSurface ( bitmap, &source, SDL_GetVideoSurface ( ), &destination ) < 0 )
	// if there was an error
		return_error ( "Failed to draw sprite..." );
}

void csprite::draw ( float _x, float _y, int x_frame, int y_frame )
// draws the sprite to the screen at a given location using a frame
{
	// position the sprite
	x = _x;
	y = _y;

	// create a source rectangle
	SDL_Rect source;
	source.x = x_frame * width;
	source.y = y_frame * height;
	source.w = width;
	source.h = height;
	
	// create a destination rectangle
	SDL_Rect destination;
	destination.x = ( int ) x;
	destination.y = ( int ) y;
	destination.w = width;
	destination.h = height;

	// blit the bitmap to the screen
	if ( SDL_BlitSurface ( bitmap, &source, SDL_GetVideoSurface ( ), &destination ) < 0 )
	// if there was an error
		return_error ( "Failed to draw sprite..." );
}

void csprite::draw_cropped ( int percentage )
// draws the sprite to the screen cropped at a given location
{
	// create a source rectangle
	SDL_Rect source;
	source.x = 0;
	source.y = 0;
	source.w = ( int ) ( ( 1.0 / 100.0 ) * ( float ) percentage * ( float ) width );
	source.h = bitmap->h;
	
	// create a destination rectangle
	SDL_Rect destination;
	destination.x = ( int ) x;
	destination.y = ( int ) y;
	destination.w = ( int ) ( ( 1.0 / 100.0 ) * ( float ) percentage * ( float ) width );
	destination.h = height;
	
	// blit the bitmap to the screen
	if ( SDL_BlitSurface ( bitmap, &source, SDL_GetVideoSurface ( ), &destination ) < 0 )
	// if there was an error
		return_error ( "Failed to draw sprite..." );
}

void csprite::destroy ( void )
// destroys all used memory of a sprite and frees it
{
	// free the surface
	SDL_FreeSurface ( bitmap );
}




tile.cpp
int tile_offset_x, tile_offset_y;

int tiles_drawn;

ctile tile[TILES_X][TILES_Y];

csprite tileset;

extern screen_width, screen_height;

void ctile::init ( int _x, int _y, tile_type _type )
// initializes the tile
{
	if ( _type == dirt )
	{
		// assign vertical frame
		y_frame = 0;

		// randomize horizontal frame
		x_frame = rand ( ) % 3;
	}

	else if ( _type == grass )
	{
		// assign vertical frame
		y_frame = 1;

		// randomize horizontal frame
		x_frame = rand ( ) % 3;
	}
	/*else
	{
		// assign vertical frame
		y_frame = 2;

		if ( _type == tra_grass_dirt_t )
			x_frame = 0;
		else if ( _type == tra_grass_dirt_tr )
			x_frame = 1;
		else if ( _type == tra_grass_dirt_r )
			x_frame = 2;
		else if ( _type == tra_grass_dirt_br )
			x_frame = 3;
		else if ( _type == tra_grass_dirt_b )
			x_frame = 4;
		else if ( _type == tra_grass_dirt_bl )
			x_frame = 5;
		else if ( _type == tra_grass_dirt_l )
			x_frame = 6;
		else if ( _type == tra_grass_dirt_tl )
			x_frame = 7;
	}*/

	// save position
	x = _x;
	y = _y;

	// save type
	type = _type;
}

void ctile::draw ( void )
// draws the tile
{
	// draw the sprite
	tileset.draw ( ( float ) x, ( float ) y, x_frame, y_frame );
}

void init_tiles ( int start_position_x, int start_position_y )
// inits the tiles
{
	int	row_index = 0;

	tiles_drawn = 0;

	// init tileset
	tileset.init ( "tilesets/jungle.bmp", false, TILE_WIDTH, TILE_HEIGHT );

	for ( int y = 0; y < TILES_Y; y++ )
	// loop through all tiles vertically
	{
		for ( int x = 0; x < ( TILES_X / 2 ); x++ )
		// loop through all tiles horizontally
		{
			if ( row_index == 0 )
				// init tile
				tile[x * 2][y].init ( ( x * TILE_WIDTH ) - start_position_x, ( y * ( ( TILE_HEIGHT + 1 ) / 2 ) ) - start_position_y, grass );

			else if ( row_index == 1 )
				// init tile
				tile[( x * 2 ) + 1][y].init ( ( x * TILE_WIDTH ) + ( TILE_WIDTH / 2 ) - start_position_x, ( ( y - 1 ) * ( ( TILE_HEIGHT + 1 ) / 2 ) ) + ( ( TILE_HEIGHT + 1 ) / 2 ) - start_position_y, grass );
		}

		// alternate index
		if ( row_index == 0 )
			row_index = 1;
		else
			row_index = 0;
	}
}

void draw_tiles ( void )
// draws the tiles
{
	tiles_drawn = 0;

	for ( int y = 0; y < TILES_Y; y++ )
	// loop through all tiles vertically
	{
		for ( int x = 0; x < TILES_X; x++ )
		// loop through all tiles horizontally
		{
			if ( tile_offset_x > 0 )
			// left scrolling
			{
				if ( tile[0][0].x >= -( TILE_WIDTH / 2 ) )
					tile_offset_x = 0;
			}

			else if ( tile_offset_x < 0 )
			// right scrolling
			{
				if ( tile[0][0].x <= -( ( TILES_X / 2 ) * TILE_WIDTH ) - 2 + screen_width )
					tile_offset_x = 0;
			}

			if ( tile_offset_y > 0 )
			// up scrolling
			{
				if ( tile[0][0].y >= -( ( TILE_HEIGHT + 1 ) / 2 ) )
					tile_offset_y = 0;
			}

			else if ( tile_offset_y < 0 )
			// down scrolling
			{
				if ( tile[0][0].y <= -( ( TILES_Y / 2 ) * ( TILE_HEIGHT + 1 ) ) - 2 + screen_height )
					tile_offset_y = 0;
			}

			// update position
			tile[x][y].x += tile_offset_x;
			tile[x][y].y += tile_offset_y;

			if ( tile[x][y].x >= -TILE_WIDTH && tile[x][y].x <= screen_width )
			// if tile is horizontally in view
			{
				if ( tile[x][y].y >= -TILE_HEIGHT && tile[x][y].y <= screen_height )
				// if tile is vertically in view
				{
					// draw tile
					tile[x][y].draw ( );

					tiles_drawn++;
				}
			}
		}
	}
}

void destroy_tiles ( void )
// destroy the tiles
{
	// destroy tileset
	tileset.destroy ( );
}




So, my question: is there any error in there from my side or is SDL just not fast enough for 1280x1024-sized games with tiles? Thanks ahead of time. [Edited by - d h k on May 24, 2007 7:02:50 AM]

Share this post


Link to post
Share on other sites
Hidden
Quote:
So, my question: is there any error in there from my side or is SDL just not fast enough for 1280x1024-sized games with tiles?

The answer: No, SDL isn't fast enough - or rather - a graphic card isn't able to handle it in software mode. Why? Let's examine this a little bit.... a 1280x1024 24-bit screen translates to about 3,75 mb of raw data. Take a screenshot in Windows and save it as a .BMP and you'll see! If you are drawing the entire screen in each update, and you have an FPS of 60, this translates to 60 * 3,75 mb = 225 mb of data per second, which is sent to the graphics card. In software mode!

The solution: SDL uses the Windows display, if you're on Windows, so changing to 256 colours or even less doesn't really do much. And it's not a very elegant solution either. Luckily, you can use OpenGL with SDL, and you can actually use OpenGL to draw 2D graphics not much harder than what you do with SDL. You can still use SDL for keyboard and mouse input, timers, etc etc. Give it a try! If you want me to give some basic code for this, let me know and I'll paste it here. It works like a charm, and it's much, much, MUCH faster than letting SDL do the blitting. Plus you can use all the other fancy effects OpenGL provide, like lightning, rotation, scaling, etc etc.

Share this post


Link to post
Okay, then I'll try to work with OpenGL (which I luckily know pretty good). Or would it make sense to switch to hardware-mode and stay with SDL (because I'd really like to stay with it)?

EDIT: Some example code would be well appreciated! :)

Share this post


Link to post
Share on other sites
Hidden
You can give it a try, but I think you'll find that it won't do much difference.

In your SDL_SetVideoMode(), change SDL_SWSURFACE to SDL_HWSURFACE but personally I have never seen any difference between these two modes.

Share this post


Link to post
Yeah, tried that, but didn't seem to change anything.

Okay, so I guess I'll be using OpenGL with SDL from now on.

Share this post


Link to post
Share on other sites
Hidden
Quote:
EDIT: Some example code would be well appreciated! :)

Hehe, allright! Many posts today. :)


#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 768
#define NUM_TILES 16
#define TILE_SIZE 32 /* use 32x32 tiles */

/* remember some stuff when we upload textures */
struct BitmapStruct {
GLuint texture_number;
GLfloat texcoord[4];
};

struct BitmapStruct GFX_Tiles[NUM_TILES];

SDL_Surface *MainScreen;
Uint32 bpp, rmask, gmask, bmask, amask;

void InitScreen() {
if (SDL_Init(SDL_INIT_VIDEO) < 0)
exit(1);

putenv("SDL_VIDEO_CENTERED=center");

MainScreen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 0, SDL_OPENGL);

bpp = MainScreen->format->BitsPerPixel;
rmask = MainScreen->format->Rmask;
gmask = MainScreen->format->Gmask;
bmask = MainScreen->format->Bmask;
amask = MainScreen->format->Amask;

atexit(SDL_Quit);

glEnable(GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glDisable(GL_DEPTH_TEST);

glAlphaFunc(GL_GREATER, 0);
glClearColor(0.0, 0.0, 0.0, 1.0f);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, 0.0, 1.0);

glMatrixMode(GL_MODELVIEW);
}

/* here you can load all the graphics for your game */
void LoadGraphicFiles() {
LoadBitmapToStruct("gfx/tiles.bmp", GFX_Tiles, TILE_SIZE, TILE_SIZE, NUM_TILES);
}

/* this loads a bitmap file (*.bmp) and uploads it to textures */
void LoadBitmapToStruct(char *src_file, struct BitmapStruct *array, int width, int height, int frames) {
SDL_Surface *image, *temp;
int i, x = 0, y = 0, w, h;
SDL_Rect area;
GLuint texture;

image = SDL_LoadBMP(src_file);
if (!image)
exit(1);
SDL_SetColorKey(image, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(image->format, 255, 0, 255));
w = power_of_two(width);
h = power_of_two(height);

for (i = 0; i < frames; i++) {
array[i].texcoord[0] = 0.0f;
array[i].texcoord[1] = 0.0f;
array[i].texcoord[2] = (GLfloat)width / w;
array[i].texcoord[3] = (GLfloat)height / h;

/* blit from bitmap to temporary surface */
temp = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
area.x = x * width;
area.y = y * height;
area.w = width;
area.h = height;
SDL_BlitSurface(image, &area, temp, NULL);

/* create GL texture */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels);

array[i].texture_number = texture;

SDL_FreeSurface(temp);

if ((x * width) + width < image->w)
x++;
else {
y++;
x = 0;
}
}

SDL_FreeSurface(image);
}

static int power_of_two(int input) {
int value = 1;

while (value < input)
value <<= 1;

return value;
}

/* this replaced the SDL_BlitSurface() function */
void GLBlit(struct BitmapStruct *array, int x, int y, int w, int h) {
GLfloat texMinX, texMinY;
GLfloat texMaxX, texMaxY;

/* easier to understand the coordinates for the texture */
texMinX = array->texcoord[0];
texMinY = array->texcoord[1];
texMaxX = array->texcoord[2];
texMaxY = array->texcoord[3];

glBindTexture(GL_TEXTURE_2D, array->texture_number);

/* draw polygon */
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(texMinX, texMinY); glVertex2i(x, y);
glTexCoord2f(texMaxX, texMinY); glVertex2i(x + w, y);
glTexCoord2f(texMinX, texMaxY); glVertex2i(x, y + h);
glTexCoord2f(texMaxX, texMaxY); glVertex2i(x + w, y + h);
glEnd();
}

/* easier call to GLBlit() */
void BlitTile(int tile, int x, int y) {
GLBlit(&GFX_Tiles[tile], x, y, TILE_SIZE, TILE_SIZE);
}



Assuming all tiles are 32x32, you can now draw tiles by just doing:

BlitTile(number_for_the_file, xpos, ypos);

I hope this works. :)

Share this post


Link to post
SDL in hardware mode may be usable (AFAIK hardware is only supported in fullscreen) but it will come down to the fill rate of your video card which can vary greatly between cards.

One thing I can see that might speed things up (admitedly probably not much if at all) is calculating the source rectangle for a sprite once during initialization instead of each time you draw a sprite (potentially quite a few times per frame).

That being said, OpenGL is definitely the way to go with something of this size (meaning 1280x1024). You will also find that OpenGL will give you some more options with alpha blending, scaling, rotation and even primitives like lines and circles since they can all be done in hardware.

Share this post


Link to post
Share on other sites
Well, I already switched to OpenGL now, no turning back... :)

One problem with your code though:

In LoadBitmapToStruct ( )

/* blit from bitmap to temporary surface */
temp = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, window.bpp, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
area.x = x * width;
area.y = y * height;
area.w = width;
area.h = height;
SDL_BlitSurface(image, &area, temp, NULL);

/* create GL texture */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels); // <- CRASH!*!*!**!*!*!*!*!

array[i].texture_number = texture;

SDL_FreeSurface(temp);





The marked line makes my application quit instantly with no errors from SDL or anything. Just quits. What could be the problem? The rest works fine. If I comment that line out, I can see OpenGL drawing the tiles, just they are white because of the missing texture. Any help?

Thanks for the help so far.

Share this post


Link to post
Share on other sites
Sounds like temp->pixels isn't pointing to anything - check it against NULL. While you're there, check the error code returned by SDL_BlitSurface - if it's -1, then the blit failed. Also you could check temp itself against NULL after creating it, as SDL_CreateRGBSurface returns NULL on failure.

Then at least you'll know where the problem is.

Share this post


Link to post
Share on other sites
Okay, thanks, I did that.

Turns out, temp does not point to NULL anywhere, but in fact this returns an error:


if ( temp == NULL )
return_error ( "Failed to create surface..." );
area.x = x * width;
area.y = y * height;
area.w = width;
area.h = height;

if ( !SDL_BlitSurface(image, &area, temp, NULL))
return_error ( "Failed to create texture..." ); // this returns an error

/* create GL texture */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);





What is wrong with SDL_BlitSurface(image, &area, temp, NULL) though? Seems right to me.

EDIT: Sorry, that got me again. The test is wrong, BlitSurface returns 0 on SUCCESS and -1 on FAILURE. I changed that and now no errors are returned, yet still the game quits when calling that line marked above with glTexImage2d.

Share this post


Link to post
Share on other sites
Here's my code to convert a SDL_Texture to an OpenGL texture


//
// Convertit une SDL_Surface en texture OpenGL
//
bool cTexture::SurfaceToTexture(SDL_Surface *surface)
{
if (!surface) return false;

// On verifie que la texture a la bonne taille
if (surface->w != PowerOfTwo(surface->w))
{
cerr << "Texture \"" << FileName << "\" width is invalid. Width = " << surface->w
<< " should be " << PowerOfTwo(surface->w) << endl;
return false;
}
if (surface->h != PowerOfTwo(surface->h))
{
cerr << "Texture \"" << FileName << "\" height is invalid. Height = " << surface->h
<< " should be " << PowerOfTwo(surface->h) << endl;

return false;
}


Clear();

// Use the surface width and height expanded to powers of 2
Width = surface->w;
Height = surface->h;

SDL_LockSurface(surface);


// Create an OpenGL texture for the image
glGenTextures(1, &Handle);
glBindTexture(GL_TEXTURE_2D, Handle);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

/*
// Lissage de la texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
*/

glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
Width, Height,
0,
surface->format->BytesPerPixel == 3 ? GL_RGB : GL_RGBA,
GL_UNSIGNED_BYTE,
surface->pixels);




SDL_UnlockSurface(surface);

return true;
}


Share this post


Link to post
Share on other sites
Allright, thanks for that. When comparing, both scripts seem to be pretty similar though, so for now I'll be sticking to the old one.

I have found out that it has to do with the tile dimensions. 32x32 works (but is the wrong size), 64x64 won't work, 128x64 neither etc.

What is up with that?

Share this post


Link to post
Share on other sites

You may need to lock the surface in order to directly access pixel data like that.

Check if the surface needs to be locked by SDL_MUSTLOCK(surface), and lock if necessary.


if (SDL_MUSTLOCK(temp))
SDL_LockSurface(temp);

/* use the pixel data */

if (SDL_MUSTLOCK(temp))
SDL_UnlockSurface(temp);


Share this post


Link to post
Share on other sites
Added that, doesn't help.

Let's revise

This function makes the game quit instantly:


/* this loads a bitmap file (*.bmp) and uploads it to textures */
void LoadBitmapToStruct(char *src_file, struct BitmapStruct *array, int width, int height, int frames) {
SDL_Surface *image, *temp;
int i, x = 0, y = 0, w, h;
SDL_Rect area;
GLuint texture;

image = SDL_LoadBMP(src_file);

if ( image == NULL )
return_error ( "Failed to load bitmap..." );

//SDL_SetColorKey(image, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(image->format, 255, 0, 128));
w = power_of_two(width);
h = power_of_two(height);

for (i = 0; i < frames; i++) {
array[i].texcoord[0] = 0.0f;
array[i].texcoord[1] = 0.0f;
array[i].texcoord[2] = (GLfloat)width / w;
array[i].texcoord[3] = (GLfloat)height / h;

/* blit from bitmap to temporary surface */
temp = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, window.bpp, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);

if ( temp == NULL )
return_error ( "Failed to create surface..." );

area.x = x * width;
area.y = y * height;
area.w = width;
area.h = height;

if ( SDL_BlitSurface(image, &area, temp, NULL) == -1)
return_error ( "Failed to create texture..." );

/* create GL texture */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

if ( temp->pixels == NULL )
return_error ( "Failed to create texture..." );

if (SDL_MUSTLOCK(temp))
SDL_LockSurface(temp);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels);

if (SDL_MUSTLOCK(temp))
SDL_UnlockSurface(temp);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

array[i].texture_number = texture;

SDL_FreeSurface(temp);

if ((x * width) + width < image->w)
x++;
else {
y++;
x = 0;
}
}

SDL_FreeSurface(image);
}




The call to glTexImage2d above is the problem, without, everything works (but the textures are missing obviously).

TILE_WIDTH and TILE_HEIGHT are set to 32 and the test.bmp file that is loaded is - for testing purposes - now 32x32 as well. Just quits.

Please anybody?

Share this post


Link to post
Share on other sites
Hidden
Sorry, I wasn't home until now so I haven't been able to reply.

The size of the tiles you use doesn't matter, as power_of_two() fixes this. You can use anything from 1x1 to 1024x1024 if you like.

You say that this crashes your program:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels);

But after this.....

temp = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, window.bpp, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);

....does temp return NULL or is it okay? I think the problem may be with endianess. If it is, it shouldn't really crash... just look screwed up with the colours. But you may try this code and see if it helps:


temp = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);





Hope it helps. If it does not, then I dunno.... we'll have to dig deeper into this. :)

Share this post


Link to post
Ha, that was it. Works fine now. Huge thank you! :)

Very nice. I'll do some speed-test now!

Share this post


Link to post
Share on other sites
Hidden
Good luck!

I use SDL and OpenGL myself, and I think it's the perfect combination. For us 2D game programmers, we get the best of both worlds. :)

Share this post


Link to post
I have experimented with directdraw and opengl myself using isometric maps, and its just really hard to render the maps very quickly, especially if its multi-layered.

If you think about it, your sending way more pixels then just the screen resolution since the tiles are stacked and theres much overdraw. That can exponentially get worse as you add layers for ground, roads, buildings.

The way most older isometric engines get away with this by creating a dirty system where only the changing areas of the screen get rendered and keeping the layers down to 2-3.

This is a similar problem that 3d programmers face, when you draw over other objects you waste memory bandwidth, the modern way to solve all that mess is by using depth buffers except for the alpha blending materials.

The only thing I can say about the high-resolution isometric filling would be to just scale down the resolution down a bit to 1024x768 MAX and have a very good clipping system that does not render the tiles outside that range.

stress test image

Just to give you an idea, my game is fairly optimized to run with opengl 1.0 and its only rendering 2 layers @ 800x600 and I can barley sustain 100fps with the screen filled. I have tried 1280x1024 and it dips below 60. On my newer laptop it goes below 30FPS if i really stress it with my game. My aim was to have the game playable on minimal pc's that are 4-5 years old and budget laptops with minimal 3d hardware or older more powerful laptop.

PC - 100FPS
AMD Athlon XP 1800+ (1.5GHz)
512MB pc2700 system ram
ATI Radeon 9800 SE 128MB ram

Laptop - 20-30FPS
AMD 64 1.8GHz
512 shared ram
ATI RADEON XPRESS 200M

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this