Sign in to follow this  
Phil_321

Texture splatting question(s)

Recommended Posts

I'm trying to implement texture splatting based on Charles Bloom's paper: http://cbloom.com/3d/techdocs/splatting.txt After reading it appox. 50 million times, I have a good grasp of what he's doing. I've a question though (probably have a few more before I've got it up and running) For each quad of the terrain Bloom puts 4 pixels into an alphamap that covers the entire terrain, for each texture. Ie. for a 256x256 heightmap there will be a 1024x1024 alphamap for each texture. Doesn't this sort of defeat the purpose of splatting(which I gather is good detail without using lots of memory), as you will end up with huge (alpha)maps consuming lots of memory consumption.

Share this post


Link to post
Share on other sites
Yes it does. I opted to go with only 1 texel per point on my map. I also went with 16 bit textures, since I couldn't really tell the different between 32 and 16. A 256x256 texture at 16 bits is only 1 megabyte.

You can get around this by using pixel shaders. This lets you pack four alphamaps (one for each channel) into a single texture. So now for a 256x256 patch you are down to 1 megabyte instead of 4 if you have 4 layers. Compression can help even more.

Don't worry about it too much. Most modern cards have at least 128 mb of memory physically on the card, and have even more available for textures. Keep in mind that it doesn't all have to be in the card at once. You can swap textures in and out from system memory as you need without too much of a performance hit.

Share this post


Link to post
Share on other sites
O.K., I think I'll go with one pixel per quad too.

I was also wondering why Bloom splits the terrain up into "splat chunks"?
I have my terrain divided up into a quadtree for rendering, but I don't see why Bloom splits it up when creating his alphamaps for splatting. Couldn't you just go through the entire heigtmap and determine the alpha values for each alphamap without breaking it into chunks first?

Share this post


Link to post
Share on other sites
Don't base it off of the heightmap. You are ruining a perfectly flexible solution by doing so. I made a simple editor that allows me to place different textures wherever I want and it's great.

I would recommend ignoring Bloom's article. It's confusing and doesn't even say what he's really doing.

All it is is a bunch of alphamaps that say what texture goes where. Forget the entire tile-blending-weight-whatever thing he had, it doesn't even make sense.

The reason the alphamaps are divided up into chunks is to save memory. Sure you could have eight 1024 x 1024 alphamaps, but some of them might only have data in one 32 x 32 area, and the rest is wasted.

Share this post


Link to post
Share on other sites
Thanks for the help Raloth. I've got the alpha maps created now but I'm not sure how to combine them with the color maps when rendering.
I have the following textures:
grass grass_alpha
rock rock_alpha
ground ground_alpha

I'm not sure how to go about rendering all this with 2 texture units(gf mx440). Any ideas?

Share this post


Link to post
Share on other sites
Hi, Phil.

I've also been looking into texture splatting, and especially Bloom's article, (which I, also, had to read about ten times).
I have the quadtree-based terrain.
According to Bloom, (or at least what I gathered he was trying to say), you should create one index buffer per texture (per chunk).

Then, follow these steps during rendering:
1. Render the base texture, (usually just the most common texture).
2. For each chunk, bind the chunk's alphamap into one texture unit
3. For each texture, (grass, rock, sand, whatever), bind the texture. Then render the index buffer associated with that texture.

Note: I haven't yet implemented it myself, (stopped the terrain-thingie shortly, and am now doing something else), but I will be doing it soon enough in the future. So, I'm interested in hearing about your results. Keep me posted on how it works out.

I hope this was helpful!

Share this post


Link to post
Share on other sites
O.K. James, I might try that.
You're saying to render the most common texture and blend the others on.
What about rendering the textures one by one (with their alpha maps), would this work?
Well I suppose I'll find out, once I remember how to do multitexturing. :)

I'm a bit rusty, I'm only getting back into it programming after about 6 months.

Share this post


Link to post
Share on other sites
O.K. I layed a base grass texture over the entire terrain.

Now I want to combine my rock texture and rock alpha maps, and render them on top of it.
The problem is the rock texture has RGB components but the alpha map texture only has one component.
I created it with this:
glTexImage2D(GL_TEXTURE_2D, 0, 1, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, data);



// Bind rock texture to texture unit 0
glActiveTextureARB(GL_TEXTURE0_ARB);
rockTex.Bind(GL_TEXTURE_2D);

// Bind alpha map to texture unit 1
glActiveTextureARB(GL_TEXTURE1_ARB);
rockAlphaTex.Bind(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);

// Set up the texture environment to combine the two textures so that the rgb of tu0 and the alpha value from tu1 are used when rendering

glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ARB, GL_REPLACE);

// This section is probably all wrong!
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ARB, GL_MODULATE);






The terrain ends up covered in a very darkened rock texture even though there's barely any rock in the terrain.

Share this post


Link to post
Share on other sites
I wrote a simple texture splatting demo in OpenGL a long time ago. It didn't work very well and wasn't very flexible, but it got the job done.

Demo
Source

There are a lot of things wrong with that code since I was new to OpenGL at the time, but it should at least help you get your render states right. I am currently working on an article about texture splatting in Direct3D. It shouldn't be too hard to be able to understand what it's doing and port it to OpenGL.

Share this post


Link to post
Share on other sites
While I haven't looked into the technical details, I think UnrealEd terrain texturing may work in a similar way. When you add a texture layer to the terrain you then have to paint where you want the texture to show, allowing you to blend it into existing layers. Very good for coping with steep slopes and cliffs, even though its just a height field, you can paint an appropriate texture over the cliff area and you don't get the horrible texture stretching if you just try and apply a texture over the entire height field.

Share this post


Link to post
Share on other sites
Quote:
Original post by Raloth
I wrote a simple texture splatting demo in OpenGL a long time ago. It didn't work very well and wasn't very flexible, but it got the job done.

Demo
Source

There are a lot of things wrong with that code since I was new to OpenGL at the time, but it should at least help you get your render states right. I am currently working on an article about texture splatting in Direct3D. It shouldn't be too hard to be able to understand what it's doing and port it to OpenGL.


looking forward to that article man.

Share this post


Link to post
Share on other sites
That's a very helpful demo alright Raloth.
One thing I didn't have in my code was the glEnable(GL_BLEND) and glBlendFunc(), I really need to brush up on opengl.
Still haven't got it working right but I should be able to sort it out tomorrow with the help of your code.

Share this post


Link to post
Share on other sites
Quote:

glTexImage2D(GL_TEXTURE_2D, 0, 1, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, data);


You might perhaps want to use GL_APHA, and not GL_RED...

Quote:

// Bind rock texture to texture unit 0
glActiveTextureARB(GL_TEXTURE0_ARB);
rockTex.Bind(GL_TEXTURE_2D);

// Bind alpha map to texture unit 1
glActiveTextureARB(GL_TEXTURE1_ARB);
rockAlphaTex.Bind(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);

// Set up the texture environment to combine the two textures so that the rgb of tu0 and the alpha value from tu1 are used when rendering

glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ARB, GL_REPLACE);

// This section is probably all wrong!
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ARB, GL_MODULATE);


When I was trying to set up an implementation of texture splatting, this was where I couldn't get it right. It's confusing, and I'm still not sure how to do it. Though the resource which I used the most was the extension registry. Check this out: ARB_texture_env_combine specification.

Good luck figuring it out, and be sure to keep us updated!

Share this post


Link to post
Share on other sites
Yeah, this glTexEnv() can be confusing.
Here's what I should have done for tu1(courtesy of Raloth's source):


glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_PREVIOUS);



The GL_RED instead of GL_ALPHA was another error.
I also forgot to use glMultiTexCoord() to specify the texture coords for tu1.
I've got it going now, albeit with fairly rough and ready code. I'm going to move on to making a proper editor now based on what PaulC said about UnrealEd(won't be able to see it in action myself until I upgrade my gfx card).

Share this post


Link to post
Share on other sites
Quote:
Original post by Phil_321
Yeah, this glTexEnv() can be confusing.
Here's what I should have done for tu1(courtesy of Raloth's source):

*** Source Snippet Removed ***

The GL_RED instead of GL_ALPHA was another error.
I also forgot to use glMultiTexCoord() to specify the texture coords for tu1.
I've got it going now, albeit with fairly rough and ready code. I'm going to move on to making a proper editor now based on what PaulC said about UnrealEd(won't be able to see it in action myself until I upgrade my gfx card).


Damn, the texture unit setup is a like riddle. You realize how simple it really is after you see the solution... Anyway, nice that you got it working. Would it be possible to see a demo anytime soon?

Share this post


Link to post
Share on other sites
Well, I've already started recoding this into a proper terrain editor so it's not actually running at the moment. Here's two screenshots I took though, and the textures used. This is just using procedural texturing based on height and slope.

1.
2.
Textures.

There was a slight transparency error where the third texture was layed, that's why some of the blends are dark, but I'm going to wait until I've got the terrain editor running before I fix it.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this