Need guidance

Started by
19 comments, last by itz_faraz 18 years, 2 months ago
I would like to add to these since they are pretty signifigant gotchas in certain cases.

Quote:Original post by evillive2
... For instance, using texture coordinates with tile sets will greatly reduce the number of texture switches increasing your performance.



This CAN be used in certain cases but one must be aware of potential issues.

Unlike our old friend the Image Blitter, mapping part of a texture onto a quad is not nearly so precise. unless you do a direct mapping of Texels to Pixels (which means the quad cannot be scaled up) you are likely to see part of your neighboring tile 'bleeding' into your drawn image, this is ususaly due to the filtering process, the only effective way to get around this is to use a 1 (or more) translucence pixel 'gutter' around all of the images in a packed tile set, which is a large large pain.


For a little bit of perspective, I found that doing a game as image-heavy as morning's wrath was enourmously hard to make performant in a 3D API, and even now it is not very performant versus a 2D api.

Quote:Original post by evillive2
The biggest problem I have with using a 3d API is the complexity of rendering to an offscreen texture. This tends to be a pain and causes performance issues if overly used (at least for me). For the most part though, you can get away with drawing 3000-5000+ textured quads with scaling, blending and rotation in less time than 2000-4000 in something like SDL without scaling, blending and rotation.

Try looking into something like PnP Bios's hxRender library (SDL/OpneGL under the hood) or HGE's game library/engine if you don't want to do the low-low level stuff yourself. Even Irrlicht has 2d functions along with a built in GUI library. Irrlicht may be overkill for anything small but who knows what your game might grow into.

Good luck


The large issues come not when you draw 5000 textured quads, the card is very happy about doing that. The issue comes when you draw 5000 textured quads with about 50 different textures. Non-grouped renderings will cause tons of texture switches, and if you happen to be using more textures than can fit on your card, prepare to drop some serious frame-rate.

my current advice would be to keep your tile images as squares, 64x64 or whatever, and utilize a view transform to put your view into isometric.

if you can guarentee that the tiles will be 64x64 (or whatever size you choose) then you can have a number of atlases (which you might have to gutter if you need to scale) these can be generated programatically or by an artist. in this way, 64x64 tiles, a single 1024x1024 image map will give you 16x16 64x64 tiles
for your needs this may be enough and each map can have it's own 'atlas' or you can use multiple atlases, that get swaped out during map changes.

just some food for thought =D

Raymond Jacobs, Owner - Ethereal Darkness Interactive
www.EDIGames.com - EDIGamesCompany - @EDIGames

Advertisement
Thats all very informative; thank you. A little problem:

Quote:
my current advice would be to keep your tile images as squares, 64x64 or whatever, and utilize a view transform to put your view into isometric.

if you can guarentee that the tiles will be 64x64 (or whatever size you choose) then you can have a number of atlases (which you might have to gutter if you need to scale) these can be generated programatically or by an artist. in this way, 64x64 tiles, a single 1024x1024 image map will give you 16x16 64x64 tiles
for your needs this may be enough and each map can have it's own 'atlas' or you can use multiple atlases, that get swaped out during map changes.


Doesnt "64x64" sound as 2D drawing? If so, how can the view transform be utilized? I think view transform is only for 3D space where x,y,z values are in relative terms not exact pixels.

I was able to setup a nice 3D terrain with no performance issues and I had also implemented all the nice tips that you guys gave; such as single index buffer, least texture switches, using the transformation view to appear like isometric, etc., but my major problem was mouse detection. Since I was using a single index buffer, I had to use ray-picking technique (transform the current mouse cordinate into 3D and check each triangle one-by-one if mouse lies within it; using Pythagoras theorm!). You can see it was very yucky!

If I checked each tile one-by-one in ascending order (top-left of terrain to bottom-right) then if my mouse was on the top edges, it would detect/calculate very fast. But if it was near the bottom edges, my algorithm would bring down the FPS from 65 to 5!! So my poor-lil code brought my system down to its knees.

Thats why I decided to revert back to 2D and get my head absorb it completely first. I can create varying-height terrains in 2D, mouse detection is a peice of cake as it is simple calculation in 2D, now comes new problem: visibility test >> ie. to decide which tiles to draw and which not to draw. For that I used the same rotten technique; checking each quad if its visible on the screen. That again brought the speed down.

..... and THATS why Im looking for a book that shows some examples+explanations to overcome the basic terrain engine problems :)

my 3D terrain

[Edited by - itz_faraz on February 13, 2006 1:50:18 PM]
Faraz Azhar-Intel 700mhz128 MB RAMnVidia GeForce4 MX440Using DirectX 8.1 SDK, VB6
I keep track of fine offset and the top left tile. When it comes down to drawing, I know that my tiles are 64x64 (as an example) and my screen is 640x480. I can now run 10x8 (or 10x16 if iso) I pre-calculate, and only re-calculated when screen resolution changes. This way their is no need to test a tile. Setting up a view port (region, whatever) can also help quite a bit if your map only takes up a section of your screen. The last thing I do, is while I'm drawing down my 1st layer of tiles I check each "Room" for what other layers exist (objects, top tiles, splat layers, etc) and que them up for drawing. Once I complete the initial draw, go back and run my que, thus eliminating the need to run the entire screen space again.

- Jeremy
Quote:Original post by itz_faraz
my 3D terrain


Okay, clearly you have a pretty firm grasp on using D3D... the earlier suggestions of using SDL are inappropriate... nice screenshot, BTW!

While EDI recommends using non-isometric tiles and then allowing the hardware to orient them into "diamond" tiles, I'd tend to argue against this depending on what your end goal is. If you're wanting to do a "classic" isometric game that's pixel-perfect, then you'll want to avoid have the 3D hardware shear your tiles to make them isometric. You'll lose some detail due to filtering and generally not be getting the most bang for your buck. Of course, if you're wanting to have 3D terrain (like EDI's Project2) then going the texturing route is the way to go.
When you say you tested against every triangle.

Does this mean you locked the vertex buffer and read triangles from it?

if so, that is _very bad_ you should _never_ read data from hardware resources.

an alternative to this is to keep a software memory equivilent to be used in hit testing.

you can keep this data in object space, and you can take your mouse coord and transform it (using similar matrixes of what you are using to display with) from screen space back to object space, and do your test there.

Raymond Jacobs, Owner - Ethereal Darkness Interactive
www.EDIGames.com - EDIGamesCompany - @EDIGames

Quote:Original post by EDI
When you say you tested against every triangle.

Does this mean you locked the vertex buffer and read triangles from it?

if so, that is _very bad_ you should _never_ read data from hardware resources.

an alternative to this is to keep a software memory equivilent to be used in hit testing.

you can keep this data in object space, and you can take your mouse coord and transform it (using similar matrixes of what you are using to display with) from screen space back to object space, and do your test there.


Ok here's how I create my terrain:

1. I load heightmap (a grayscale bitmap picture) into an array
2. Then I setup traingles' xyz points in a D3D_LIT_VERTEX array
3. Create a vertex buffer from the above vertex array
4. I setup indices in an indices' array
5. Create an index buffer using the indices' array

And in 'each' frame render, I perform the following:

1. Set the vertex shader type (I use different types for different geometry thats why I have to reset it in everytime to draw terrain)
2. Set the texture for the terrain (D3DDev.SetTexture 0, t_grass)
3. If user wants the grids to appear on terrain (grids can be turned off) then I setup another texture at stage 1 ((D3DDev.SetTexture 1, t_grid)
4. Use SetStreamSource to set the vertex buffer stream
5. Set indices
6. DrawIndexedPrimitive using the indices' array as D3DPT_TRIANGLELIST

Since I have an array of vertices and indices, I use that array (not the buffers) to test if my mouse is within that triangle. I dont need to lock/unlock because Im not using the buffers.

Anyways folks, Ive spent about 1.5 yrs trying to accomplish a simple 3D terrain engine but Im not able to make any good out of it so Im planning to revert back to 2D drawing and get a good grip on it first; learn a few more tricks before I get on to 3D. [smile] Ive done some work in 2D, but only on flat terrain engine. I was making a variable-height-2D-terrain engine a few months back but got disasterious performance because my visibility-test code was not working well. I was testing each tile to check if it was visible, thats why I wanted a book which could show me a few tricks on how to implement a variable-height engine in 2D (or 3D even, but 2D just for now [smile]). Here's my 2D game:



PS. In my 3D terrain engine, you all can see that my whole terrain is drawn by a single buffer. It raises a problem, it will draw the whole terrain even if only a small part of the terrain is being viewed/infocus. So impossible to perform visibility-test here to reduce the rendering load. My terrain can be zoomed-in as well. Actually the screenshot is taken from the farthest away zoom. In the closest zoom only 16 tiles are visible (4 rows, 4 cols) and even in that the cpu/gpu is wasted by drawing the whole terrain. No idea what to do here [rolleyes]

[Edited by - itz_faraz on February 12, 2006 1:43:41 PM]
Faraz Azhar-Intel 700mhz128 MB RAMnVidia GeForce4 MX440Using DirectX 8.1 SDK, VB6
There is a very simple trick for mouse click detection for isometric, tile and height map based games. Determine the column where the mouse is positioned, this selects one or two strips of terrain. Then iterate through each entry in the selected column(s), from front to back and check the height of each tile. (terrain height + object height) When the mouse cursor is below the currently checked height then the tile is selected. (i count with the origo in the bottom-left corner) The front to back ordering ensures that the closest objects, that occlude others get selected first. This selection is accurate to the bounding box of the enclosed terrain and objects. A better algorithm might check the alpha map of each tile hit and on a miss continue with the next tile.

For fast tile clipping, the programmer should determine the area visible on the maximal and minimal zoom factors and interpolate between these two sizes for other zoom positions. (the general rule is if you zoom in 2x, you have to draw an erea half the width)

Viktor
With what you explained there you should be getting very good performance, unless of course you have some very very sad hardware.

if you are indeed having bad performance feel free to post the code that does what you described and I can look it over.

Raymond Jacobs, Owner - Ethereal Darkness Interactive
www.EDIGames.com - EDIGamesCompany - @EDIGames

You can also post up a Test app for others to download and run. This will give you a much better idea of where you stand on different hardware and software configs.

- Jeremy
Maybe I'm just missing something, but it sounds to me like you need to look up visibility culling, like hierarchical trees (BSP, octree, quadtree is probably most appropriate for a 2D playing field). You should probably take your vertex buffer and split it into "chunks" and use a tree to test whether or not each chunk is visible (actually, you work the other way around).

Bottom-line: do some googling on quadtrees and BSP trees.

BTW: the game looks pretty cool. Any other info on it?

This topic is closed to new replies.

Advertisement