drawing batches of tiles

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Dembele
Posts: 3
Joined: Thu Jun 15, 2017 5:44 pm

drawing batches of tiles

Post by Dembele »

Hi! That's my first post over here so if I missed a thread or something I sincerely apologise.

My problem that I need to draw tiles en masse, for a 1080p its around 8000 tiles ((1920/16) * (1080/16)). My approach thus far is generating an array of source and dest:

Code: Select all

 
core::array<position2d<s32>> destinationBatch;
core::array<rect<s32>> sourceBatch;
 
and then fill it in the main loop depending on player's position:

Code: Select all

 
destinationBatch.clear();
sourceBatch.clear();
int i = 0, j = 0;
for (int h = player.getCoordinatesX(); h < screenTileSize.Height + player.getCoordinatesX(); h++)
{
    for (int w = player.getCoordinatesY(); w < screenTileSize.Width + player.getCoordinatesY(); w++)
    {
       int posH = tilemap[h][w] / 8;
       int posW = tilemap[h][w] % 8;
 
        destinationBatch.push_back(position2d<s32>(16 * i, 16 * j));
        sourceBatch.push_back(rect<s32>(posW * 16, posH * 16, (posW + 1) * 16, (posH + 1) * 16));
        i++;
     }
     j++;
     i = 0;
}
//somewhere later in the loop
driver->draw2DImageBatch(tileAtlas, destinationBatch, sourceBatch);
 
I can see some places I can improve a bit, but that won't increase my FPS a lot. Now my FPS is round 40, which will be later reduced even more by game logic, NPC and so on.
The only solution I can see is using a 32x32 or 64x64 tiles, but I don't really want to do that. Any ideas that can be useful?

EDIT: forgot to add that im using opengl driver
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: drawing batches of tiles

Post by CuteAlien »

Hm, doesn't look wrong on first view. Just wondering - do you compile in release? As for figuring out where the bottleneck is it helps to use a profiler. On Windows I can recommend VerySleepy (http://www.codersnotes.com/sleepy/) which is very easy to use. Compile your application in release but with debug information and then simply start it in VerySleepy - or start VerySleepy after starting your application and click then on the running process in there. If you get information from that it might give you a hint. Thought with graphic-applications it's always a little bit more tricky as this only shows you the CPU side (while this might as well be a problem with drawing on GPU).

edit: If you put some full working example on github or bitbucket (or any other similar webside) it will be easier for others to help you.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Dembele
Posts: 3
Joined: Thu Jun 15, 2017 5:44 pm

Re: drawing batches of tiles

Post by Dembele »

thanks a lot! My problem was building my app in a debug mode. I switched from debug x86 to debug x64 (FPS went from 40 to 50) but changing it to a release (x64) gave a HUGE boost to 600 FPS.
Arclamp
Posts: 71
Joined: Thu Oct 10, 2013 7:45 pm

Re: drawing batches of tiles

Post by Arclamp »

My thought would be to reserve the array memory before the loop?
i.e. all at once
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: drawing batches of tiles

Post by CuteAlien »

Yeah - always good in games to reserve dynamic memory for arrays not inside loops. Thought get used to a profiler tool like VerySleepy - it's rather fun to use (at least I always enjoy working with it) and really easy (in a previous company we even send that out to users and they managed to send us back profile reports with it).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: drawing batches of tiles

Post by hendu »

You're still making 8k drawcalls, which uses a lot of cpu. You'd want to make just one. Either batch that with a large vertex buffer, or write a shader.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: drawing batches of tiles

Post by CuteAlien »

Unfortunately we don't have 2D meshbuffers. So would mean using 3D mode for that then... which might still
be faster even if it sends more data (2d mode sends only 2d vertices). Not sure how you would do shader for that as passing vertices/indices is the slow part - so still needs a large vertex buffer?

I really have to do some simply 2D game some day to learn more about this. But I guess.. I would probably use 3D meshbuffers even for a 2D game and write some custom scenenode for this.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: drawing batches of tiles

Post by hendu »

The shader would be rendered with a screenquad, and take two textures as input: the rgb atlas, and a r8 (r8g8 if more than 256 tiles) index map of size (tiles_w + 1, tiles_h + 1).
Dembele
Posts: 3
Joined: Thu Jun 15, 2017 5:44 pm

Re: drawing batches of tiles

Post by Dembele »

hendu wrote:You're still making 8k drawcalls, which uses a lot of cpu. You'd want to make just one. Either batch that with a large vertex buffer, or write a shader.
Hm, doesnt irrlicht make a single draw call with draw2DBatch function?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: drawing batches of tiles

Post by CuteAlien »

No, it seems to make one draw call per image.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
realmsinthemists
Posts: 28
Joined: Mon Mar 27, 2017 7:29 am

Re: drawing batches of tiles

Post by realmsinthemists »

wouldn't it be simpler to just create a 3D mesh for the entire terrain, maybe broken up into several chunks while using an ortho cam.

it gives you a lot of advantages I think, like depths for moving objects, rotation of buildings and a lot more.

also you can still use 2D data, accept the Z-offset which would be the Y position where Z... you'll guess.

With a mesh you have the advantage of create it once and only change it when a tile actually is changing its data type (or height). Goes for terrain but also for 'indoor' rooms or streets.

e.g.: pseudo, you do more but (a lot) less data will be constantly send to the gpu
(also, you can customise the [driver->draw2DImageBatch function] or create a new function, an example would be [IVideoDriver::draw2DImageBatch(...)] itself)
(Or render the tiles to a texture and use [draw2DImageBatch()] on that.)

Code: Select all

 
class cLayer
{
// maybe this can be broken up into several chunks, only render/update those within the frustum of the camera
update(){if(modified) { create the mesh }};
daw(){ the mesh }
}
 
class cTile
{
}
 
class cStreets : public cLayer
{
array cTile; // index could easily be used as x, y position when calling cLayer::update()
update() override {}
}
 
class cBuilding
{
vector2di posOnTheGridOfStreets; // a building can use its own grid and thus overlapping one tile of cStreets
array cTile; // or cBuildingTile
}
 
class cBuildings : public cLayer
{
array cBuilding;
draw(){ building[it].draw() }
}
 
mainloop
{
 
   gamelogic.update();
 
   streets.update();
   buildings.update();
 
begin scene
   streets.draw();
   buildings.draw();
end scene
 
}
 
 
For my end result I am working on:
- Volume Voxel System
- Simple light weight physics engine
Post Reply