Skip ahead a few debugging sessions...
As a test, I created 1,000 Billboard Scene Node ; I get around 450 fps. I copied the Irrlicht's CBillboardSceneNode files to my project, renamed the class to CBillboardSceneNode2, and tried to create a thousand instances of that class ; I get around 140 fps.
There has to be something going on. Why am I getting these kind of poor performance if I'm using the exact same class as the engine?
EDIT :
Here's my code, in case it's relevant. As I said, CBillboardSceneNode2 is an exact copy of Irrlicht's CBillboardSceneNode.cpp/.h with the class renamed to CBillboardSceneNode2 (see line 75).
Code: Select all
#include <windows.h>
#include <irrlicht.h>
#include "CBillboardSceneNode2.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
#define NB_STRESS_TEST (1000)
#define SCREEN_WIDTH (1024)
#define SCREEN_HEIGHT (768)
void SetWindowCaptionString(core::stringw* strCaption, s32 FPS, const core::stringw &strDriverName)
{
*strCaption = L"Irrlicht Stress Test Program - [";
*strCaption += strDriverName;
*strCaption += "] FPS:";
*strCaption += FPS;
}
int main(int argc, const char* argv[])
{
IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D9, dimension2d<u32>(SCREEN_WIDTH, SCREEN_HEIGHT), 16, false, false, false, eventReceiver);
int iFPS = 0, iLastFPS = 0;
core::stringw strWindowCaption;
if(device)
{
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
// Declare a screensize object using the values from the driver
const core::dimension2d<u32> screenSize = driver->getScreenSize();
// Get the camera node
ICameraSceneNode *cam = (scene::ICameraSceneNode *)smgr->getSceneNodeFromType(scene::ESNT_CAMERA);
// If the camera doesn't exists (which is the case here, because the program just started)
if(cam == NULL)
{
// Add a camera node with the top-left corner pointing at (0,0,0), and a field of view of 100 units, which will be used as a percentage to properly align the 2D pixels on screen.
cam = device->getSceneManager()->addCameraSceneNode(0, irr::core::vector3df((f32)screenSize.Width/2, -((f32)(screenSize.Height/2)), -1), irr::core::vector3df((f32)screenSize.Width / 2, -((f32)(screenSize.Height / 2)), 100));
}
// Create a projection matrix to translate a 3D view to the exact screen size, and an orthographic field of view of 1000 units.
matrix4 projectionMatrix;
projectionMatrix.buildProjectionMatrixOrthoLH((f32)screenSize.Width, (f32)screenSize.Height, 0.0f, 1000.0f);
// Apply the projection matrix to the camera.
cam->setProjectionMatrix(projectionMatrix, true);
// The world and the view needs to be reset to the identity matrix, in order to remove any matrix transformation for field of view.
driver->setTransform(video::ETS_WORLD, core::matrix4());
driver->setTransform(video::ETS_VIEW, core::matrix4());
video::ITexture* testTexture = driver->getTexture("./Resources/Test.png");
ISceneNode* parentNode = smgr->addEmptySceneNode(0);
ISceneNode* testNodes[NB_STRESS_TEST];
for(int iNode = 0; iNode < NB_STRESS_TEST; iNode++)
{
// testNodes[iNode] = new CBillboardSceneNode2(parentNode, smgr, 0, core::vector3df(((int)testTexture->getSize().Width / 2), 0 - ((int)testTexture->getSize().Height / 2), 0), core::dimension2d<f32>((f32)testTexture->getSize().Width, (f32)testTexture->getSize().Height));
testNodes[iNode] = smgr->addBillboardSceneNode(parentNode, core::dimension2d<f32>((f32)testTexture->getSize().Width, (f32)testTexture->getSize().Height));
testNodes[iNode]->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL);
testNodes[iNode]->setMaterialTexture(0, testTexture);
testNodes[iNode]->getMaterial(0).AntiAliasing = video::EAAM_FULL_BASIC;
testNodes[iNode]->getMaterial(0).TextureLayer[0].BilinearFilter = false;
testNodes[iNode]->setMaterialFlag(video::EMF_LIGHTING, false);
testNodes[iNode]->setMaterialFlag(video::EMF_ANISOTROPIC_FILTER, false);
testNodes[iNode]->setMaterialFlag(video::EMF_ANTI_ALIASING, false);
testNodes[iNode]->setMaterialFlag(video::EMF_USE_MIP_MAPS, false);
}
parentNode->setVisible(true);
while(device->run())
{
/********/
/* DRAW */
/********/
driver->beginScene(true, true, SColor(255, 0, 0, 0));
driver->enableMaterial2D(true);
for(int i = 0; i < NB_STRESS_TEST; i++)
{
int X = (rand() % (screenSize.Width - testTexture->getSize().Width));
int Y = 0 - (rand() % (screenSize.Height - testTexture->getSize().Height));
testNodes[i]->setPosition(core::vector3df(X + ((int)testTexture->getSize().Width / 2), Y - ((int)testTexture->getSize().Height / 2), 0));
}
driver->enableMaterial2D(false);
smgr->drawAll();
guienv->drawAll();
driver->endScene();
/******************/
/* WINDOW CAPTION */
/******************/
// Get the FPS and build the window caption with it.
iFPS = driver->getFPS();
if(iLastFPS != iFPS)
{
SetWindowCaptionString(&strWindowCaption, iFPS, driver->getName());
device->setWindowCaption(strWindowCaption.c_str());
iLastFPS = iFPS;
}
}
}
device->drop();
return 0;
}