New terrain texture blending method (soon a resource)
by Tim Holt · in Torque Game Engine Advanced · 06/16/2006 (12:14 pm) · 17 replies
Been working on a new terrain texture blending method lately that I wanted to toss out. When completed I'm going to put it up (source, etc.) as a free resource.
So TQT textures for Atlas terrains are pretty weak for large scale areas from a practical perspective. The only way to get any kind of reasonable detail in a texture is to make either a HUGE base texture, or a small Atlas instance. Either way, it's a method that doesn't scale very well when you're trying to map very large areas.
So I had an idea of actually using the RGB channels of the TQT image to encode data on how the ground should be textured. Specifically, the red channel maps how much "rock/gravel" texture to show, the green channel how much "brown needle forest floor/dirt" to show, and the blue channel how much "green grassy/plants/moss" texture to show. A modified shader doesn't actually draw the TQT image at all, but only samples it's RGB channels in order to decide how to mix the base detail textures.
Maybe the best way to describe this is with pictures.
First, I started by assuming I could create my desired terrain textures for my project using just three base textures: gravel, green/plant and forest floor/needle. They are shown below...
Gravel Base
Plant Base
Needle Base
Next, I create a false color texture as shown below. I wanted road areas to have gravel texture, so you can see how I drew solid red lines where I wanted roads.

In this image, the red intensity of a pixel indicates how much gravel base to show, the green intensity how much forest floor/needle base to show, and the blue intensity how much green plant base to show. For example no red in a pixel means no dirt shown. Only full red (no green or blue) means only dirt shown.
Here's a picture that shows a portion of the texture broken out into separate RGB channels to help visualizes this...

So now I've got my TQT image that now contains base texture coverage data, and I've got my 3 base textures that will get blended and drawn on the surface.
The actual blending happens in a new customized shader. What the shader does is basically grab a pixel from each base texture and multiply it by the appropriate TQT channel (red, green or blue). Using the sample piece above, pictorally that works out like this...

Summing up these three textures creates a final composite image like this...

Lastly here's a screenshot showing the final result in-game...

As you can see, the ground now has MUCH more detail visible than with just a standard TQT image. You can also see how the distant terrain texture isn't so hot looking. That's the next step in the development - working on a way to have it blend in a second TQT image at a distance. See this thread
So TQT textures for Atlas terrains are pretty weak for large scale areas from a practical perspective. The only way to get any kind of reasonable detail in a texture is to make either a HUGE base texture, or a small Atlas instance. Either way, it's a method that doesn't scale very well when you're trying to map very large areas.
So I had an idea of actually using the RGB channels of the TQT image to encode data on how the ground should be textured. Specifically, the red channel maps how much "rock/gravel" texture to show, the green channel how much "brown needle forest floor/dirt" to show, and the blue channel how much "green grassy/plants/moss" texture to show. A modified shader doesn't actually draw the TQT image at all, but only samples it's RGB channels in order to decide how to mix the base detail textures.
Maybe the best way to describe this is with pictures.
First, I started by assuming I could create my desired terrain textures for my project using just three base textures: gravel, green/plant and forest floor/needle. They are shown below...
Gravel Base
Plant Base
Needle BaseNext, I create a false color texture as shown below. I wanted road areas to have gravel texture, so you can see how I drew solid red lines where I wanted roads.

In this image, the red intensity of a pixel indicates how much gravel base to show, the green intensity how much forest floor/needle base to show, and the blue intensity how much green plant base to show. For example no red in a pixel means no dirt shown. Only full red (no green or blue) means only dirt shown.
Here's a picture that shows a portion of the texture broken out into separate RGB channels to help visualizes this...

So now I've got my TQT image that now contains base texture coverage data, and I've got my 3 base textures that will get blended and drawn on the surface.
The actual blending happens in a new customized shader. What the shader does is basically grab a pixel from each base texture and multiply it by the appropriate TQT channel (red, green or blue). Using the sample piece above, pictorally that works out like this...

Summing up these three textures creates a final composite image like this...

Lastly here's a screenshot showing the final result in-game...

As you can see, the ground now has MUCH more detail visible than with just a standard TQT image. You can also see how the distant terrain texture isn't so hot looking. That's the next step in the development - working on a way to have it blend in a second TQT image at a distance. See this thread
#2
06/16/2006 (3:05 pm)
This is really neat. Will try it when you post it.
#3

That doesn't happen in-game, as TSE is calculating in-between pixel values. It's a bit hard to see but there's a road in the example shot on the right textured in dirt.
06/16/2006 (3:17 pm)
One thing to note. In this image below, there's no blending showing up and the result is kind of pixelly.
That doesn't happen in-game, as TSE is calculating in-between pixel values. It's a bit hard to see but there's a road in the example shot on the right textured in dirt.
#4

So the near texture is being done using the above technique, and then the distant texture (forested hills) are drawn using a distance fade. It's sort of like fog in that the farther your eye from a point, the more it will show the "distant forest" texture instead. The distant forest texture is only 1024x1024, and definitely could use a bit of parallax bumps to really make it perfect!
06/16/2006 (6:23 pm)
Here's an update picture. 
So the near texture is being done using the above technique, and then the distant texture (forested hills) are drawn using a distance fade. It's sort of like fog in that the farther your eye from a point, the more it will show the "distant forest" texture instead. The distant forest texture is only 1024x1024, and definitely could use a bit of parallax bumps to really make it perfect!
#5
06/16/2006 (11:54 pm)
That looks hot. =)
#6
06/17/2006 (1:03 am)
Cool stuff!
#7
06/17/2006 (4:49 pm)
Tim, this is a great idea! I'm also very interested in applying this concept as soon as it's available. Great work!
#8
I think part of the motivation for this was that I just couldn't figure out good and practical ways to create massive textures for terrain - 65k x 65k might be the theoretical limit, but serious - who can create textures like that? I can't even open or do multilayer editing of a 8192x8192 texture in Photoshop on my 4g RAM 3.8 ghz box without some obvious and painful performance issues. Really what I wanted to be able to do was "paint" terrain with a broad brush stroke, yet still be able to see details. In fact with this method I could probably just ditch the whole TQT format, as even a relatively coarse resolution false color guide texture will still give me a nice looking terrain surface.
One thing I don't know about yet, and this relates to my relative newness to shaders. Realistically, how many separate textures can I have a shader use? I had wondered about doubling the number of base textures for example, but how portable to different graphics cards would that be if I did that? I suppose the key would be to write multiple shaders for different levels of graphics card ability.
06/17/2006 (10:54 pm)
Glad you like it. I'm very close to done and want to release it before I get too carried away making more changes. I also am thinking though that the upcoming Atlas update is going to break it. But luckily 95% of the process is in a shader, not in the TSE code. Really the only code changes in the AtlasInstance are to add additional detail textures.I think part of the motivation for this was that I just couldn't figure out good and practical ways to create massive textures for terrain - 65k x 65k might be the theoretical limit, but serious - who can create textures like that? I can't even open or do multilayer editing of a 8192x8192 texture in Photoshop on my 4g RAM 3.8 ghz box without some obvious and painful performance issues. Really what I wanted to be able to do was "paint" terrain with a broad brush stroke, yet still be able to see details. In fact with this method I could probably just ditch the whole TQT format, as even a relatively coarse resolution false color guide texture will still give me a nice looking terrain surface.
One thing I don't know about yet, and this relates to my relative newness to shaders. Realistically, how many separate textures can I have a shader use? I had wondered about doubling the number of base textures for example, but how portable to different graphics cards would that be if I did that? I suppose the key would be to write multiple shaders for different levels of graphics card ability.
#9
06/17/2006 (11:27 pm)
@Tim Holt: This is probably different for D3D, but in OpenGL you can count on having at least 16 textures available to the shader. I'm sure there's some way to query how many textures a shader can use in D3D. (Sorry, not very experienced with D3D).
#10
to get the number of suppported textures per pixel/pass on a given directX device
check dx device caps MaxSimultaneousTextures,
should be able to intelisense .DeviceCaps.MaxSimultaneousTextures and .DeviceCaps.MaxTextureBlendStages
06/19/2006 (8:32 am)
Yah its the same for dx, most cards (even a fx5200 will give you up to something like 16 textures per pixel/per pass) The hard part is runing out of instructions (on those ealier cards) passing that may texcoords around, if they are differnet sizes ;)to get the number of suppported textures per pixel/pass on a given directX device
check dx device caps MaxSimultaneousTextures,
should be able to intelisense .DeviceCaps.MaxSimultaneousTextures and .DeviceCaps.MaxTextureBlendStages
#11
06/19/2006 (8:47 am)
Cool ok. I want to try adding a parallax-type shader to the distant land so that it has some realistic roughness - same for close up.
#12
D3D has 4 max in 1.1-1.3, 6 in 1.4, 8 in PS2.0, and higher as you go higher.
Naturally things run slower as you use more. Check the DX docs for details on various limits.
07/02/2006 (11:59 am)
Incidentally, this is the basic technique that is used in Atlas2's blender terrain (and TGE's terrain blender). It's hooked into the TQT system so you can have opacity maps as big as you want. It's pretty cool. :)D3D has 4 max in 1.1-1.3, 6 in 1.4, 8 in PS2.0, and higher as you go higher.
Naturally things run slower as you use more. Check the DX docs for details on various limits.
#13
--- edit ---
Note to self, check forums now and then...
http://www.garagegames.com/mg/forums/result.thread.php?qt=46940
07/03/2006 (8:24 am)
Ben, what's the ETA on Atlas2 release?--- edit ---
Note to self, check forums now and then...
http://www.garagegames.com/mg/forums/result.thread.php?qt=46940
#14
07/03/2006 (1:10 pm)
Good man. :)
#15
07/20/2006 (11:02 am)
That is pretty.
#16
07/23/2006 (4:33 am)
Now where in hell did I read a document describing a method similar to this that blended two detail textures at different octaves to achieve a reduction in the repeated noise...
#17
07/23/2006 (4:39 am)
Now where in hell did I read a document describing a method similar to this that blended two detail textures at different octaves to achieve a reduction in the repeated noise...
Torque Owner Tim Holt
// -------------------------------------------------------------------- // diffuseColor is a map of dirt, needle and green stuff intentsities // mapped into the R, G and B channels respectively. Use the RGB values // in the diffuseColor to control the mix of the 3 detailMap textures // -------------------------------------------------------------------- float4 mergedColor; mergedColor = (tex2D(detailMap0, IN.detailCoord) * diffuseColor.r) + (tex2D(detailMap1, IN.detailCoord) * diffuseColor.g) + (tex2D(detailMap2, IN.detailCoord) * diffuseColor.b); mergedColor = lerp (mergedColor, fogCol, fogCol.a);It also required some modifications to the Atlas code to support multiple detail textures.
Oh I do have normal maps crudely working on here as well. What I really want to do is put some kind of parallax shader type noise onto the ground surface so it's not so flat and regular.
The other thing I'm contemplating is to actually pack more data into the RGB values. For example I could manage 8 different base textures if I limited the intensity values from 0-127 instead of 0-255 and mapped for example base texture 1 into the first 4 bits of one color channel, and base texture 2 into the last 4 bits. It would be great if the TQT image had an alpha channel where I could pack more data in!
As mentioned above, when this is done I'm going to release all the source for it. It's being done as part of a university research project.