(HLSL) Terrain shader.

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

(HLSL) Terrain shader.

Post by Mel »

This terrain shader is part of an idea i had. It lacks the light or the normals calculation, but it is up to the reader to add the code to insert it.

I've used the FOG0 semantic, which is available on PS2.0 (not in PS3.0, though...) to map some fog, and may show if it is enabled, (but that part is untested) I hope you find it interesting and even useful :)

The good thing is that it is faster than the regular terrain splatter shaders, because it only reads textures twice, the bad thing is that, for now, it is only restricted to 2 textures.

Code: Select all

//Terrain vertex Shader

float4x4 matWorldViewProjection;
float4x4 matWorldInverse;

struct VS_INPUT 
{
   float4 Position : POSITION0;
   float2 Texcoord : TEXCOORD0;
   float3 Normal   : NORMAL0;
};

struct VS_OUTPUT 
{
   float4 Position : POSITION0;
   float fog       : FOG0;//If fog is set, it will be used.
   float2 Texcoord : TEXCOORD0;
   float3 Normal   : TEXCOORD1;
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
   VS_OUTPUT Output;

   Output.Position = mul( Input.Position, matWorldViewProjection );
   Output.Texcoord = Input.Texcoord;
   Output.Normal = mul(Input.Normal, matWorldInverse);
   Output.fog = Output.Position.z/Output.Position.w;

   return( Output );
   
}

//Terrain Pixel Shader

float tiles;//Allows to repeat the textures many times as wished, or needed

sampler2D base1; //"Ground" Texture
sampler2D base2; //"Wall" Texture

struct PS_INPUT 
{
   float2 Texcoord : TEXCOORD0;
   float3 Normal   : TEXCOORD1;
};

float4 ps_main( PS_INPUT Input ) : COLOR0
{
   float3 upVect = float3(0,1,0);
   float dp = dot(upVect,Input.Normal);
   
   dp = clamp(4*dp-2.5,0,1);
   
   float4 col1 = tex2D( base1, Input.Texcoord*tiles );
   float4 col2 = tex2D( base2, Input.Texcoord*tiles );
   
   return lerp(col2,col1,dp);
   
}
This is a screen of this in action.

Image
Last edited by Mel on Wed Feb 09, 2011 10:29 am, edited 2 times in total.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Re: (HLSL) Terrain shader.

Post by Luben »

Nicely looking. Just checking, since your variable is named 'matWorldInverse', you are aware that you need the transposed inverse to properly transform normals?
Mel wrote:

Code: Select all

   return col1*dp + col2*(1-dp);
I think there is a lerp-function for this, if i'm not mistaken it's the same as glsl's mix funtion. http://msdn.microsoft.com/en-us/library ... 85%29.aspx
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

I really don't know which is the best (or the right) matrix to transform the normals. I have always used worldInverse, and it always have worked well.

Mmmm... i am not used to put LERP in my shaders, but it is highly probable that the directX driver changes that automatically to use a LERP operation when the shader compiles if that makes it faster. Not obstant, checking the MSDN HLSL LERP functions, it seems it has to work with variables of the same dimensions, while my shader uses combinations of scalars with vectors, which i don't know if would work the same.

EDIT: Checked, no, it doesn't update the operation to a LERP, and changing the code to a LERP makes the shader a 12.5% faster. Good point. I will update that right now.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
fmx

Post by fmx »

is it just me or is there some texture stretching going on at steep height changes?
The UVs should flow equally over the surface of the terrain

I'm not an expert on coding terrain shaders though, simply an observer :oops:
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

Regarding normals, i've posted in the other thread.
What does obstant mean? Think it's the first time i've encountered that word.
Yeah, i got confused by that documentation too. Googled before posting to make sure it's used the way i thought.
It's kinda wierd really that it doesn't optimize to a lerp-instruction. Unless i'm mistaken, it'd be kinda easy to make a pattern to recognize that optimization(I haven't dabbled in compiler coding though so i haven't really got a clue ;p).
By the way, how did you measure the speed of the shader? :)
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

fmx wrote:is it just me or is there some texture stretching going on at steep height changes?
The UVs should flow equally over the surface of the terrain

I'm not an expert on coding terrain shaders though, simply an observer :oops:
That's a matter of the terrains. The terrains normally consists of large blocks of polygons whose vertices are vertically set to simulate a terrain, but their mapping coordinates are normally flat. The stretching of the textures is unavoidable if you use that approach to build terrains (irrlicht for instance, does it). But perhaps, if you build a mesh on your own which has the shape of a terrain, you can give it any mapping coordinates, avoid that problem, and still, have the shader behave correctly.

@Luben "Not obstant" is more or less the same as "Although". Their usage is the same, although, (not obstant :D ), their meaning is diferent.

I measure the speed by the number of instructions the shader has :P I know this ISN'T precise at all, I have made that estimation given that the previous version had 7 arithmetic operations when compiled and the new one has only 6 arithmetics. Rendermonkey can provide a disasembled version of the shaders if they compile well.

But checking the disasembled shaders, i see that when the LERP function is in use, the "lrp" DX asm instruction is used, so i guess it is faster, or else, why use it at all?
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Valmond
Posts: 308
Joined: Thu Apr 12, 2007 3:26 pm

Post by Valmond »

>is it just me or is there some texture stretching going on at steep height changes?

>The stretching of the textures is unavoidable if you use that approach to build terrains

You can actually "fix" this using triplanar mapping.
Don't ask me exactly why it works (but it does), Nadro gave me the tip in my project thread.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

triplanar mapping... curious. I'll have a peek at that :)

Ahm... I think i get what it does. It samples 3 planar mapping coordinates based on the sample's position, and using the normal, generates an unified color which biases the three samples, and obtains the final result.

+It doesn't matter the position, the texture will always look well.
- Is slower, logically.

That's good if you don't use mapping coordinates at all, and sample them from the object's position, perhaps, but i was using the exported coordinates, so i can't really apply the same concept. It would require 3 texture coordinates set. (and it is complex to even have 2 and tangent space...)
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Post by REDDemon »

3 planar mapping is good but has some problems i'm tryin to solve with glsl 1.0

it doesn't work well with aperiodic mapping, it doesn't work well with tiling.

I was able to do


tiling+3planar (so triplanar with UVs)

or

tiling+aperiodic

but not all at the same time. I have some ideas on how to work around that but seems to be very difficult O_O (well i know a possible way but it requires more vertex data than available data and i want to do that with standard irrlicht materials)

i'm using your example on how to do +2 uv mapping coordinates. of course i worked hard to get it work with glsl 1.0. but now it works.

do you have any idea on how to solve this problem and get tiling+aperiodic+3planar?

well.. using 3planar gives some sort of aperiodicity . But it is not the same thing of an aperiodic mapping done for real. (alwalys get artifacts when looking from far)
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Use 3 sets of mapping coordinates? I don't know.

The triplanar system used in NVidias's demo is designed to use the fragment's position as the key to generate the mapping coordinates, so they don't have to care really of the texture coordinates. But of course, that can be a bit limiting.

If you want to mess with really odd stuff, the Tangent Vertices have enough room for up to 4 texture coordinates sets given you aren't using the tangent space data + 1 "normalized" (it means that the range is just [0,1]) set of coordinates if you use the color channel to store even more data, + one extra normalized set if you dare to compress more texture coordinates within the normal vector
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Post by REDDemon »

I know Actually i used Colors+Normals+4 UV sets.

Using NVIDIA solution make every tile of the terrain going on its own and visible seams could occur.

As solution I wrote a shader that take as input the UV of nearby vertices (i have lots of duplicated vertices cause of tiling system).

This way I use normal data and UV data to compute the correct mix of tiles and I have a tiled/3planar mapped terrain.

The problem is that every different texture layer requires 4UV mapping coordinates this way. And the shader is not the fastest shader I ever seen.
I ended all vertices data with only 1 texture layer.

So i have color data not used, but it is not enough for add another texture layer(of course I can use a second layer for the Heightmap and do parallax mapping, but not another terrain layer).
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Irrlicht needs FVF's already.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Post Reply