HeroEngine Developers > Developer Created Tutorials

Omzy's Advanced Terrain Splatting Shader


Omzy's Advanced Texture Shader
For use with HeroEngine

Hello fellow Dev's!
We at Odyssey of Ydris have been working hard creating our world these past few months, and in the process we have created a Texture Splatter shader for use with HeroEngine that revolutionizes the way texture layering is processed by the engine.  This shader is merely a few lines of code injected into an existing .fx shader file within your repo. 

You can read more about how to use custom shaders here:

I was working in our world when I became frustrated with the way opacity blending worked.  There were textures that faded into nothingness, and unless you became extremely creative with alpha layers, you couldn't really create realistic layering effects with your terrain textures.  I ran across this article (http://www.gamasutra.com/blogs/AndreyMishkinis/20130716/196339/Advanced_Terrain_Texture_Splatting.php) which explains the math and the process for creating more realistic layering, and directed it to Omzy, our owner/programmer/developer.  In response, he provided me with this shader, and we're sharing it with the community!

This custom shader replaces the normal opacity function on all layers except the bottom layer.

In order to create 'depth', you must use the alpha layer of the normal map (currently only for spec).  To do this, create a heightmap/bump map of your texture and blend it with your spec map, so that the image has pronounced highs/lows. (you can modify/tweak this later using levels, brightness, and contrast controls).  You must create a 'balance' between your spec and your heightmap so you don't completely sacrifice your spec.

I will be providing a more in-depth texture splatting tutorial using this shader at a later date.  Until then, this video pretty much sums up how this functions:

And now for the shader!


Find this code in heightmappermutations.fx locade in your "Render/shaders200a/game" folder:

    #if defined(DO_TEXTURE_ALPHA)
      fadevalue *= diffuseTexColor.a;

(Insert the code below here)

    diffuseTexColor.rgb *= In.VertexColor;

--- Code: ---

float4 normaltexture = tex2D(NormalSampler,In.TexCoord0.zw);
float heightval = normaltexture.w; //w is alpha, which contains spec = heightmap substitute
if (fadevalue > 0.2 && fadevalue < 0.6) { //transition width is 0.4
float fadenorm = (fadevalue - 0.2)/ 0.4;
float edgenorm = (fadevalue - 0.2)/ 0.0625; //edge blend value
if (fadenorm < (1-heightval)) {
if ( fadenorm > (1-heightval)*0.55) { //blend a few adjacent pixels
if ( fadevalue < 0.3) { //blend the edge down
fadevalue = (fadenorm - (1-heightval)*0.55) / ((1-heightval)*0.45) * edgenorm;
} else {
fadevalue = (fadenorm - (1-heightval)*0.55) / ((1-heightval)*0.45);
} else {
fadevalue = 0.0;
} else {
if ( fadevalue < 0.3) { //blend the edge down
fadevalue = edgenorm;
} else {
fadevalue = 1.0;
} else {
if (fadevalue < 0.2) {
fadevalue = 0.0;
} else {
fadevalue = 1.0;

--- End code ---

Screenshots of how it's used in our game:

And a video flyby of our world in progress:

MCINDUS and Omzy

Odyssey of Ydris

Good work!

I'll let ya know if we use it and how it goes.

thanks for posting it!

I will certainly try this out in the future! Thanks for sharing!

By Patrick McGuire - for Hero Engine with Omzy’s Shader

When using Omzy’s Terrain Shader, there are several things you must keep in mind:

The spec map is now not ideal, but on terrain I’ve found it to work better this way.

When generating spec maps, try to create black/white ranges that are balanced between the different textures for the zone.  This way, you can use more consistent opacity settings while painting terrain.

Layer 1 - or the bottom layer, is unaffected by the shader, so any layer that is placed directly on top of layer 1 will act as the HE default opacity blend. (This works especially well when you have a varying normal/diffuse UV combination.

Every Layer (besides layer 1) will only paint the texture that is ‘highest’ based on the opacity (or ‘strength’) slider level and the ‘shader spec’.

Creating the Proper Spec Maps: (MOST IMPORTANT STEP)

* Create a ‘spec map’ - preferably from the texture’s ‘normal’ (or use current one)
* Create a ‘heightmap’ - essentially where black is the lowest point and white the highest. (Can also be created from the normal, but I find that a custom B&W version of the diffuse texture can also work very well)
* Place the ‘spec map’ as a layer above the ‘heightmap’
* Make the ‘spec map’ layer an ‘overlay’ or ‘soft light’ layer
* Adjust the levels of the layers to create a nicely balanced result and merge them.
* Lower the overall brightness 30-40% due to HE’s crazy spec settings and due to ease of use for painting.
* Add this new ‘shader spec’ to the alpha channel of your old ‘normal’ file
* Save as DXT5 with Kaiser mips. (I also use 1.1 blurriness blending)
Painting the Textures:

* Use one of the Custom Brushes to paint textures. (Or Perlin Noise)
* Paint with about 60-75% of the opacity you truly wish first to paint the main ‘body’ of the texture - this gives a good base, and doesn’t create hard edges between textures. Remember to use the shift+ctrl ‘rotate’ feature to get varying randomness in the placement of the textures as you paint.
* Then go 75-90% with a smaller brush and connect the main parts of the texture.
* Crank up opacity to 100% and use a brush set very small (one or two vertices) to do bold centered detail work.
* Drop the opacity to 40-50% to do the trim of the textures, but try to avoid tiling.
* Drop the opacity to 20-40% and paint all round the edges for fine detail to finish off your transitions.
Other Notes:Using large resolution normals: BE VERY SPARING

* Use a normal that best accents the terrain and texture
* Set it to as low as ¼ of the diffuse texture UV size (huge)
* These normals tend to need a varying degree of ‘noise’ to keep the texture detail in tact*** The spec on these normals will apply to the huge UV, but the shader will only apply the spec depth range to the diffuse UV.
**** Use these as infrequently as possible, as the filesize is 4x the original

Using inverted normals:
When creating snow, sand, and other textures you wish to ‘fill-in’ between crevices in the texture below (texture A), you can:

* Invert the base texture’s (texture A) normal and spec.
* Use this inverted normal (normal A_inv) paired in-engine with your fill-in diffuse (texture B)
* Make sure the UV of your new [normal A_inv] matches the UV of [texture A]
* Paint over texture A with texture B (paired in-engine with normal A_inv).

Damn it looks great. Nice terrain and sculpting btw.


[0] Message Index

Go to full version