I have a simple application derived from Tutorial 3: Custom Scene Node [1]. I'm only rendering 1200 cubes (each cube has 12 triangles thus 14400 triangles in total) which all share one texture and I get about 7fps when rendering in OpenGL on Linux. I tried the buring video software renderer and get an equal number of fps. Therefore I thought my OpenGL driver is broken but glmark2-es2 [2] has no less than a 100 to 500 fps (depending on the concete test). What's wrong with my (very simple) program?
Code: Select all
#include <cstdint>
#include <random>
#include <stdexcept>
#include <irrlicht.h>
#include "driverChoice.h"
using namespace irr;
typedef enum {
UPPER_LEFT,
UPPER_RIGHT,
LOWER_LEFT,
LOWER_RIGHT
} Corner;
class GtaTextureIndex {
public:
static uint32_t const ROWS = 31;
static uint32_t const COLUMNS = 32;
private:
uint32_t const row;
uint32_t const column;
static uint32_t row_offset(Corner corner) {
return (UPPER_LEFT == corner) || (UPPER_RIGHT == corner)
? 0 : 1;
}
static uint32_t column_offset(Corner corner) {
return (UPPER_LEFT == corner) || (LOWER_LEFT == corner)
? 0 : 1;
}
public:
GtaTextureIndex(uint32_t const row, uint32_t const column) : row(row), column(column) {
if (row >= ROWS) {
throw std::runtime_error(std::string("`row' invalid"));
}
if (column >= COLUMNS) {
throw std::runtime_error(std::string("`column' invalid"));
}
}
float u(Corner corner) const {
return (float)(column + column_offset(corner)) / COLUMNS;
}
float v(Corner corner) const {
return (float)(row + row_offset(corner)) / ROWS;
}
};
class Square : public scene::ISceneNode {
private:
core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;
public:
Square(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, GtaTextureIndex const& texture_idx) : scene::ISceneNode(parent, mgr, id) {
Material.Wireframe = false;
Material.Lighting = false;
Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
video::SColor white = video::SColor(255,255,255,255);
Vertices[0] = video::S3DVertex(-10,+10,0, 1,1,0, white, texture_idx.u(UPPER_LEFT), texture_idx.v(UPPER_LEFT)); // A
Vertices[1] = video::S3DVertex(+10,+10,0, 1,0,0, white, texture_idx.u(UPPER_RIGHT), texture_idx.v(UPPER_RIGHT)); // B
Vertices[2] = video::S3DVertex(-10,-10,0, 0,1,1, white, texture_idx.u(LOWER_LEFT), texture_idx.v(LOWER_LEFT)); // C
Vertices[3] = video::S3DVertex(+10,-10,0, 0,0,1, white, texture_idx.u(LOWER_RIGHT), texture_idx.v(LOWER_RIGHT)); // D
Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i) {
Box.addInternalPoint(Vertices[i].Pos);
}
}
virtual void OnRegisterSceneNode() {
if (IsVisible) {
SceneManager->registerNodeForRendering(this);
}
ISceneNode::OnRegisterSceneNode();
}
virtual void render() {
u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 };
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setMaterial(Material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
}
virtual const core::aabbox3d<f32>& getBoundingBox() const {
return Box;
}
virtual u32 getMaterialCount() const {
return 1;
}
virtual video::SMaterial& getMaterial(u32 i) {
return Material;
}
};
class Cube : public scene::ISceneNode {
private:
core::aabbox3d<f32> Box;
Square front;
Square back;
Square left;
Square right;
Square top;
Square bottom;
public:
Cube(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
GtaTextureIndex const& front_texture_idx,
GtaTextureIndex const& back_texture_idx,
GtaTextureIndex const& left_texture_idx,
GtaTextureIndex const& right_texture_idx,
GtaTextureIndex const& top_texture_idx,
GtaTextureIndex const& bottom_texture_idx
) :
scene::ISceneNode(parent, mgr, id),
front(this, mgr, id + 1, front_texture_idx),
back(this, mgr, id + 2, back_texture_idx),
left(this, mgr, id + 3, left_texture_idx),
right(this, mgr, id + 4, right_texture_idx),
top(this, mgr, id + 5, top_texture_idx),
bottom(this, mgr, id + 6, bottom_texture_idx)
{
addChild(&front);
addChild(&back);
addChild(&left);
addChild(&right);
addChild(&top);
addChild(&bottom);
front.setPosition(core::vector3df(0, 0, -10));
back.setPosition(core::vector3df(0, 0, +10));
left.setRotation(core::vector3df(0, -90, 0));
left.setPosition(core::vector3df(-10, 0, 0));
right.setRotation(core::vector3df(0, +90, 0));
right.setPosition(core::vector3df(+10, 0, 0));
top.setRotation(core::vector3df(-90, 0, 0));
top.setPosition(core::vector3df(0, -10, 0));
bottom.setRotation(core::vector3df(+90, 0, 0));
bottom.setPosition(core::vector3df(0, +10, 0));
}
virtual void OnRegisterSceneNode() {
if (IsVisible) {
SceneManager->registerNodeForRendering(this);
}
ISceneNode::OnRegisterSceneNode();
}
virtual void render() {
front.render();
back.render();
left.render();
right.render();
top.render();
bottom.render();
}
virtual const core::aabbox3d<f32>& getBoundingBox() const {
return front.getBoundingBox();
}
virtual u32 getMaterialCount() const {
return 6;
}
virtual video::SMaterial& getMaterial(u32 i) {
switch (i) {
case 0: return front.getMaterial(0);
case 1: return back.getMaterial(0);
case 2: return left.getMaterial(0);
case 3: return right.getMaterial(0);
case 4: return top.getMaterial(0);
case 5: return bottom.getMaterial(0);
}
throw std::range_error("Invalid material index");
}
};
int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
// create device
IrrlichtDevice *device = createDevice(driverType,
core::dimension2d<u32>(1600, 800), 32, false);
if (device == 0)
return 1; // could not create selected driver.
// create engine and camera
device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo");
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
// smgr->addCameraSceneNode(0, core::vector3df(0,0,-400), core::vector3df(0,0,0));
// smgr->addCameraSceneNodeMaya();
smgr->addCameraSceneNodeFPS();
video::ITexture* texture = driver->getTexture("../media/chross_gta2.png");
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> row(0, GtaTextureIndex::ROWS - 1);
std::uniform_int_distribution<> column(0, GtaTextureIndex::COLUMNS - 1);
for (ssize_t x = -10; x < 10; ++x) {
for (ssize_t y = -10; y < 10; ++y) {
for (ssize_t z = 0; z < 3; ++z) {
Cube *myNode = new Cube(smgr->getRootSceneNode(), smgr, 666,
GtaTextureIndex(row(gen), column(gen)),
GtaTextureIndex(row(gen), column(gen)),
GtaTextureIndex(row(gen), column(gen)),
GtaTextureIndex(row(gen), column(gen)),
GtaTextureIndex(row(gen), column(gen)),
GtaTextureIndex(row(gen), column(gen))
);
myNode->setMaterialTexture(0, texture);
myNode->setPosition(core::vector3df(x * 40, y * 40, z * 40));
scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));
if(anim && false) {
myNode->addAnimator(anim);
anim->drop();
anim = 0;
}
myNode->drop();
myNode = 0; // As I shouldn't refer to it again, ensure that I can't
}
}
}
u32 frames=0;
while(device->run())
{
driver->beginScene(true, true, video::SColor(0,100,100,100));
smgr->drawAll();
driver->endScene();
if (++frames==100)
{
core::stringw str = L"Irrlicht Engine [";
str += driver->getName();
str += L"] FPS: ";
str += (s32)driver->getFPS();
device->setWindowCaption(str.c_str());
frames=0;
}
}
device->drop();
return 0;
}
-- ooxi
[1] http://irrlicht.sourceforge.net/docu/example003.html
[2] http://packages.ubuntu.com/de/vivid/glmark2-es2
[3] http://subvein.chross.de/gts/chross_gta2.png