I'm trying to create tiled terrain in 3D with XNA. I checked tutorials on how to doit(Riemers and Allens). Allens tutorial has an exact result I want to achieve, however I'm not sure about performance - it seems he is using single quadrilateral to draw all terrain and process it with pixel shader, it means - whole terrain will be processed each frame.
Currently I'm drawing a quadrilateral for each tile(Example) - it allows to draw visible tiles only, but it also means that much more verticies need to be processed in each frame and a lot of "DrawIndexedPrimitives" is called.
Am I doing it right or Allens way is faster? Is there a way to do tiled terrain better?
Thanks.
Totally depends on your terrain complexity and size. Typically, you will have terrain tiles with more than one quad/tile (for instance, a tile could consist of 4096 triangles) and then displace the vertices to get the terrain you want. Still, each tile will be a indexed primitive, but a single draw call will result in lots of triangles and a larger part of the terrain. Taking this idea further, you can make the tiles in the distance larger so you don't get too much detail (look for quad-tree/clipmap based terrain approaches; you'll get something like this: http://twitpic.com/89y5kn.)
Alternatively, if you can displace in the vertex shader, you can use instancing to further reduce the amount of draw calls. Per-instance, you pass the UV coordinates into your heighfield and the world-space position and then you again render high-resolution tiles, but now you may wind up with a single draw call for the whole terrain.
For a small game, you might want to generate only a few high-resolution tiles (65k triangles or so) and then frustum-cull them. That gives you a large terrain easily and is still manageable; but this definitely doesn't scale too well :) Depends on your needs.
For the texture tiles, you can also use a low-resolution index texture and do the lookup into an atlas per-pixel or just store the indices in the vertex buffer and interpolate them (this is very common: Store 4 weights per vertex and use it to look up into four different textures.)
Related
I'm making a 2D platform game engine with C# and MonoGame that uses floating point numbers for all of its maths. It works well so far, however I'd like to have the option of using the engine for a retro-style pixel art game, which is obviously best done with integer maths. Is there a simple way to achieve this?
The simplest method I can come up with is to do all the calculations with floating point numbers, but then when I draw each sprite, I round the position to the nearest multiple of the scale of the pixel art (for example, to the nearest 5 pixels for pixel art that is scaled 5x). This functions, but the movement of the player character on the screen doesn't feel smooth.
I've tried rounding the player position itself each time I update it, but this breaks my collision detection, causing the player to be stuck on the floor.
Maybe there's a standard way people achieve a solution?
Thanks :)
Apologies for resurrecting an ancient question, but I think a very simple way to do this for both programmer and hardware using GPU triangle rasterization (I'm assuming you're using a GPU pipeline, as this is trivial otherwise) that most directly simulates the look and feel of old hardware rendering at 200p or so is just render your entire game to an offscreen texture that is that actual 200p resolution and perform your entire game logic, including collision detection, at that resolution. You can shift all the coordinates by half a pixel which, combined with nearest neighbor sampling, should get them to plot precisely at a desired pixel if you have to work in floating point.
Then just draw a rectangle with the offscreen texture to the screen scaled to the full display resolution using nearest neighbor sampling and integer-sized scalars (2x, 3x, 5x, etc). That should be so much simpler than scaling each individual sprite and tile.
This is assuming you want a full retro look and feel where you can't draw things at what would normally be sub-pixel positions (1 pixel increments after scaling 5x instead of 5 pixel increments, or even sub-pixel at full resolution). If you want something that feels more modern where the scaled up art would be able to transform (move, rotate, scale) and animate in single-pixel increments or even sub-pixel with floating point, then you do need to scale up every individual sprite and tile. I don't think that would feel so retro and low-res though, more like very modern with scaled up blocky pixel art. Operating at the original low resolution tends to impact not just the look of the game but the feel as well.
I am creating realtime scene in XNA, it is 2D using sprites only (rendered on quads, standard spritebatch with alpha map on sprites). I would like to create create simply lens flare, actually only occlusion around light source (I donĀ“t need direction to center of camera to offset multiple sprites for lens flare, etc.) Only thing I basically need is to calculate how many pixels from light source sprite (small star) are rendered and according to it set scale of lens flare sprite (so scale 0 if sprite there are not visible pixels from relevant sprite).
I know how to do it in 3D, I read through this and tested few things:
http://my.safaribooksonline.com/book/programming/game-programming/9781849691987/1dot-applying-special-effects/id286698039
I would like to ask what is best and cheapest way to do it in 2D scene (counting how many pixels of sprite were rendered / occluded with per pixel precision or something comparable).
I know also stencil buffer could help but I am not sure how to applicate in this case.
Okay, two ways how to solve it, either kinda old school approach, using stencil to calculate count of occluded pixels and scale sprites of lens flare according to it.
Other way: modern approach, use screen space lens flare, isolate bright pixels (I recommend HDR rendering pipeline and use values of brightness above 1.0 to generate lens flares, but it depends on scene average and maximum) and generate ghosts, like so:
https://www.youtube.com/watch?v=_A0nKfzbs80&list=UUywPlxpmCZtuqOs6_bZEG9A
Is it possible to retrieve the texture coordinates of an object, for example through hittesting?
As an example: I use a 1920x1080 texture on a simple plane, and I want to get the coordinates 1920, 1080 if I click in the right bottom. (The model is in reality slightly more complex, so trying to calculate the position via math isn't as easy)
When math does not work for some reasons, I used to do the following graphic hit-test: assign unique colors to each texel of your plane, then do one frame rendering to an offscreen surface with lighthing and effects disabled, then read pixel color under the cursor and translate its value back to coordinates. This is quite efficient on complex models when you don't need to do such lookups too often (say, games), because reading pixels back will stop graphics hardware pipeline and drain the performance. Also, this potentially would work with any projections: ortho or perspective.
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'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.