• Advertisement

Archived

This topic is now archived and is closed to further replies.

Ultimate terrain texturing thread

This topic is 4969 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Heyas all, Well, I'm writing this thread as I'm pretty annoyed with my current terrain texturing. It looks pretty cool, but I'm sure it could be better, and more efficient. To kick off the thread, here is a current picture (more recent than in the terrain screenshot thread) of my terrain @ 1024x768 resolution, 16 bit colour. As you can see, I'm using Charles Blooms' splatting method. That is 8x8 chunks of 33x33 vertices. Each chunk has a splat struct for each texture layer, consisting of an index buffer for that texture layer and an alpha texture. Each quad is assigned a texture layer, then the alpha map is generated based on the weightings of neighbouring elements. Finally an index buffer is generated for each texture layer that encompasses all quads of a given texture layer, and all quads adjacent to those (for blending). Now this is all well and good, looks pretty cool, but there are a few cons which I will go into detail about now. The more textures you use, the more splat alpha maps you need, though in theory you could have 9 alpha textures for every quad as that would cater for the texture from the central element and its neighbours, however, that is still a hefty nine 64x64 textures for every chunk. (which is 9Mb of alpha textures alone in my current setup). I would like to be able to increase, or remove the limit on the number of textures. This is not a necessity though, as I know vegetation will detract from imperfect terrain texturing, though it would be nice to have scenes with little vegetation looking just as good. View distance is also a pain in the butt. Working at a scale of 1 unit = 2 meters. 2 units per quad. That makes my terrain currently 2x2x32x8 = 1024 meters. As it is streamed, this will have to be halved as the player will effectively be in the middle of the terrain, making the view distance roughly 0.5 km. Now if I wish to increase the view distance, memory consumption will increase drastically, and most likely performance will decrease drastically as well, especially bearing in mind that to keep splatting looking correct, it may be fiddly to implement LOD schemes. Memory consumption as it currently stands for 256x256 vert terrain buffer (with some duplicate verts): Alpha maps for unlimited textures - 9Mb Vertex buffer @ 32 Bytes per vertex - 4.26 Mb (1 system copy for ray testing) say ten 512x512 texture layers (32 bit colour) - 10 Mb Index Buffers - 0.75 Megs Well, I wont go into every tiny detail, but thats a total of roughly 24 megs, not even including several necessary other components. Now, that's not bad, but consider this. To increase my view distance from 0.5 Km to 4Km, it requires 64 times the amount of data I currently have - 24x64 = 1536 megs!! So as you can see, it's looking unfeasible to increase the size by any great amount. But I don't know, is 0.5 Km a bad size? I'm not sure. So what I'm looking for is possibly a way to cut on memory consumption (I only wish it were possible to store all the alpha values in a single texture or something like that). Another issue is that of texture tiling. If I have the splat textures tiling very frequently, the resolution looks amazing, but the texture looks increasingly worse due to it becoming more apparent that it is tiled. The only way to combat this is to make textures very bland and smoothe, which defies the point of trying to get more detail out of it. You can use Yanns suggestion of tiling the texture very frequently, then tiling it infrequently such that it becomes its own detail texture, but this has a bit of a side effect of sometimes making the terrain appear discoloured when you want it to be more regular. Now on top of all this, my frames per second is a big issue. Currently, at 800x600 resolution, I max out at about 65 FPS, which is limited by the fact I'm using an MFC window with message loop (not refresh rate), and at worst case I can be down to 20-30 FPS ish. I don't even want to consider FPS impact upon increasing view distance!! Now this isn't bad for the level of detail I'm achieving, but it could be better I'm sure. So what I want to achieve is as follows: Possible pixel / vertex shader use - but with a fallback for pre-GF3 cards that still looks reasonable. Lower memory consumption Increase framerate Possibly increase to 1024x1024 texture layers Reduce tiled appearance Increase view distance All that and I still have lighting to implement (though I have temporary slope base vertex lighting, which looks ok, but nothing special), and I'd like to be able to acheieve framerates that would allow me to actually use this terrain in a game, I'm not looking to make this a pure tech-demo. Is it possible to achieve this? I think I may have summed up 90% of the terrain texturing posts on this forum in one, so it'd be nice to see if we can't beat my last thread on creating detailed terrain under sever limitations (hugely popular reference due to Yann!). PS I'm using DirectX 8, with GeForce FX 5700LE 256 Mb card, 256 Mb RAM and Athlon 2400 processor, though looking to make something that would still work on something like: 1Ghz processor, Geforce 4+ 64mB VRAM, 256+ megs RAM Cheers, Steve AKA Mephs [edited by - Mephs on June 10, 2004 1:31:32 PM]

Share this post


Link to post
Share on other sites
Advertisement
If you''re trying to make a practical engine for a game that runs on low-end hardware, you''ll have to set your goals lower. Even the latest high-end games don''t have unlimited textures on terrain and all that.

Techniques like those discussed in the "severe limitations" thread are probably more common... Eg. pack four detail textures into one RGBA texture (I think Yann talked about something like this), use a larger RGBA at 1 texel/vertex to blend between them and multiply the whole thing with another big texture that has the terrain color in it. You can do this in one pass and still have some fillrate left for vegetation and sky rendering.

Ultimately, art rather than tech determines how "good" your terrain looks. Your screenshot has three different textures that don''t fit together all that well, and they''re not arranged in an aesthetically pleasing way. The same tech in the hands of a good artist (= better textures, better heightmap..) would probably result in something a lot more interesting.

Even programmatically there''s a bunch of things you can do, like texturing based on slope rather than just altitude. Definitely add lighting and fog. Experiment with your noise generator too; try non-linear noise scale to exaggerate mountain peaks, blend multiple noise generators for different terrain types and so on.

(Minor optimization note: if you switch to a normal map rather than vertex normals you''ll save 8 bytes per vertex)

Share this post


Link to post
Share on other sites
OK, some minor discrepancies to point out here first off.

Vertices do not include normals at present. Texture blending can be edited realtime, so auto-generation isn''t a big worry (I know it looks wrong at the moment, but that''s simply because I have been focusing elsewhere than auto-generation.)

On the other hand, I think you may be correct in saying that I need to set my goals lower, however, even with that in mind there are some things I consider possible to do, but that I perhaps haven''t done them in the most efficient way, as I have seen several great looking terrain engines that outclass my own by a fair amount even without vegetation(FarCry, Realms of Torment/Krel/whatever it''s now called,Everquest 2, etc etc) OK I know I just reeled off a list of big names that are hard to compare to, but I know that it''s possible to improve on what I have, and I''m just trying to work out how, even if I don''t actually implement them, it would be nice to have the knowledge.

Unlimited texture numbers as I mentioned, is not necessary but desired (by unlimited I really just mean a large enough amount that an artist would have a lot of freedom). View distance is something I''m pretty sure I can increase.

Texturing the terrain using a large texture and several detail textures does not appeal. For starters you''re limited to four textures (which get boring quickly). Secondly, even if you work more into the equation somehow, the detail at a distance may look ok, but monochrome detail textures means that up close, you don''t really see anything in the way of real detail compared to what you do with splatting. A monochrome detail texture over a color map simply doesn''t look as detailed as a normal high frequency texture.

Anyhoo I could go on rambling all day, but I''ve gotta get back to work on it... have a few ideas to try and implement and what have you!

Cheers,

Steve AKA Mephs

Share this post


Link to post
Share on other sites
Hi,

Just a few comments make of them what you will.

Firstly i''m rather surprised by your splat alpha texture size, using 9x64x64 per chunk is quite extreme to me. In my own versions i''ve gone for much less resolution actualy to be one pixel per vertex. So in your example that would be a single 32x32 texture per chunk. As you can see vastly cutting down your texture memory requirements.

However I can fully appricate that you''d want more resolution than that and maybe should with your 4m sq quads. As to how much thats for you to decide and the purpose of the game. If on foot then I would have thought a splat 0.5m sq would be sufficent (requiring then a 256x256 alpha texture per chunk), if driving then you might get away with 32x32 or 64x64.

As to LOD I wouldn''t have thought this would be a great problem as the splats are done via textures and being chunked you can just have several index LODs to switch between for view distance. I think there was a good paper/pdf by someone at Muckyfoot about chunked LOD i''m sure it will turn up with a search in google.

Finally concerning tiling, this is a problem you''ll always face, but I seam to remember a solution involving using different tiling for different textures and overlaying two similar types of textures. That is for say a rocky path which might show tiling, have two types of rock and mix them to form the path. If they have different tiling frequency you should be able to disguise the tiling effect.

You may also want to look up an article (on gamasultra I think) about using the High band pass to reduce the prominance of tiled elements.

Share this post


Link to post
Share on other sites
I don''t have Far Cry so I''m not too familiar with the engine... But from what I''ve read, the level editor generates a huge texture (color+lightmap) to cover the entire map just like Battlefield, and detail textures are used when up close. That''s what the screenshots look like too. Are you sure it does something more advanced than that?

Share this post


Link to post
Share on other sites
I think it''s safe to assume that at least half (if not more) of gamers within the next year or so will possess a shader-capable card.

Using shaders, you can, effectively, create an "unlimited" variety in your textures (or close to it). This is only going to become more true as time passes, as I doubt any hardware will be released (well, short of those shitty intel boards that they stick in low end computers) in the near future that won''t support it (or some evolution thereof).

Personally, I''m going a wholly different route. Traditional terrain rendering methods are simply not very good for realistic outdoor simulations. Reality doesn''t allow for only concave geometry, for example. Lets not even get into the requirements for having a wholly different rendering technique for objects that aren''t part of the terrain itself (e.g. buildings).

Share this post


Link to post
Share on other sites
Heyas,

Okay, @ Etnu first as your reply most intrigues me. Do you have any screenshots of your method? I like the sounds of your method detailed in another recent thread with the idea of ''materials'' and such like. I''d love to see how it looks if you have anything fully working yet? I can host an image if you need it?

As for Farcry, it may well use a single base texture, but I recognise that it has a failing in memory consumption, in that the method it uses is likely unfeasible for large scale terrains. Say a base texture is a 32 bit 1024x1024 texture over a 1024x1024 heightmap, and you have 64 heightmaps(64 x 1024x1024x32-bit = 256 megs). Thats just for one pretty large sized map, so an RPG game as I hope to make is going to be struggling with that kind of consumption. So anyhoo, I accept it may not be a very relevant example, as it''s really built for a different purpose than most outdoor engines (small FPS levels rather than vast areas).

As for 64x64 alpha maps, this is as Charles suggests, and I think the extra bit fo resolution for the alpha maps make enough of a difference to warrant having them that size (4 texels per land element offers a blend that is a bit more finely controllable(sp?). Chunked LoD, hmm, something possibly worthwhile looking into.... I''ll et back to you on that one, but thanks!

Coming back round to Etnu, I''m convinced you''re correct aswell, though I have yet to implement any form of shaders in my terrain, I do think that it is the way forward, and the answer to several of my problems. I get the rough impression, that it will make it simpler and more efficient to render blending effects through a shader than through standard means.

Based on feedback thus far, here are my new goals:

1. Implement shader system,
2. Slightly increase view distance,
3. Reduce memory consumption,
4. Increase framerate,
5. Stick with around 5 textures per map (if FarCry can look stunning with 3 or 4 or so textures variations or whatever,
then it can''t be too important)
6. Reduce tiled appearance.

To achieve the above I will

1. Learn shader programming!! (e.g. I can load less alpha maps if I fade them out and turn off after a given distance, which I think could be done in a vertex shader that generates vertex alpha as a function of distance from viewer?)

2. Look at reducing per-chunk memory cost

3. As above, but also optimise my terrain buffer to a circular buffer rather than a square one, possibly look at streamlining existing methods to reduce consumption

4. I''m actually stumped on this. Though currently I use 2 passes per splat texture, which could be a single pass on my hardware (keeping the 2 pass option for backward compatibility). Don''t think it would make too huge a difference though, as effectively it''s rendering the same gemoetry over and over which shouldn''t be too bad? Possibly look at chunked LoD as suggested.

5. ''nuff said.

6. Vertex shader should manage this by implementing alpha map fade out, I''m still not 100% convinced by the multiple tiling frequency method (it just doesn''t look quite right). This was a major unrealised obstacle, I couldn''t work out why my terrain didn''t fade to base map in the distance, but have realised it''s due to not being able to have any real control over mipmap fadeout, and needs to be finely controlled in vertex alpha.

Hmm, any further suggestions?

Thanks for the input thus far though,

Steve

Share this post


Link to post
Share on other sites
Yeah, I'm no artist, but I did a few shots to demo stuff.

I suck at shaders, too (my first project using them), but the flexibility of the system means that I can always get other people to make my shaders for me :-)

Here are two shots of the exact same place on a map. The first has my "terrain" material applied. The terrain "material" isn't a d3d material. It's more like a real-world material. It consists of a vertex shader, a pixel shader, textures (3 in this case), and various properties used for setting render states and the like.



The second "material" ('dead grass') has no shaders (defaults to using FVF codes), 1 texture, and lets d3d do the lighting.



These actually use the same texture for the grass (the "terrain" shader applies a modifier to reduce the blue & red color channels in the first shot to make the grass greener).

I'm still working on my level editor though, so I haven't been able to do the really cool stuff that the engine allows, like buildings, water, caves, and the like.

One other thing neither of those shots show is how the material system can be used on EVERYTHING in game - even the interface itself.




[edited by - Etnu on June 11, 2004 2:43:27 AM]

Share this post


Link to post
Share on other sites
One other thing of note that neither shot shows is that every "face" in the map can have a different material. A face is usually a single triangle, but it doesn''t have to be. Faces don''t have vertices of their own, but rather indexes into a large index buffer (that way identical vertices can be reused). Faces are concocted when the map is loaded into several arrays of indices (1 for each material used in that particular node). Each frame, the nodes are tested for visibility first, and then they add their indices into a dynamic buffer for each material they contain (sorted by material).

I''m currently only using 1 vertex buffer (static) and 1 index buffer (dynamic) for the whole map, but I''m considering having individual buffers for each node of the octree for a performance boost, though I don''t think it''s quite necessary quite yet as I''m still getting about 300fps on a map with about 1.5 million faces, and I don''t think I''ll have too many more polys than that, so I''ve got plenty of leeway for character models and such.

Share this post


Link to post
Share on other sites
Four things that come to mind concerning memory consumption:

1. Do you really need RGBA textures to use just the alpha channel ? Using alpha-only textures you would need ~2.25 MB, instead of 9 MB.
2. Do you really need all textures _per chunk_ ? If you limit each chunk to being affected by 4 textures at max you are down to ~1 MB of alpha maps with your current mapsize.
3. Try texture compression, if you aren''t using it yet.
4. How does your vertex struct look ? 32 Bytes per Vertex, without normals, seems a bit big to me.

Got a few more things to say, but for now I''m already out of time.

So far,
Michael

Share this post


Link to post
Share on other sites
Okay, got to be quick as I''m at work, so Etnu, nice to see some screen shots, but I will come back to your stuff after work if you can bear with me!!

@ Eternal - As far as I am aware, DirectX doesn''t support alpha only textures. IIRC, there is an D3DFMT_A8 or something similar, but I''m pretty sure I tried it, found it wouldn''t work as expected, then read somewhere that it is unsupported by hardware (in the splatting paper I think). It would be damn handy if you could do that though!! Texture compression is a possibility, but am I right in saying that it only affects the storage size of texture on disk, and not hardware, or would it speed up using the texture on hardware also???

My vertex structure is a position, two texture co-ordinate sets and a diffuse colour, which are all pretty necessary (and should be efficient as it is 32-bit aligned IIRC).

I''ve had afew more ideas to make my ideas more feasible. I''m going to introduce a view distance setting ni my editor so you can scale the view to get the speed you desire. I also think that perhaps I''m not rendering too much geometry, but rather that I''m fill-rate limited. So, I''m looking at organising terrain chunks closest to farthest to reduce overdraw. Possibly look at shrinking textures (see how it affects FPS). I''m not sure about chunked LoD now I''ve read up on it, as storage overhead is supposedly quite high, and maps are already going to be quite large, and I''d like to think if I add multiplayer capability, that maps may be a reasonable size so as to be ownloadable. Anyhoo, gotta dash now for the rest of my break..... back later,

Cheers,

Steve

Share this post


Link to post
Share on other sites
quote:
Original post by Mephs
As far as I am aware, DirectX doesn't support alpha only textures.


I doubt DX is missing an important function like alpha textures. I'm not working with DX so someone else might wnat to fill the details about this.

quote:
Original post by Mephs
Texture compression is a possibility, but am I right in saying that it only affects the storage size of texture on disk, and not hardware, or would it speed up using the texture on hardware also???


Textures can be compressed in video memory. Loop up DDS/DXTC. Textures are either loaded from compressed format (DDS) directly into video memory or compressed by driver and then sent to video memory. Then they are uncompressed when texel from texture is needed.

quote:
Original post by Mephs
My vertex structure is a position, two texture co-ordinate sets and a diffuse colour, which are all pretty necessary (and should be efficient as it is 32-bit aligned IIRC).


Do you need texture coordinats? They can usualy be calculated in VP (with single instruction even) from position. This saves you 16 bytes.

quote:
Original post by Mephs
I'm not sure about chunked LoD now I've read up on it, as storage overhead is supposedly quite high, and maps are already going to be quite large, and I'd like to think if I add multiplayer capability, that maps may be a reasonable size so as to be ownloadable.

What kind of LOD are you using now? Personaly I think modified chunked lod or geometry clipmaps are one of the best choices right now.


You should never let your fears become the boundaries of your dreams.

[edited by - _DarkWIng_ on June 11, 2004 8:06:31 AM]

Share this post


Link to post
Share on other sites
quote:
Texture compression is a possibility, but am I right in saying that it only affects the storage size of texture on disk, and not hardware, or would it speed up using the texture on hardware also???


There are two kinds of compression. The usual, like .JPG, will save a lot of diskspace, but the Texture.FromFile() will expand it into uncompressed format when loading.
Then there is the kind of compression supported by the hardware, DXTC 1/3/5. Textures compressed using this method are smaller on disk, but will be loaded and stored on the card in this compressed format, saving memory.

Share this post


Link to post
Share on other sites
quote:

I doubt DX is missing an important function like alpha textures. I'm not working with DX so someone else might wnat to fill the details about this.



Sorry.. but Mephs is in the right way
from DirectX manual ( 9.b summer update)
quote:

Note that DXTex does not currently support textures with surface formats that do not contain at least an R, G, and B texture (such as D3DFMT_G16R16 and D3DFMT_A8), although D3DX can load and save such textures in DDS format.



there are D3DFMT_A4R4G4B4 and D3DFMT_A8R3G3B2 .. they use 18bit instead of 32, but have very many colors limitation

[edited by - BlueChip on June 11, 2004 11:03:23 AM]

Share this post


Link to post
Share on other sites
Uhm, if you have A4B4G4R4, you have 16 bits to work with -> why not use that as an "alpha" texture? (concoct the values)

Well, I guess I''m assuming that you''re working with pixel shaders. I always forget how limited the fixed-function pipe is.

Share this post


Link to post
Share on other sites

I also implemented splatting for my terrain rendering, using alpha maps to blend N different texture layers onto the terrain. The basic method I used is the same: mix a texture and alpha map for a given layer, and accumulate the different layers using multipass. I preprocess the whole map beforehand so I can kinda cheat on some stuff. Things I do:

1. Chunked LOD manages mesh detail. For distant chunks at a low-resolution, I used a pre-built vague diffuse texture instead of splatting, since the user can''t tell the difference anyway at that distance. I need to add in fading though, since the switch to splatting at closer distances is pretty evident.

2. I have N different texture layers for a given terrain, where N<256. For each chunk of the terrain, I figure out which detail textures are actually used in that chunk, and only do passes for those textures. So if a chunk doesn''t have any "rock" texture on it I skip the pass that draws the rock texture. Also, the alpha map for unused detail textures is all 0''s obviously so I don''t generate them. This saves me some passes and allows me to have a lot of different layers as long as the artist doesn''t stick 200 different layers on every chunk...

3. I also tried calculating minimum triangle meshes for each detail texture in order to reduce fill requirements, since it seems like drawing the whole chunk for every pass is a waste. For example, if you just have a small strip of grass on the chunk, then during the draw pass to "splat" on grass you only draw triangles along that strip where the grass is applied instead of drawing the (mostly blank) mesh for the whole chunk. This kinda successfully reduces my fill rate, but since I need a larger index buffer and use triangle meshes instead of strips I don''t see a huge improvement.

4. I tried using alpha-only textures in DX and couldn''t get them to work, as Bluechip noted they wouldn''t. Argh. I also tried using compressed DXTn textures for my alpha maps, only to find that my old GeForce2 won''t store them compressed in video memory. So I''m using a 16-bit texture for alpha maps right now.

I think to avoid tiling I''ll need to either use multiple detail textures (i.e., have two or three actual grass textures and dither them together wherever I have grass) or pick really good textures to begin with. I could store three different grass textures in memory, but I also considered using the same texture at a different scale to give different-looking textures without using more texture memory.

I also still need to sort by texture and shader state. Right now I draw all the layers for a chunk and go on to the next chunk, so I basically flip through all the needed textures several times. I should probably bind one texture layer and render all the chunks using that layer. However, I would still have to bind in the alpha maps for each chunk as well as the vertex/index buffers for that chunk, so I''m not convinced that I win anything.

I would also like to use a pixel shader to mix 4 detail textures at once using the RGBA channels of a weight texture, but that will have to wait until I upgrade my video card.

Share this post


Link to post
Share on other sites
Using vertex + pixel shaders, you can actually calculate the blend factors at runtime, then pass them to your pixel shader as texture coordinates (8 blending factors will fit in 2 texture coordinate sets).

In the image above, for example, I do that. I also deform the geometry slightly to give the impression that the rocky areas are actually raised up from the surface (since, you know...rocks that stick out of the grass are usually taller than the grass :-p)

The real advantage is that you can control everything within your shader. If you decide you don''t like how the terrain looks further down the road, you simply have users download a new shader. Also, since it''s working real time, you can use it to effect dynamic geometry (such as if a user blows a hole in the side of a mountain).

All the more reason why shaders are so awesome.

Obviously you can''t do EVERYTHING within a shader, but they can certainly do things like this (amongst other things).

Share this post


Link to post
Share on other sites
Hi all,

Maybe you are confusing things a little with DX and A8 format.

First, Bluechip, DXTex is just a small application (smaller than Paint I guess) that allows you to view textures and cometimes save it in other format. It don''t support MANY file formats. DXTex is not part of the core D3D dll, just a separate app.

DX in fact supports A8 files with the D3DFMT_A8 format. It can be used as an alpha channel if you set it in a texture stage.

The problem is not DX supporting it but video cards. Some time ago, many card manufactures found that palletized textures (D3DFMT_P8) were just more a problem than a solution and supporting them just added too much complication for the chip architecture. So they just dropped all the 8 bit support, including A8 for the 3D pipeline. You can find if your card supports 8 bit textures just querying, but I guess it will become a more and more scarce feature in future video hardware.

Luck!
Guimo

Share this post


Link to post
Share on other sites
Ok, I''ve sorted point number 4 with the following optimisations, and now enjoy a constant, solid 65 FPS (maximum limit using MFC at the moment)

Front to back sorted chunks to reduce overdraw,
Rearranged the rendering routine to reduce texture switching in favour of more vertex buffer switching, the payoff seems huge!


I may also implement some kind of quadtree to allow for larger terrain as I''ve worked with them before (unlike LoD), but I''m still not sure about LoD, I think I may manage without it if I can keep my framerate up with other simpler to implement methods. I think I''d like to implement vertex shader texture co-ordinate generation, as that would reduce memory consumption and save memory bandwidth to boot! Plus, while learning shaders I can implement alpha fadeout in the vertices as well! I think relying on vertex shaders is safe as even older cards support them IIRC. I will look into pixel shaders at some point too, but it''s less of a priority I reckon.

Anyways thanks for the help thus far, but further discussion (not just about my methods though) is welcome. I as beginning to worry my thread may not live up to its name, but I thin it''s doing nicely!

Oh and excuse me for being a dumbass.... I just realised that my 128x128 base textures to cover gaps in splat alpha blending amounts to the same memory consumption as a 1024x1024 texture, doh!!

As for the whole D3DFMT_A8 thing, that''s what I experienced... the hardware not supporting it, so thanks for the explanation Guimo.

Still have much more to cover, but i have to dash as always..... will post again later.

Cheers,

Steve

Share this post


Link to post
Share on other sites

  • Advertisement