T3D 1.2 terrain shader Detail channel as 2nd layer diffuse
by Kenneth Eves · 10/18/2012 (2:56 pm) · 18 comments
T3D 1.2 terrain system uses by default, a diffuse bitmap of the entire terrain and an 8 bit detail channel to hide the low resolution of the diffuse.
This modification (hack) reworks the terrain shader so that the detail channel functions as a second layer diffuse with TGEA style tiling, while the normal diffuse channel hides the tiling. In my own testing, I've found this to produce very high quality results given the right combination of textures.
This hack was something created for my own work. I'm publishing it as a resource in response to a request to do so. Comments, suggestions and improvements are strongly welcomed!
To use this modification I suggest the following setup for terrain materials.
Experiment with diffuseSize depending on the resolution of the texture. Do this with the detailMap unassigned so you can see what effects the scaling has. Target should be a blurry camouflage look with very little obvious tiling.
The detailSize at 10 is slightly soft at normal viewing angle when looking down at terrain. Smaller number will tighten it up but make the 2nd layer tiling more obvious.
With both, these are significantly affected by the texture itself. The more uniform the texture, the less tiling. The larger the features are on the texture, the more obvious the tiling becomes. It's a tough one to balance.
The detailDistance at 9999 has not shown to be much, if any, in terms of performance hit. Because the 2nd layer textures are mipmapped, there isn't aliasing noise.
NOTE: This will change terrain lighting, however I've found that once illumination is adjusted the terrain lighting is a closer match to the rest of the scene lighting.
Source patch. These are all in Engine/source/terrain/hlsl/terrFeatureHLSL.cpp
This last part is optional. It looks like it might be an optimization for when no detail is present. In my own work detail is always present. Leaving it in might save load if detailDistance is set lower, but it might not work as intended. I removed it in mine because the blendTotal calculation is changed from max to accumulator.
This modification (hack) reworks the terrain shader so that the detail channel functions as a second layer diffuse with TGEA style tiling, while the normal diffuse channel hides the tiling. In my own testing, I've found this to produce very high quality results given the right combination of textures.
This hack was something created for my own work. I'm publishing it as a resource in response to a request to do so. Comments, suggestions and improvements are strongly welcomed!
To use this modification I suggest the following setup for terrain materials.
new TerrainMaterial()
{
diffuseMap = "art/terrains/xgrassgreen10";
diffuseSize = "256";
detailMap = "art/terrains/xgrassgreen10";
detailSize = "10";
detailDistance = "9999";
internalName = "grass-0-20";
};Experiment with diffuseSize depending on the resolution of the texture. Do this with the detailMap unassigned so you can see what effects the scaling has. Target should be a blurry camouflage look with very little obvious tiling.
The detailSize at 10 is slightly soft at normal viewing angle when looking down at terrain. Smaller number will tighten it up but make the 2nd layer tiling more obvious.
With both, these are significantly affected by the texture itself. The more uniform the texture, the less tiling. The larger the features are on the texture, the more obvious the tiling becomes. It's a tough one to balance.
The detailDistance at 9999 has not shown to be much, if any, in terms of performance hit. Because the 2nd layer textures are mipmapped, there isn't aliasing noise.
NOTE: This will change terrain lighting, however I've found that once illumination is adjusted the terrain lighting is a closer match to the rest of the scene lighting.
Source patch. These are all in Engine/source/terrain/hlsl/terrFeatureHLSL.cpp
//KENHACK TGEA TERRAIN MOD //blendtotal is now TOTAL not highest meta->addStatement( new GenOp( " @ = saturate( @ + @ ); //total not highestrn", blendTotal, blendTotal, detailBlend ) ); // Add to the blend total. //meta->addStatement( new GenOp( " @ = max( @, @ );rn", blendTotal, blendTotal, detailBlend ) ); //END
//KENHACK TGEA TERRAIN MOD
//Removes the *2-1 scaling (it's not needed for detail textures to work, not sure why it is here)
if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
{
meta->addStatement( new GenOp( " @ = lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z );rn",
detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
}
else
{
meta->addStatement( new GenOp( " @ = tex2D( @, @.xy ); //xyzzyrn",
detailColor, detailMap, inDet ) );
}
/* ORIGINAL 1.2 CODE
if ( fd.features.hasFeature( MFT_TerrainSideProject, detailIndex ) )
{
meta->addStatement( new GenOp( " @ = ( lerp( tex2D( @, @.yz ), tex2D( @, @.xz ), @.z ) * 2.0 ) - 1.0;rn",
detailColor, detailMap, inDet, detailMap, inDet, inTex ) );
}
else
{
meta->addStatement( new GenOp( " @ = ( tex2D( @, @.xy ) * 2.0 ) - 1.0;rn",
detailColor, detailMap, inDet ) );
}
*/
//END//KENHACK TGEA TERRAIN MOD
//KENHACK average outColor and detail (now 2nd layer diffuse) so they BLEND, was ADD.
meta->addStatement( new GenOp( " @ = lerp( @, (@ + @)*0.5, @ );rn",
outColor, outColor, baseColor, detailColor, detailBlend ) );
//meta->addStatement( new GenOp( " @ = lerp( @, @ + @, @ );rn",
// outColor, outColor, baseColor, detailColor, detailBlend ) );
//ENDThis last part is optional. It looks like it might be an optimization for when no detail is present. In my own work detail is always present. Leaving it in might save load if detailDistance is set lower, but it might not work as intended. I removed it in mine because the blendTotal calculation is changed from max to accumulator.
//KENHACK TGEA TERRAIN MOD //not sure why GG would discard a pixel. //in theory it might cause artifacts. //leaving line in the shader but commenting it out so it doesn't run. meta->addStatement( new GenOp( " //clip( @ - 0.0001 ); //WARNING clip removed, not sure why this is here. KEN 2012-10-18.rn", blendTotal ) ); //meta->addStatement( new GenOp( " clip( @ - 0.0001 );rn", blendTotal ) ); //END
About the author
<3 TGE/A Quickly becoming a fan of T3D 1.2
#2
10/18/2012 (3:06 pm)
Screenie? I'm dealing with the tiling of the detail layer big-time as you posted it, wondering if it'll solve my issue...
#3

Full size: www.ameridat.com/terraininprog10.jpg
10/18/2012 (3:11 pm)
Just happen to have one handy.
Full size: www.ameridat.com/terraininprog10.jpg
#5
10/18/2012 (3:26 pm)
That makes me smile. Played Colossal Cave on a DEC PDP-10 both locally and from home using a CAT Bell 103 modem and single board terminal using a TV as monitor. Funny how times change.
#6
With that done, it would be possible to add a third layer (an 8 bit diffuse) into the mix using distance limit from it's configuration.
I looked at doing this, but it got way too abstract and I couldn't get from concept to code, so I gave up.
10/18/2012 (3:48 pm)
One idea I had for optimization would be to rewrite the shader so that diffuse texture was used for both layers and UV adjusted on the second layer with hardcoded scaling right in the shader.With that done, it would be possible to add a third layer (an 8 bit diffuse) into the mix using distance limit from it's configuration.
I looked at doing this, but it got way too abstract and I couldn't get from concept to code, so I gave up.
#7
I'm wondering if this'd be helpful to me, to be honest. At times the detail textures don't blend to my satisfaction, and I use a sencond detail texture on a low pressure brush to smooth out the tiling. But I'm thinking that if I use this resource in a fresh build and port over the resulting diffuse texture, it'll save time and still look awesome.
I'll have a crack at it when I have some free time.
Thanks Kenneth.
@Frank - :P
10/18/2012 (8:01 pm)
You know Frank just Googled that, right?I'm wondering if this'd be helpful to me, to be honest. At times the detail textures don't blend to my satisfaction, and I use a sencond detail texture on a low pressure brush to smooth out the tiling. But I'm thinking that if I use this resource in a fresh build and port over the resulting diffuse texture, it'll save time and still look awesome.
I'll have a crack at it when I have some free time.
Thanks Kenneth.
@Frank - :P
#8
Is that like:
mat1 = grasstex + detail1
mat2 = grasstex + detail2
Paint mat1 over the area.
Paint mat2 over the same area with low pressure so it gets dithered in.
???
If so, the results will be different than the patch, with personal preference on which is more appropriate for a given application.
In your setup, color is from diffuse as a low-res camouflage, detail does a high-res burn or dodge to shift luminosity up or down but leaving the color intact. Eye is very sensitive to luminosity so it perceives high resolution. Randomized details avoids tiling.
In the patch, color and luminosity is 50% from low-res diffuse blended with color and luminosity 50% from the high-res (but tiling) second diffuse. Low-res diffuse breaks up tiling, at least some what.
It could be helpful if your project needs lots of procedurally painted terrains. I'm always working on experimental zones so for me it's fast and functional.
Compulsory anecdotal comment:
This is why they don't have cars in Morrowind.
http://www.youtube.com/watch?v=SJQNm8-mx6g
10/18/2012 (9:12 pm)
I'm not sure about how a second detail texture on a terrain works.Is that like:
mat1 = grasstex + detail1
mat2 = grasstex + detail2
Paint mat1 over the area.
Paint mat2 over the same area with low pressure so it gets dithered in.
???
If so, the results will be different than the patch, with personal preference on which is more appropriate for a given application.
In your setup, color is from diffuse as a low-res camouflage, detail does a high-res burn or dodge to shift luminosity up or down but leaving the color intact. Eye is very sensitive to luminosity so it perceives high resolution. Randomized details avoids tiling.
In the patch, color and luminosity is 50% from low-res diffuse blended with color and luminosity 50% from the high-res (but tiling) second diffuse. Low-res diffuse breaks up tiling, at least some what.
It could be helpful if your project needs lots of procedurally painted terrains. I'm always working on experimental zones so for me it's fast and functional.
Compulsory anecdotal comment:
This is why they don't have cars in Morrowind.
http://www.youtube.com/watch?v=SJQNm8-mx6g
#9

Also, click on MarkupLite is enabled to see how to embed YouTube (and other video) into your posts.
10/18/2012 (10:55 pm)
Kenneth, that's exactly what I do. However, because I make my diffuse textures in World Machine almost exclusively, I find that I can get a lot more detail into the terrain by cramming in Hi-res textures and tiling them. Tiling doesn't show up in the finished diffuse map because of the way I select parameters and combine the textures. Also, I can create hi-res normal and light maps to be used in weird and surprising ways.
Also, click on MarkupLite is enabled to see how to embed YouTube (and other video) into your posts.
XAP Games "Drive"
#10
10/19/2012 (1:14 pm)
I'm not sure I understand what this actually does, got any before/after shots that show or explain it better?
#11
10/19/2012 (8:38 pm)
@Kenneth - if you're interested in an experiment, send me an email to dan [at] psycandygames [dot] com and I'll shoot you one of my heightmap/diffuse map pairs. I'd like to see how this resource treats it.
#12
@Bloodknight - Will do. At the moment I'm rebuilding my T3D. I somehow managed to break underwater fogging and can't find it. :-(
10/20/2012 (12:04 am)
@Dan - Info sent. Would be glad to try it.@Bloodknight - Will do. At the moment I'm rebuilding my T3D. I somehow managed to break underwater fogging and can't find it. :-(
#13
Before:
Default grass material with default settings grey-scale detail map.

Full size: www.ameridat.com/thackbefore.jpg
After:
Default grass material with full color texture in both diffuse and detail channels, with modification to blend the two textures and 9999 meter detail range.

Full size: www.ameridat.com/thackafter.jpg
-------------------------------------------------------
NOTES:
The softness at distance is the detail range. This can be overcome in stock T3D 1.2 by cranking up detail distance in settings, which yields similar results to the patch. That's part of how the patch works.
What the patch does is:
Changes diffuse / detail blending from additive to average.
Changes how detail maps blend by changing the detailBlend calculation from max to accumulator. (not shown in before/after since there is only 1 texture on the whole terrain)
Has the developer use a single texture for both diffuse and detail, so that the detail channel becomes a full-color 2nd layer rather than an additive bitmap. Using 2 different full color textures could be done also, and might produce interesting results.
Has the developer use the detail channel with 9999 range so that second layer is always visible.
NOTE: Thought there might have been a bug. Turns out the 9999 range is not optional. It needs to run detail to the edge of the terrain or lighting becomes inconsistent.
10/20/2012 (2:20 am)
Changes are nothing huge but might be useful.Before:
Default grass material with default settings grey-scale detail map.

Full size: www.ameridat.com/thackbefore.jpg
After:
Default grass material with full color texture in both diffuse and detail channels, with modification to blend the two textures and 9999 meter detail range.

Full size: www.ameridat.com/thackafter.jpg
-------------------------------------------------------
NOTES:
The softness at distance is the detail range. This can be overcome in stock T3D 1.2 by cranking up detail distance in settings, which yields similar results to the patch. That's part of how the patch works.
What the patch does is:
Changes diffuse / detail blending from additive to average.
Changes how detail maps blend by changing the detailBlend calculation from max to accumulator. (not shown in before/after since there is only 1 texture on the whole terrain)
Has the developer use a single texture for both diffuse and detail, so that the detail channel becomes a full-color 2nd layer rather than an additive bitmap. Using 2 different full color textures could be done also, and might produce interesting results.
Has the developer use the detail channel with 9999 range so that second layer is always visible.
NOTE: Thought there might have been a bug. Turns out the 9999 range is not optional. It needs to run detail to the edge of the terrain or lighting becomes inconsistent.
#14
10/20/2012 (7:52 am)
oh pretty, this looks like a nice improvement.
#15
causes this issue (video)
http://www.youtube.com/watch?v=tJQLow_L3wc
f*ck markuplite
I'm also not sure about the viability of setting the visible distance of all terrain details to 9999, having tested this in the past i'm pretty sure that there is an impact especially on lower spec systems
10/21/2012 (5:03 pm)
causes this issue (video)
http://www.youtube.com/watch?v=tJQLow_L3wc
f*ck markuplite
I'm also not sure about the viability of setting the visible distance of all terrain details to 9999, having tested this in the past i'm pretty sure that there is an impact especially on lower spec systems
#16
I tested performance on two computers here. The weaker is a cheap Acer laptop 1.5ghz dual core with intel onboard video. The drop on it was only a few percent given an empty scene and unnoticeable once the scene was populated with trees. It's very possible that older hardware wouldn't do as well since the texture blending is GPU intensive.
I don't see any easy optimization for performance. If the target is older hardware it might be better to stick with the stock detail mapping which can be set to short distance and doesn't artifact.
I'll take a shot at seeing if I can identify what causes the brightness to pop at distance. It could only be one of two things. Either the *2-1 in the 2nd code block really is needed (I don't know why it's there), or the *0.5 in the 3rd block to average the two values rather than add is darkening the blended terrain too much which makes the un-detailed terrain at distance look so much brighter. I'll post back if I figure it out.
10/21/2012 (7:21 pm)
I've seen that lighting artifact when a block goes completely outside the range where the detail texture gets applied. I've not seen it from a normal player view when detail distance is greater than the size of the terrain.I tested performance on two computers here. The weaker is a cheap Acer laptop 1.5ghz dual core with intel onboard video. The drop on it was only a few percent given an empty scene and unnoticeable once the scene was populated with trees. It's very possible that older hardware wouldn't do as well since the texture blending is GPU intensive.
I don't see any easy optimization for performance. If the target is older hardware it might be better to stick with the stock detail mapping which can be set to short distance and doesn't artifact.
I'll take a shot at seeing if I can identify what causes the brightness to pop at distance. It could only be one of two things. Either the *2-1 in the 2nd code block really is needed (I don't know why it's there), or the *0.5 in the 3rd block to average the two values rather than add is darkening the blended terrain too much which makes the un-detailed terrain at distance look so much brighter. I'll post back if I figure it out.
#17
it also seems to be related to the mesh culling code for the terrains, the part that reduces the mesh polys based on distance from camera (changing the screenerror setting seems to confirm this).
10/22/2012 (11:09 am)
Ive looked at this a bit more, and unless i missed something its the *2-1 part that seems to trigger the effect.it also seems to be related to the mesh culling code for the terrains, the part that reduces the mesh polys based on distance from camera (changing the screenerror setting seems to confirm this).
#18
before
after
and the forum crops not resizes, oh well you can see half the image, you will have to open it up to see the full thing
10/23/2012 (6:06 pm)
here is my before and after, i tried to tale from about the same place, not always easy :)
before
afterand the forum crops not resizes, oh well you can see half the image, you will have to open it up to see the full thing

Torque 3D Owner Kenneth Eves
XAP GAMES
I didn't try to fix it in the post because more often than not I just mess it up worse. My apology.
Also "xyzzyrn" should just be "\r\n"
xyzzy is an ancient game reference that I use as a magic number when editing. Kudos to anyone who knows what that's from :-) hint: I first played it back in 1977.