{"action":"created","issue":{"url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended/issues/136","repository_url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended","labels_url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended/issues/136/labels{/name}","comments_url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended/issues/136/comments","events_url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended/issues/136/events","html_url":"https://github.com/craftworkgames/MonoGame.Extended/issues/136","id":139759839,"number":136,"title":"[Tiled] Rendering large maps uses a lot of memory","user":{"login":"craftworkgames","id":3201643,"avatar_url":"https://avatars.githubusercontent.com/u/3201643?v=3","gravatar_id":"","url":"https://api.github.com/users/craftworkgames","html_url":"https://github.com/craftworkgames","followers_url":"https://api.github.com/users/craftworkgames/followers","following_url":"https://api.github.com/users/craftworkgames/following{/other_user}","gists_url":"https://api.github.com/users/craftworkgames/gists{/gist_id}","starred_url":"https://api.github.com/users/craftworkgames/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/craftworkgames/subscriptions","organizations_url":"https://api.github.com/users/craftworkgames/orgs","repos_url":"https://api.github.com/users/craftworkgames/repos","events_url":"https://api.github.com/users/craftworkgames/events{/privacy}","received_events_url":"https://api.github.com/users/craftworkgames/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended/labels/bug","name":"bug","color":"fc2929"},{"url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended/labels/help%20wanted","name":"help wanted","color":"159818"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2016-03-10T02:01:09Z","updated_at":"2016-03-13T10:38:54Z","closed_at":null,"body":"![image](https://cloud.githubusercontent.com/assets/3201643/13553805/c1fd9022-e3e0-11e5-8e79-c1c6bd5c18b9.png)\r\n\r\nCurrently we are rendering each layer of the *entire* map to a render target and caching that render target in memory for future renders. This gives the best possible frame rate performance at the cost of memory.\r\n\r\nIdeally, we'd like to have the ability to use different *draw strategies* for different situations. I've had a couple of attempts at implementing this but it's more complicated than I first realized. This discussion is about what we can do about it.\r\n\r\nWe started discussing this issue in #132 but that was off topic. Here's the relevant bits.\r\n\r\n> It turns out that drawing to a render target every frame is *really* slow. With some minor tweaks I managed to get the frame rate up a *lot*.\r\n\r\n> 1. We can't get rid of the render target completely. If we do that it'll re-introduce an old bug that causes gaps between the tiles.\r\n> 2. The optimization I implemented tonight is a bit of a hack, I simply rendered the *entire* map to a render target *once* and drew that. It works, but means we have a *really* large texture loaded into the GPU. (Trading GPU memory for frame rate performance). This works on a PC but won't fly on a mobile device.\r\n> 3. Only rendering the visible part of the map isn't trivial either. I tried doing this by re-rendering to the render target every time the visible rectangle changes (each time the camera moves one whole tile) and unfortunately the rendering becomes very *jumpy*.\r\n\r\n> What we really need is a more balanced approach. Possibly rendering the map in several large *chunks* to keep the number of render target draws down and the total GPU memory at a reasonable level.\r\n\r\n> The way the map is drawn is always going to be a trade off between memory and frame rate. I don't think there's ever going to be one solution that fits all situations.\r\n\r\n> I propose that we provide a way to override the `DrawStrategy` so that people can render the map different ways in different situations. This way we can always provide a default strategy that works pretty well in most situations but can be overridden when people have different requirements.\r\n\r\n> I suspect the way you draw small maps is going to be quite different for large maps. Also, the constraints on each platform is going to be different. On a PC with a decent graphics card it seems reasonable to simply render the entire map all at once. This gives a great frame rate at the cost of some GPU memory. On a phone, the map could be split up into smaller chunks, etc.\r\n\r\n> There's also animated tiles to consider. We haven't implemented them yet, but drawing a large static map is going to be very different from drawing one with animated tiles.\r\n\r\n> @LithiumToast said:\r\n> Seamless maps where you enter the \"chunk\" size during the content pipeline phase and it just automatically splits up a map into \"chunks\"? As long as the \"chunk\" size is big enough, for 2D there should only be a maximum of 4 \"chunks\" be drawn at once (current \"chunk\" + neighbours). This would also be an effective culling technique since only the \"chunk\" size amount of tiles will ever be candidates for drawing. Further culling could be checking if the tile's screen position is with in the camera visible screen space.\r\n\r\n> I wonder if the render target technique can be avoided by locking the tile positions to the nearest integer when zooming in and out with the camera.\r\n\r\n> @craftworkgames said:\r\n> I tried this before implementing the render target approach. It's not as easy as it sounds. I don't remember the exact details but I spent a good few nights on it. I really do feel that render targets are the right approach here. Have a read of [this](https://msdn.microsoft.com/en-us/library/bb976073(v=xnagamestudio.31).aspx).\r\n\r\n> That said, there may be other strategies we can use. Perhaps the `PrimitiveBatch` will help. We could render the tiles in a single polygon mesh to make sure the triangles are properly stitched together. The same way a 3D game renders a terrain.\r\n\r\n> @LithiumToast said:\r\n> See \r\n> - http://stackoverflow.com/questions/2226812/xna-tearing-when-doing-2d-camera-transformations > - http://gamedev.stackexchange.com/questions/25117/why-are-there-lines-in-between-my-tiles\r\n> - http://gamedev.stackexchange.com/questions/25063/how-do-i-clear-up-artifacts-between-aligned-faces-when-using-aa-in-xna-4-0\r\n\r\n> One suggestion is to use sample state `PointClamp` or `LinearClamp`.\r\n\r\n> `PrimitiveBatch` is not the best way to draw static meshes; it's meant more for dynamic geometry. Using a static `VertexBuffer` is probably the right way to draw tiles. If tiles are to change frequently, like say a character cutting grass in a field, perhaps an object in the object layer is more suitable.\r\n\r\n> @craftworkgames said:\r\n>  I've already tried different clamping modes. It's not as simple as that. Besides, the sprite batch is passed into the map draw function, we don't control these parameters within the map drawing code itself (unless we are drawing to a render target).\r\n"},"comment":{"url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended/issues/comments/195931173","html_url":"https://github.com/craftworkgames/MonoGame.Extended/issues/136#issuecomment-195931173","issue_url":"https://api.github.com/repos/craftworkgames/MonoGame.Extended/issues/136","id":195931173,"user":{"login":"craftworkgames","id":3201643,"avatar_url":"https://avatars.githubusercontent.com/u/3201643?v=3","gravatar_id":"","url":"https://api.github.com/users/craftworkgames","html_url":"https://github.com/craftworkgames","followers_url":"https://api.github.com/users/craftworkgames/followers","following_url":"https://api.github.com/users/craftworkgames/following{/other_user}","gists_url":"https://api.github.com/users/craftworkgames/gists{/gist_id}","starred_url":"https://api.github.com/users/craftworkgames/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/craftworkgames/subscriptions","organizations_url":"https://api.github.com/users/craftworkgames/orgs","repos_url":"https://api.github.com/users/craftworkgames/repos","events_url":"https://api.github.com/users/craftworkgames/events{/privacy}","received_events_url":"https://api.github.com/users/craftworkgames/received_events","type":"User","site_admin":false},"created_at":"2016-03-13T10:38:54Z","updated_at":"2016-03-13T10:38:54Z","body":"> The best MonoGame.Ex can provide is just the pieces of software people can choose to use, or not use, to build their game.\r\n\r\nYep, that's pretty much it. MG.Ex is intended to help you build your games faster by providing one possible implementation of the features you might need. For a lot of games this will be more than enough. It lowers the need to roll your own everything.\r\n\r\nOf course, it's not going to cover every possible scenario. Sometimes you'll still want to roll your own bits for the specific needs of your game. That's one of the benefits of being open source. If you need to make changes you can fork the project or just copy and paste the bits you want.\r\n\r\nAs for this particular issue, it really boils down to the limitations of using render targets and sprite batches. We might have to come up with a different way to render the map. Maybe by using a polygon mesh instead of rendering every tile a single sprite and trying to stitch them together at the edges.\r\n\r\nI'm not really worried about this issue. I'm certain it can be solved. It's just not going to be a simple tweak to the existing implementation."}}