Im working on isometric 2D tile engin for RTS game. I have two ways how can I draw floor. One option is one big image (for example 8000px x 8000px have about 10MB) and second option is draw images tile by tile only in visibly area.
My questin is what is better (for performance)?
Performance-wise and memory-wise, a tiled approach is better.
Memory-wise: If you can use a single spritesheet to hold the textures of every tile you need to render, then the amount of memory used would decrease tremendously - as opposed to redefining textures for tiles you want to render more than once. Also, on every texture there is an attribute called "pitch". This attribute tells us how much more memory is being used than the image actually needs. What? Why would my program be doing this? Back in the good old days, when Ben Kenobi was still called Obi Wan Kenobi, textures took up the memory they were supposed to. But now, with hardware acceleration, the GPU adds some padding to your texture to make it align with boundaries that it can process faster. This is memory you can reduce with the use of a spritesheet.
From a performance standpoint: Whenever you draw a regular sprite to the screen, the graphics hardware requires three main pieces of information: 1) The texture you want to render from. 2) What part of that texture you want to render from. 3) Where on the screen you want to render to. Repeat for every object you want to render. With a spritesheet, it only passes data once - a big performance increase because passing data from the CPU to the GPU (and vice-versa) is really slow.
And I disagree with the two comments, actually. Making a change of this caliber would be difficult when your program is mature.
Related
I'm currently trying to implement procedurally generated tilemaps for an overworld. I'm as far as generating noise and building the tilemaps using different ranges within the generated noise. However, they're very crude as each different 'biome' is just one tile. What is the best way to implement the detailing and edges of each biome? e.g flowers/trees/etc spread out in a forest biome, beach-to-water transition tiles between beach and ocean biome, etc.
For some context, I built an engine in MonoGame with a friend of mine. We implemented a chunk loading system for dynamic generation and infinite scrolling with no load screens(not exactly state of the art, I know, but I was proud of it). Each chunk is 50x50 tiles, and there are 9 chunks loaded at any given time. When the player moves chunks in any direction, the chunks on the opposite corner are unloaded and new ones are loaded in the direction the player is walking. Since the player is starting on the opposite of where chunks are being generated, it hasn't been a problem thus far as the maps are big enough that they're done generating by the time the player gets to them. I'm not sure whether the current method I have in mind is going to change this or not.
Anyway, I'm thinking that I need to determine within each biome a specific set of tiles and generate noise for each biome instance to determine placement of 'detail' tiles specific to that biome. For the edges, I'd just loop through each adjacent tile to determine whether it's a different biome. If so, use the transition tile. However, the whole idea seems very inefficient as that's a ton of noise to generate as well as looping through 7500 tiles every time the player moves chunks. I've been trying to think of a better method, but this is my first foray into procedural generation and I haven't been able to find much online that talks about anything more in-depth than generating noise and using that noise to generate chunks of land. Is there a more efficient method I should use or is my next step going to be optimizing? I can't imagine my method is going to be very efficient or practical due to how much I'm going to be looping through every tile. Anyone have any ideas or suggestions? Thanks in advance.
One idea:
Use noise to generate height, temperature, rain, ... for each chunk
Use generated values to determine the biome for each chunk
For each tile interpolate the generated of the surrounding chunks
Use the interpolated values to select ground textures, plants, ...
That should generate smooth borders between biomes and also different chunks with the same biome can have a different feel.
I pretty much put the question in the title. Would it help performance-wise if I stopped drawing targets are aren't on the screen anymore? What I mean by this is:
if (textureLocation is on the screen)
{
draw code here
}
Or it is so insignificant(if at all) that it doesn't matter?
Thanks,
Shyy
Depends. Ultimately spent time comes down to 3 things: sending data to the GPU, vertex shading, and pixel shading.
If the texture is located on a spritesheet that has other textures that are being drawn on screen and the offscreen draw call is within the same .Begin() .End() block as those others, it won't hurt performance since it takes just as long to send data and set the GPU up for the spritesheet. The 4 off-screen vertices will run through the vertex shader but that is not a bottle neck. The graphic pipeline culls offscreen objects between the vertex shader and pixel shader so it won't spend any time in the pixel shader
But if is a stand alone texture or in it's own .Begin() .End() block, it will cost time sending it's data to the GPU even though the GPU will cull it.
Whether it is significant or not only profiling can tell you.
I read about DynamicVertexBuffer, and how it's supposed to be better for data that changes often. I have a world built up by cubes, and I need to store the cubes' vertices in this buffer to draw them to the screen.
However, not all cubes have vertices (some are air, which is transparent) and not all faces of the cubes need to be drawn either (they are facing each other), so how do I keep track of what vertices are stored where in the buffer? Also, certain faces need to be drawn last, namely the ones with transparency in them (like glass or leaves), and these faces also need to be drawn in a back-to-front order to not mess up the alpha blending.
If all of these vertices are stored arbitrarily in this buffer, how do I know what vertices are where?
Also, the number of vertices can change, but the DynamicVertexBuffer doesn't seem very dynamic to me, since I can't change it's size at all. Do I have to recreate the buffer every time I need to add or remove faces?
Sounds like you are approaching this in the wrong way - assuming you have anything more than a trivial number of cubes in your world. You should store the world (and it's cubes) in a custom data structure that lets you rapidly determine which cubes (and faces) are visible based on the rules of your world from a given point when looking in a given direction.
Then each time you render a scene generate batches of vertex buffers of just these faces. So don't use vertex buffers as the basis for storing the entire geometry of your world. Vertex buffers are a rendering tool, not a world scene graph tool.
These kind of large scale visibility issues are much faster run in code than by the GPU. For example if you are sat at the origin, looking +x, you can immediately ignore all cubes in the -ve x direction, this is a very simple example.
For a more complete example search on oct-tree rendering. This kind of rendering would match your world layout quite nicely.
Final tip - when I say generate batches of vertex buffers - I mean batch you cubes together in ways that minimize changes in the state of the GPU (e.g. same texture, same shader etc). Minimizing changes to the state of the GPU is key to optimizing the rendering - once you've gone as far as you can with culling faces from the render in the first place.
I'm working on a simple 2D Real time strategy game using XNA. Right now I have reached the point where I need to be able to click on the sprite for a unit or building and be able to reference the object associated with that sprite.
From the research I have done over the last three days I have found many references on how to do "Mouse picking" in 3D which does not seem to apply to my situation.
I understand that another way to do this is to simply have an array of all "selectable" objects in the world and when the player clicks on a sprite it checks the mouse location against the locations of all the objects in the array. the problem I have with this approach is that it would become rather slow if the number of units and buildings grows to larger numbers. (it also does not seem very elegant) so what are some other ways I could do this. (Please note that I have also worked over the ideas of using a Hash table to associate the object with the sprite location, and using a 2 dimensional array where each location in the array represents one pixel in the world. once again they seem like rather clunky ways of doing things.)
For up to hundreds of units, it should be fast enough to simply do a linear search O(n) over all the units in the world if the click regions are circles or rectangles. Especially seeing as it will be once per click, not once per frame.
If your units are not circular or rectangular, check against a bounding circle or rectangle first, and if that passes check against the more complicated bounding shape.
For a more detailed answer, here's my answer to a similar question about space partitioning. There I mention bucketed grids and quadtrees as potential structures for performance optimisation.
But you should never do performance optimisation until you have tested and actually do have a performance problem!
If you have a class that manages drawabel objects you could have a static int that you increase every time you make a new object, and save the old one as a local instance of Color in the drawabel object. You can then use the .Net type converter to make its to bye arrays and back, dont remember its name and im on my phoneon a train so can't check for you im afraid.
When you build the color from the byte array just remember to max the alpha channel, and if you happen to get too many objects you might overrun the indexes you can use.. not sure what to do then... probably have all your objects reaquire new colors from 0:0:0:255 again since hopefully some old ones are no longer in use :P
Not sure i made alot of sense but since im on a train thats all i can give you, sorry :)
You could use pixel perfect picking, which scales very well to massive numbers of objects (and has the advantage of being pixel perfect).
Essentially you render your scene using a unique colour for each object. Then you resolve the backbuffer into a texture and get the texture data back, finally you can simply check the pixel underneath the mouse and find out which object the mouse is on.
You can be clever about the information you get back, you can request just the single pixel the mouse is on top of.
Color[] pixel = new Color[1];
texture.GetData(pixel, mousePosition.Y * texture.Width + mousePosition.x, 1);
//pixel[0] == colour of the item the mouse is over. You can now look this up in a dictionary<Color, item>
You should be careful not to stall the pipeline by doing this (causing the CPU to wait for the GPU to render things). The best way to do this is to swap between 2 render targets, and always GetData from the render target you used last frame, this means the data is a frame out of date, but no human has fast enough reactions to notice.
Addendum in response to your comment.
To assign a unique colour to each object, simply increment a byte for each object. When that byte overflows, increment another, and when that one overflows increment another; Then you can use those three bytes as Red, Green and Blue. Remeber to keep alpha at max value, you don't want any see through objects!
To resolve the backbuffer is slightly changed in XNA4. Now you must render to a rendertarget and resolve that. To do this is pretty simple, and outlined by Shawn Hargreaves here
I've been producing this 2d tile-based game engine to be used in several projects.
I have a class called "ScreenObject" which is mainly composed of a
Dictionary<Point, Tile>
The Point key is to show where to render the Tile on the screen, and the Tile contains one or more textures to be drawn at that point. This ScreenObject is where the tiles will be modified, deleted, added, etc..
My original method of drawing the tiles in the testing I've done was to iterate through the ScreenObject and draw each quad at each location separately. From what I've read, this is a massive waste of resources. It wasn't horribly slow in the testing, but after I've completed the animation classes and effect classes, I'm sure it would be extremely slow.
And one last thing, if you wouldn't mind..
As I said before, the Tile class can contain multiple textures to be drawn at the Point location on the screen.
I recognize possibly two options for me here. Either add a quad at that location for each texture to be drawn, or, somehow.. use a multiple texture for the same quad (if it's possible). Even if each tile contained one texture only, that would be 64 quads to be drawn on the screen. Most of the tiles will contain 2-5 textures, so the number of total quads would increase dramatically with this method. Would it be feasible to add a quad for each new texture, or am I ignoring a better way to do this?
I'd suspect using a Dictionary would be slower than just using a straight array. If your world consists of 512x512 tiles then you allocate an array 512x512 (262144) in length. YTou can get any given tile in that array by using "array[x + (y * 512)]".
You know how many tiles there are so store an array where each either points to the tile at that position or has an index to the tile in a list (you will likely save memory this way as you can probably keep all your tiles in an array less than 65536, or maybe even 256, in size and thus store the index as a 16-bit.
You then find the area of your array you want to render. To do this optimally you want to avoid switching textures as much as possible. So first thing I'd check to see how big your tiles are I'd then try and combine as many of the texture into 1 big texture. Then set your UVs to sample a sub portion of this large texture. This way you should be able to limit the number of textures in use with a few big textures. Of course you will probably find that a given tile set (lets say rocky ground, for example) will use the same groups of textures. There may also be some blending across to grass somewhere so it may well be worth holding the grass textures in BOTH big texture to avoid doing so many texture swaps. ie sacrifice video memory for speed.
You then iterate over the visible portion of the array and draw all the tiles using texture 1 and then all tiles using texture 2 and so on.
I would recommend to use single VAO object composed from triangles + indices. Calculate position on client side and just update it on each frame (streaming).
Use texture atlas to store everything in single texture (to avoid switching states). You can use texture packer tool.
Render in one shot (if you have depth buffer enabled). Otherwise render first objects that opaque and then render everything that should be blended.