C#, Sprite Drawing Performance

Started by
8 comments, last by remigius 15 years, 9 months ago
Hello, I'm writing an application that should render simple tile-based 'world', built from System.Drawing.Bitmap tiles, sized 32x32 pixels onto a Form. Here are parts of the code: Class is derived from Form:
class Renderer : Form {

private Device device;
private Sprite sprite;
Initialization:
PresentParameters parameters = new PresentParameters();
parameters.Windowed = true;
parameters.SwapEffect = SwapEffect.Discard;

CreateFlags createflags = CreateFlags.HardwareVertexProcessing | CreateFlags.PureDevice;

device = new Device(0, DeviceType.Hardware, this, createflags, parameters);
sprite = new Sprite(device);
Textures are created from bitmaps:

[...] = new Texture(device, bitmap, 0, Pool.Managed);
And the actual drawing:
            device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
            device.BeginScene();
            sprite.Begin(SpriteFlags.AlphaBlend);
           
            for (int h = 7; h >= z; h--) {              
                for (int ay = 0; ay < 600 / 32 + 2; ay ++) {
                    for (int ax = 0; ax < 800 / 32 + 2 + 2; ax ++) {
      
                        int[] items_array = map.getData(ax, ay, h);
                       
                        foreach (int it in items_array) {
                            Texture texture = map.getTexture(it);             
                            sprite.Draw2D(texture, new Point(0, 0), 0, new Point(ax * 32, ay  * 32), Color.White);
                          
                        }
                    }
                }
            }
            sprite.End();
            device.EndScene();
            device.Present();
Pretty self explaining, it fills the screen area with tiles, but the problem is - with all those up to 8 floors (though not all of them are always completely filled), and single tiles composed of many textures it means a lot of work - in worst cases, around 5000 calls to sprite.Draw2D to redraw the whole scene, which unfortunately takes noticable time. I would like to ask for your advice - is it possible to achieve the effect this code does (by some modifications to it, or maybe with completly diffrent approach?), but with performance that allows for smooth animation and scrolling? How?
Advertisement
Use XNA Games Studio or managed directx instead of winforms.
Quote:Original post by mpipe
Use XNA Games Studio or managed directx instead of winforms.


He is quite obviously using Managed DirectX already.
Mike Popoloski | Journal | SlimDX
I can't say for sure, but it looks like you're using multiple textures (perhaps 1 for each tile?) You really should pack those tile bitmaps into the one larger texture. If you're dealing with 32x32 tiles you can pack quite a few onto a 512x512 texture.
Quote:Original post by Tape_Worm
I can't say for sure, but it looks like you're using multiple textures (perhaps 1 for each tile?) You really should pack those tile bitmaps into the one larger texture.


Indeed I am, but that's the nature of the application , it doesn't display some static background, but dynamically gets the data about each single tile and has to build the image from those little pieces.

I know it would be more efficient to provide the device with larger textures, but is there a way to dynamically build those from 32x32 tiles that would be significally faster than drawing each single of them the way I do it now?
Quote:Original post by gorky20
Indeed I am, but that's the nature of the application , it doesn't display some static background, but dynamically gets the data about each single tile and has to build the image from those little pieces.

I know it would be more efficient to provide the device with larger textures, but is there a way to dynamically build those from 32x32 tiles that would be significally faster than drawing each single of them the way I do it now?


I think you've misunderstood what I'm saying. I'm not proposing you display your tile map as a single image. I'm stating that you should pack your individual tile bitmaps onto a single texture. Your map can still be drawn from those tiles, just the tiles will all be located on the same texture as opposed to being single 32x32 bitmaps.
Quote:Original post by Tape_Worm
Quote:Original post by gorky20
Indeed I am, but that's the nature of the application , it doesn't display some static background, but dynamically gets the data about each single tile and has to build the image from those little pieces.

I know it would be more efficient to provide the device with larger textures, but is there a way to dynamically build those from 32x32 tiles that would be significally faster than drawing each single of them the way I do it now?


I think you've misunderstood what I'm saying. I'm not proposing you display your tile map as a single image. I'm stating that you should pack your individual tile bitmaps onto a single texture. Your map can still be drawn from those tiles, just the tiles will all be located on the same texture as opposed to being single 32x32 bitmaps.


Yes, yes, to Tape_Worm you listen!
Mike Popoloski | Journal | SlimDX
Quote:Original post by Mike.Popoloski
Quote:Original post by Tape_Worm
Quote:Original post by gorky20
Indeed I am, but that's the nature of the application , it doesn't display some static background, but dynamically gets the data about each single tile and has to build the image from those little pieces.

I know it would be more efficient to provide the device with larger textures, but is there a way to dynamically build those from 32x32 tiles that would be significally faster than drawing each single of them the way I do it now?


I think you've misunderstood what I'm saying. I'm not proposing you display your tile map as a single image. I'm stating that you should pack your individual tile bitmaps onto a single texture. Your map can still be drawn from those tiles, just the tiles will all be located on the same texture as opposed to being single 32x32 bitmaps.


Yes, yes, to Tape_Worm you listen!


So I assume you're about 3 feet tall, have green wrinkly skin, train jedi and have some messed up grammar?
Quote:
So I assume you're about 3 feet tall, have green wrinkly skin, train jedi and have some messed up grammar?

On points (1), (2), and (4) you are correct. Point (3) is just what he'd like you to believe. In reality he just makes coffee.

Quote:
Pretty self explaining, it fills the screen area with tiles, but the problem is - with all those up to 8 floors (though not all of them are always completely filled), and single tiles composed of many textures it means a lot of work - in worst cases, around 5000 calls to sprite.Draw2D to redraw the whole scene, which unfortunately takes noticable time.

I would like to ask for your advice - is it possible to achieve the effect this code does (by some modifications to it, or maybe with completly diffrent approach?), but with performance that allows for smooth animation and scrolling? How?

Tape_Worm's suggestion is the correct approach -- pack the reused texture tiles into a single texture and adjust the texcoords to send only a subset of that texture for each unique tile instance.

Since doing this via the sprite interface may be clunky, you may have to handle the quads manually -- this is annoying, but has the benefit of allowing you to take advantages of batching or instancing techniques to reduce draw calls further, in the optimal case producing one instanced draw call for each unique tile image to render all instances of that tile.
Quote:Original post by jpetrie
On points (1), (2), and (4) you are correct. Point (3) is just what he'd like you to believe. In reality he just makes coffee.


Sorry about the useless comment, but... [lol]
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

This topic is closed to new replies.

Advertisement