More splatting questions

Jon

03-11-2005 19:55:32

Splitting this off from the "splatting7" thread.



height[0]= 0
height[1]= Material heights[0]
height[2]= Material heights[1]
height[4]= maxTerrainheight


Thanks, I understand now and have played around with the cfg settings a bit. There are a couple of things I don't quite like about the way the splatting is done, so I'd like to check if there is a way to correct these before I dive in and make my own PagingLandScapeTexture subclass (although I'm dieing to give that a shot :D )

Before I jump into the list, I'd like to point out that my experiments were made with my own terrain data (not any of the distributed ones).

1. Sometimes splatting occurs where it shouldn't. By that I mean a cliff next to water has the water texture splatted a ways up the side of the cliff. Certainly the way splatting is supposed to work, but not what I wanted here. In this case an abrupt transition is desired. Certain textures like water don't seem to splat as well as grass/snow/sand.

2. Sometimes texture assignments shouldn't be based on height, but on (x,y) coordinate, or on slope (I'd love for the cliff to have a rock texture).
While slope isn't an attribute of a vertex, a polygon between vertices does get textured.

Now I understand that I could create a texture file which covered the entire heightmap, and what I'd like to do is a varient of this. What I don't want to do is to replicate the texture data in high resolution, or have a low resolution texture map applied to the terrain. (What I mean by this might be clear below).

So my ideal Texture class would process an texture map corresponding to the heightmap, where each coordinate would identify the desired texture and whether splatting was permitted.

If a vertex was not on a texture boundary, the specified texture would be used (i.e. an index of 1 would mean texture 1, which might mean rock.png).

If a vertext is on a texture boundary, and splatting is permitted, interpolation is performed as it is currently. If splatting is not permitted, the texture is applied as if the vertex was not on a boundary.

This would allow me to preprocess a heightmap and generate texture assignments offline. I think this would give me enough control over texture assignments :wink:

So the big question: are there tools to do this already in the plugin, or should I write my own?

PS: I think I'll finally have the time to go do a detailed study of the code. These last few days I've been busy with a couple of big problems not related to Ogre, but I think I have things under control now.

tuan kuranes

03-11-2005 20:48:27

1. cliff are very hard so texture due to heighmaps limitations as on top view of map prevent real cliffs. So interpolation using textures maps results in small glitch on cliffs. Hard to avoid.
Be sure to try splatting5 or splattingShader for the most perfect splatting. (use of pixel shader avoid some glitches)

2. that's user splat maps or a special texture mode handling. Sope is acutally handled by mapsplitter splat maps generation. Surely can be better, but still have to find how.

While slope isn't an attribute of a vertex, a polygon between vertices does get textured.
sorry, I don't understand that one.

3. You need to add your own mapsplatter.cpp in mapsplitter tool, based on actual version, that's somewhat minor modifications, once you understood the code.
That's the heart of it :

// calculate value using height and slope
const Real height = heightmap[i + curr_row];
uint indx = 1;
while (height > heights[indx])
indx++;
const Real interpol = (height - heights[indx - 1]) * dividers[indx];
//slope of current point (the y value of the normal)
const Real Slope = 1.0f - normal[i + curr_row].y;

//ColourValue color;
alpha[0] = 0.0f;alpha[1] = 0.0f;alpha[2] = 0.0f;alpha[3] = 0.0f;

const Real A = (1.0f - Slope);
const Real B = A * (1.0f - interpol);
const Real C = A * interpol;
const Real D = Slope;

alpha[indx - 1] = B;
alpha[indx] = C;

// alpha[2] being the splat for Rock. (slope factor.)
alpha[ 2 ] = alpha[ 2 ] + Slope;
alpha[ 2 ] = alpha[ 2 ] > 1.0f ? 1.0f : alpha[ 2 ];

Jon

05-11-2005 03:49:14



2. that's user splat maps or a special texture mode handling. Sope is acutally handled by mapsplitter splat maps generation. Surely can be better, but still have to find how.


Thanks, my terrain generator knows slope around vertices as well, and I think it is a good candidate for material assignment.

I might end up modifying mapsplitter to split up material assignments and renderables into page chunks so they can be paged along with vertex data.


While slope isn't an attribute of a vertex, a polygon between vertices does get textured.
sorry, I don't understand that one.


Just me rambling, and since a vertex's normal vector can be considered its slope, I'm quite wrong above. What I was trying to say was that I was interested in assigning textures to the triangles adjacent to a vertex based on their normals. (like with Submeshes)


3. You need to add your own mapsplatter.cpp in mapsplitter tool, based on actual version, that's somewhat minor modifications, once you understood the code.


Thanks. After looking over the code this afternoon, I understand quite a bit more.

What I want to do is dispense with the single alpha-blended material (if I am able) and have my terrain generator assign materials. I'm convinced I know how the splatting works, and don't think I'll ever be happy with any of the existing Texture objects.

This evening I'm going to read through the texture assignment code again.

I'm having too much fun with this stuff :D

[Edit] took a wrong turn with the single mRenderable, think I'm back on track with the array of tiles, each of which is a scene node...

Jon

06-11-2005 02:10:11

OK, back with a specific question. Currently each tile is a renderable, and uses a single material. Each texture is performed as a pass in the material, and alpha maps are used to determine which texture is painted.

This works since the textures are hard coded into the demo, and the material has all possible textures. I believe this means that card texture memory will always contain these textures, since the driver wouldn't know which textures could be safely unloaded (I am assuming that modern drivers unload textures which aren't being used).

What I'd like to do, and I'd like some feedback, is to break tiles into multiple non-rectangular renderables, most with a single texture, some with multiples in the case of splatted areas. I think I can generate the splatting materials along with the terrain, since it will be obvious where textures meet.

This would mean that a tile wouldn't be able to return a single renderable, but instead would return a list of renderables, which means that this change would be incompatible with the CVS baseline unless it was somehow committed Tiles with a single texture (like is used with the existing code) would return a list of one renderable.

RenderQueue would need to have a method for adding a list of renderables to a queue as well.

1) Is this a bad idea?

I keep thinking about larger numbers of textures, and don't think that card memory should be taken up with textures used only on the far side of the map. I believe the drivers automatically unload unused textures, but this functionality could probably be manually done if needed. The scene manager could probably keep track of active textures based on which tiles are loaded/unloaded. I'm going to handwave on this for now.

I also think that the existing code uses the GPU to compute data which could be precomputed (no offense intended to the authors). If we ignore deformation for a moment, each tile will have the same vertixes with the same textures each time it is rendered, but the GPU will still apply the alpha masking. I am thinking that I would be replacing this with more renderables (but almost the same number of vertixes, some overlap at the renderable boundaries I believe).

I don't think much of a load is being transferred to the CPU. Most of the work would be in adding vertixes to the hardware buffer, so a few more vertixes and some addition index lookups?

Bandwidth to card/agp memory might be taxed a bit as textures are loaded, but my gut feeling is this is a good tradeoff for not having textures pinned in texture memory.

2. Is there any chance of such a change being committed to CVS?

There is always the chance that I'm the only one who worries about such things. There is the chance that the existing code does what I want, but I just haven't seen it yet (I'm still new to this, a dangerous think I know, but nothing like a little project to get ones hands dirty, as they say).

I really don't want to keep patching upcoming releases for eternity so that I can have my own private code base :wink:

3. If this is something useful to others, what do I need to do to make sure I keep everyone happy?

I'm assuming that Tuan has been ransacking Paris nightly because he is upset with what I am planning :twisted: I can't say that I blame him, after all my understanding of the code is limited to just reading the source.
But I also figure there are a few important design rules which must be observed.

tuan kuranes

06-11-2005 10:42:42

Some useful bits that you surely already figured out
1 page ==1 material
n tiles on same page == 1 material.
A big texture is better than a lot small ones.

1. Sorry, didn't understand clearly the thing. is this related to tilebanking ?
(http://www.nevrax.org/tikiwiki/tiki-ind ... e=TileBank )

2. I'm very concerned about perfomance and memory? so any good results not breaking idea behind plsm2 is usually committed to cvs.

3. do not break other parts of plsm2 ;)

Jon

06-11-2005 17:41:22

Perhaps a short write-up with a drawing or two would help.

1. Do you still get email at your free.fr address in the source code?
2. Would you object to my emailing a word document to you?

tuan kuranes

07-11-2005 12:51:08

1. yes.
2. no, but we'll sadly loose other people in forum comments.

Jon

07-11-2005 15:42:09

Good point, I'll keep discussion here. It is a bit more work to include images though :?

I have about three pages written up so far, and what I'm discovering is that some of my assumptions are turning out to be incorrect. Imagine that :shock: But this is a good learning experience for me.

A short summary of the major corrections to my first post on the 6th:

1. The material is pruned on the fly for each page, so only contains texture passes which are used.

2. Ogre places textures in a managed pool, so textures will be removed from card memory when no longer used.

Based on this I'm considering a less drastic approach. Perhaps a subclass of Material which is designed to be built on the fly (formalizing what is going on in the various texture classes). This would still allow me to have tons of textures on the terrain, and possibly make it clearer what is going on.

I still think I can create splatting textures offline.