Still searching for a batching advise or sthg
Hi,
long time since i last created a topic here, but finally i got a little free time again to play around with irrlicht
and - of course - i'm having a performance problem with the 2d graphics and i wonder, what i'm doing wrong.
my application is creating 2000 32x32 images which are moving randomly within the windowsize. since i know, that with f.e. DarkGDK or SDL i can create more then 2k sprites and still have a fpsrate>60, i am confused, that with irrlicht i only get about 10-15fps.
i know irrlicht is much more complex and u can easily mess things up with stupid mistakes, but i don't really get my problem in my application here.
the important classes are the image,explodeableobject and triangle class.
here they are:
Code: Select all
#ifndef IMAGE_H
#define IMAGE_H
#include "Framework.h"
class Image
{
private:
irr::video::ITexture* _texture;
irr::gui::IGUIImage* _image;
irr::video::SColor _color;
float _posX;
float _posY;
float _scale;
unsigned int _width;
unsigned int _height;
void SetBoundingRect()
{
_image->setRelativePosition(
irr::core::rect<int>( (int)_posX, (int)_posY, (int)(_posX+_width*_scale), (int)(_posY+_height*_scale) ) );
} // end SetBoundingRect
public:
Image( const char* texturepath )
{
_texture = VIDEODRIVER->getTexture( texturepath );
_color = irr::video::SColor( 255, 255, 255, 255 );
_scale = 1;
_posX = _posY = 0;
_width = _texture->getSize().Width;
_height = _texture->getSize().Height;
_image = GUIENV->addImage( _texture, irr::core::vector2d<int>((int)_posX,(int)_posY) );
_image->setScaleImage( true );
} // end Konstructor
~Image()
{
VIDEODRIVER->removeTexture( _texture );
_image->remove();
} // end Destructor
void draw(){ _image->draw(); }
void SetPosition( float x, float y ){ _posX = x; _posY = y; SetBoundingRect(); }
void SetScale( float scale ){ _scale = scale; SetBoundingRect(); }
void SetColor( int r, int g, int b )
{
_color = irr::video::SColor( 255, r, g, b );
_image->setColor( _color );
}
inline float GetPositionX() const { return _posX; }
inline float GetPositionY() const { return _posY; }
inline float GetScale() const { return _scale; }
inline float GetWidth() const { return _width*_scale; }
inline float GetHeight() const { return _height*_scale; }
};
#endif
Code: Select all
#ifndef EXPLODEABLEOBJECT_H
#define EXPLODEABLEOBJECT_H
#include "Image.h"
class ExplodeableObject
{
protected:
static const float SPEED_MIN;
static const float SPEED_MAX;
static const float TIME_EXPLOSION;
static const float SCALE_MAX; // maximum scale size for explosion
irr::core::vector2df _velocity;
irr::core::vector2df _position;
irr::video::SColor _color;
float _scale;
bool _isExploding;
bool _isRemoveable;
float _explosionTime;
float _scaleGain; // on explosion scalegain
Image* _image;
public:
ExplodeableObject( Image* img )
{
_isExploding = _isRemoveable = false;
_velocity = irr::core::vector2df( FRAMEWORK->GetRandomFloat( SPEED_MIN, SPEED_MAX ),
FRAMEWORK->GetRandomFloat( SPEED_MIN, SPEED_MAX ) );
switch( FRAMEWORK->GetRandomInt( 1, 4 ) )
{
case( 0 ): break;
case( 1 ): _velocity.X = -_velocity.X; break;
case( 2 ): _velocity.Y = -_velocity.Y; break;
case( 3 ): _velocity.X = -_velocity.X; _velocity.Y = -_velocity.Y; break;
}
_image = img;
_scale = 1;
_position = irr::core::vector2df( (float)FRAMEWORK->GetRandomInt( 0, VIDEODRIVER->getScreenSize().Width ),
(float)FRAMEWORK->GetRandomInt( 0, VIDEODRIVER->getScreenSize().Height ) );
_color = irr::video::SColor( 255, FRAMEWORK->GetRandomInt(0,255), FRAMEWORK->GetRandomInt(0,255), FRAMEWORK->GetRandomInt(0,255) );
_explosionTime = _scaleGain = 0.0f;
} // end Konstructor
virtual ~ExplodeableObject()
{
//delete _image;
} // end Destructor
virtual void OnUpdate( float deltatime ) = 0;
void Update( float deltatime )
{
if( _isRemoveable )
return;
OnUpdate( deltatime );
_position = irr::core::vector2df( _position.X+_velocity.X*deltatime,
_position.Y+_velocity.Y*deltatime );
// if object is exploding, expand it for TIME_EXPLOSION/2 seconds before
// it slowly gets smaller and smaller until it disappears
if( _isExploding )
{
if( _explosionTime == 0 )
{
// calculate the scalegain per second
_scaleGain = (SCALE_MAX-_image->GetScale())/(TIME_EXPLOSION*0.5f);
}
else if( _explosionTime >= TIME_EXPLOSION )
_isRemoveable = true;
else if( _explosionTime >= (TIME_EXPLOSION * 0.5f) && _scaleGain > 0 )
_scaleGain = -_scaleGain;
_explosionTime += deltatime;
_scale += _scaleGain*deltatime;
}
} // end Update
virtual void OnRender() = 0;
void Render()
{
if( _isRemoveable )
return;
OnRender();
_image->SetColor( _color.getRed(), _color.getGreen(), _color.getBlue() );
_image->SetScale( _scale );
_image->SetPosition( _position.X, _position.Y );
_image->draw();
} // end Render
void SetVelocity( float velX, float velY ){ _velocity = irr::core::vector2df( velX, velY ); }
inline irr::core::vector2df GetVelocity() const { return _velocity; }
void Explode(){ _isExploding = true; }
inline bool IsExploding() const { return _isExploding; }
inline bool IsRemoveable() const { return _isRemoveable; }
virtual bool IsColliding( const ExplodeableObject* obj ) = 0;
const Image* GetImage(){ return _image; }
};
const float ExplodeableObject::SPEED_MIN = 12.0f;
const float ExplodeableObject::SPEED_MAX = 25.5f;
const float ExplodeableObject::TIME_EXPLOSION = 2.5f;
const float ExplodeableObject::SCALE_MAX = 3.0f;
#endif
Code: Select all
#ifndef TRIANGLE_H
#define TRIANGLE_H
#include "ExplodeableObject.h"
class Triangle : public ExplodeableObject
{
private:
irr::core::position2df _vertices[3];
void UpdateVertices()
{
// x and y of the image is the top left corner of the image rect
// to get the 3 triangle vertices we just need the top middle,
// left bottom and left right coordinate
const float x = _image->GetPositionX();
const float y = _image->GetPositionY();
const float w = _image->GetWidth();
const float h = _image->GetHeight();
_vertices[0] = irr::core::position2df( x + w/2, y );
_vertices[1] = irr::core::position2df( x, y+h );
_vertices[2] = irr::core::position2df( x+w, y+h );
}
public:
Triangle( Image* img ) : ExplodeableObject( img )
{
UpdateVertices();
} // end Konstructor
~Triangle()
{
} // end Destructor
void OnUpdate( float deltatime )
{
UpdateVertices();
for( int i=0; i<3; ++i )
{
// check if a vertex is outside the window
// if so -> recalculate velocity
if( _vertices[i].X+_velocity.X*deltatime < 0 || _vertices[i].X+_velocity.X*deltatime > VIDEODRIVER->getScreenSize().Width ||
_vertices[i].Y+_velocity.Y*deltatime < 0 || _vertices[i].Y+_velocity.Y*deltatime > VIDEODRIVER->getScreenSize().Height )
{
_velocity.X = -_velocity.X;
_velocity.Y = -_velocity.Y;
}
}
//IsColliding( obj );
} // end OnUpdate
void OnRender(){}
bool IsColliding( const ExplodeableObject* obj )
{
return false;
} // end IsColliding
};
#endif
and finally the mainloop, where i create and update the objects:
Code: Select all
void Game::Loop()
{
irr::IrrlichtDevice* device = DEVICE;
irr::video::IVideoDriver* video = VIDEODRIVER;
device->setWindowCaption( L"FQ Exploder 2010" );
FRAMEWORK->PlayMusic( "media/music/background.mp3" );
while( device->run() && video && _currentState != GAME_STATE_QUIT )
{
if( device->isWindowActive() )
{
FRAMEWORK->UpdateTime();
video->beginScene();
switch( _currentState )
{
case( GAME_STATE_MAIN_MENU ): RunMainMenu(); break;
case( GAME_STATE_GAME ): RunGame(); break;
case( GAME_STATE_QUIT ): break;
case( GAME_STATE_VICTORY ): RunVictory(); break;
case( GAME_STATE_DEFEAT ): RunDefeat(); break;
}
video->endScene();
FRAMEWORK->UpdateTime();
FRAMEWORK->UpdateInput();
}
else
device->yield();
}
} // end Loop
void Game::RunMainMenu()
{
} // end RunMainMenu
void Game::RunGame()
{
const int numtris = 2000;
static Triangle* tri[numtris];
static Image* img = new Image( "media/images/Triangle.png" );
if( tri[0] == NULL )
{
for( int i = 0;i<numtris; ++i )
tri[i] = new Triangle( img );
}
if( FRAMEWORK->IsKeyPressed( irr::KEY_ESCAPE ) )
{
for( int i = 0;i<numtris; ++i )
delete tri[i];
delete img;
_currentState = GAME_STATE_QUIT;
return;
}
if( FRAMEWORK->IsMouseLeftPressed() )
tri[FRAMEWORK->GetRandomInt( 0, numtris-1 )]->Explode();
const float deltat = FRAMEWORK->GetDeltaTime();
for( int i = 0;i<numtris; ++i )
{
tri[i]->Update( deltat );
tri[i]->Render();
}
irr::core::stringw text = "";
text += VIDEODRIVER->getFPS();
DEVICE->setWindowCaption( text.c_str() );
} // end RunGame
if i comment the tri->Update( deltat ); line i still only get ~10fps so there must be some mistakes within the render method and i can't find them.
some hints pls
edit:
k i found out, that i don't need the iguiimage. and with a little code refactoring the application now runs 3time faster (~30fps instead of 10). however i now got a weird color problem. the triangles seem more transparent now and switching their colors continuously. an explanation would help me there, if someone knows why.
here the new image code:
Code: Select all
#ifndef IMAGE_H
#define IMAGE_H
#include "Framework.h"
class Image
{
private:
irr::video::ITexture* _texture;
irr::video::SColor _color;
float _posX;
float _posY;
float _scale;
unsigned int _width;
unsigned int _height;
public:
Image( const char* texturepath )
{
_texture = VIDEODRIVER->getTexture( texturepath );
_color = irr::video::SColor( 255, 255, 255, 255 );
_scale = 1;
_posX = _posY = 0;
_width = _texture->getSize().Width;
_height = _texture->getSize().Height;
} // end Konstructor
~Image()
{
//VIDEODRIVER->removeTexture( _texture );
} // end Destructor
void draw()
{
VIDEODRIVER->draw2DImage( _texture,
irr::core::rect<int>( (int)_posX, (int)_posY, (int)(_posX+_width*_scale), (int)(_posY+_height*_scale) ),
irr::core::rect<int>(0,0,_width,_height),
0,&_color,true);
} // end draw
void SetPosition( float x, float y ){ _posX = x; _posY = y; }
void SetScale( float scale ){ _scale = scale; }
void SetColor( int r, int g, int b )
{
_color = irr::video::SColor( 255, r, g, b );
}
inline float GetPositionX() const { return _posX; }
inline float GetPositionY() const { return _posY; }
inline float GetScale() const { return _scale; }
inline float GetWidth() const { return _width*_scale; }
inline float GetHeight() const { return _height*_scale; }
};
#endif
here are 2 screenshots:
the first shows the old version with the correct color but low fps.
the second one shows the new version with wrong colors but higher fps.
edit3:
API ftwcolors Array of 4 colors denoting the color values of the corners of the destRect
but still. isn't 30 fps low for 2k moving images?
system:
intel core 2duo @ 2.1ghz
2gb ram
mobile intel 965 express chipset family (guess 256 ram)