Terrain texturing shader(splatting)

For shader makers

Terrain texturing shader(splatting)

Postby KronosUK » Tue Feb 09, 2010 11:00 pm

Hi,

Just started using Xors3d and know next to nothing about shaders. Anyone out there got any terrain splatting shader code they'd be prepared to share or something to get me started at least. It's the usual sort of thing I'm after ie using an rgba alphamap with 4 textures. The alphamap channels determine how much of each texture shows through.

Thanks

KronosUK

 
Posts: 2
Joined: Tue Feb 09, 2010 10:48 pm

Re: Terrain texturing shader(splatting)

Postby Knightmare » Fri Feb 12, 2010 3:49 pm

Well, about splatting.
I haven't any working sample, but I can write a shader sample code for you.
Code: Select all
// objects world matrix
float4x4 matrixWorldViewProj : MATRIX_WORLDVIEWPROJ;
float4x4 matrixWorld         : MATRIX_WORLD;

// diffuse textures for splatting
texture  diffuseTexture1 : TEXTURE_0;
sampler diffuseSampler1 = sampler_state
{
   Texture = <diffuseTexture1>;
   AddressU      = WRAP;
   AddressV      = WRAP;
   AddressW      = WRAP;
   MinFilter     = ANISOTROPIC;
   MagFilter     = ANISOTROPIC;
   MipFilter     = ANISOTROPIC;
   MaxAnisotropy = 4;
};
texture  diffuseTexture2 : TEXTURE_1;
sampler diffuseSampler2 = sampler_state
{
   Texture = <diffuseTexture2>;
   AddressU      = WRAP;
   AddressV      = WRAP;
   AddressW      = WRAP;
   MinFilter     = ANISOTROPIC;
   MagFilter     = ANISOTROPIC;
   MipFilter     = ANISOTROPIC;
   MaxAnisotropy = 4;
};
texture  diffuseTexture3 : TEXTURE_2;
sampler diffuseSampler3 = sampler_state
{
   Texture = <diffuseTexture3>;
   AddressU      = WRAP;
   AddressV      = WRAP;
   AddressW      = WRAP;
   MinFilter     = ANISOTROPIC;
   MagFilter     = ANISOTROPIC;
   MipFilter     = ANISOTROPIC;
   MaxAnisotropy = 4;
};
texture  diffuseTexture4 : TEXTURE_3;
sampler diffuseSampler4 = sampler_state
{
   Texture = <diffuseTexture4>;
   AddressU      = WRAP;
   AddressV      = WRAP;
   AddressW      = WRAP;
   MinFilter     = ANISOTROPIC;
   MagFilter     = ANISOTROPIC;
   MipFilter     = ANISOTROPIC;
   MaxAnisotropy = 4;
};

// alpha texture with blending values
texture  alphaTexture : TEXTURE_4;
sampler alphaSampler = sampler_state
{
   Texture = <alphaTexture>;
   AddressU      = WRAP;
   AddressV      = WRAP;
   AddressW      = WRAP;
   MinFilter     = ANISOTROPIC;
   MagFilter     = ANISOTROPIC;
   MipFilter     = ANISOTROPIC;
   MaxAnisotropy = 4;
};

// vertex shader input data structure
struct VSInput
{
   float4 position  : POSITION;
   float3 normal    : NORMAL;
   float2 texCoords : TEXCOORD0;
};

// vertex shader output data structure
struct VSOutput
{
   float4 position  : POSITION;
   float3 normal    : TEXCOORD1;
   float2 texCoords : TEXCOORD0;
};

// vertex shader
VSOutput VSMain(VSInput input)
{
   VSOutput output;
   output.position  = mul(input.position, matrixWorldViewProj);
   output.normal    = normalize(mul(input.normal, matrixWorld));
   output.texCoords = input.texCoords;
   return output;
}

// pixel shader
float4 PSMain(VSOutput input) : COLOR0
{   
   // getting diffuse colors
   float4 diffuse1 = tex2D(diffuseSampler1, input.texCoords);
   float4 diffuse2 = tex2D(diffuseSampler2, input.texCoords);
   float4 diffuse3 = tex2D(diffuseSampler3, input.texCoords);
   float4 diffuse4 = tex2D(diffuseSampler4, input.texCoords);
   // getting blending weights
   float4 alpha = tex2D(alphaSampler, input.texCoords);
   // compute result color from all textures
   float4 resultColor = diffuse1 * alpha.r + diffuse2 * alpha.g + diffuse3 * alpha.b + diffuse4 * alpha.a;
   // return color value
   return resultColor;
}

// effect technique
technique Splatting
{
   pass p0
   {
      VertexShader = compile vs_2_0 VSMain();
      PixelShader  = compile ps_2_0 PSMain();
   }
}

May be you will need multiply color value, and you need add light code (I just don't know how many light sources you use and their types (directional, point or spot)).
Image
Image

Knightmare

 
Posts: 335
Joined: Thu Mar 12, 2009 1:22 am

Re: Terrain texturing shader(splatting)

Postby KronosUK » Fri Feb 12, 2010 8:10 pm

Thanks very much Knightmare I will look at this over the weekend.

KronosUK

 
Posts: 2
Joined: Tue Feb 09, 2010 10:48 pm

Re: Terrain texturing shader(splatting)

Postby Mau » Sat May 15, 2010 2:19 pm

I found this very informative article about terrain texture splatting:

http://www.gamedev.net/reference/articl ... le2238.asp

Now I am trying to fiddle around with this, but since I am new to shader programming (using Blitz3D), it's still quite confusing for me. Is there any working demo code that demonstrates this kind of technique?

Mau

 
Posts: 40
Joined: Thu Apr 29, 2010 10:32 am

Re: Terrain texturing shader(splatting)

Postby Knightmare » Sat May 15, 2010 2:32 pm

Hi!
Xors3d have built-in splatting support for terrains, see here - viewtopic.php?f=7&t=253&start=20#p1448
Image
Image

Knightmare

 
Posts: 335
Joined: Thu Mar 12, 2009 1:22 am

Re: Terrain texturing shader(splatting)

Postby Mau » Sat May 15, 2010 4:38 pm

Is this feature limited to automatically generated terrains only or can it be used with any manually created meshes as well?

Mau

 
Posts: 40
Joined: Thu Apr 29, 2010 10:32 am

Re: Terrain texturing shader(splatting)

Postby Knightmare » Sat May 15, 2010 5:01 pm

Only with engine terrains. But it uses a very simple shader and I can post its code here.
Image
Image

Knightmare

 
Posts: 335
Joined: Thu Mar 12, 2009 1:22 am

Re: Terrain texturing shader(splatting)

Postby Mau » Sat May 15, 2010 6:02 pm

This would be great. It would be very useful if you could post the splatting shader code, please.

I am porting my world editor from B3D to Xors. It allows to create and modify own terrain meshes. Now I am looking for a way to blend textures on that meshes, so using a shader method would be ideal, I think.

BTW: is it possible in any way to use more than four blend textures on a terrain or mesh?

Mau

 
Posts: 40
Joined: Thu Apr 29, 2010 10:32 am

Re: Terrain texturing shader(splatting)

Postby Knightmare » Sat May 15, 2010 6:09 pm

Code: Select all
float4x4 worldViewProjMatrix : MATRIX_WORLDVIEWPROJ;
float4x4 worldViewMatrix     : MATRIX_WORLDVIEW;
float4x4 texture1Matrix      : MATRIX_TEXTURE0;
float4x4 texture2Matrix      : MATRIX_TEXTURE1;
float4x4 texture3Matrix      : MATRIX_TEXTURE2;
float4x4 texture4Matrix      : MATRIX_TEXTURE3;
int      filtering           : TEXTURE_FILTERING;
int      anisotropyLevel     : ANISOTROPY_LEVEL;
bool     haveLightmap        : TERRAIN_LIGHTMAPPED;
float4   fogColor            : FOG_COLOR;
float3   fogRange            : FOG_RANGE;
texture diffuseMap1 : TEXTURE_0;
sampler samplerMap1 = sampler_state
{
    Texture       = <diffuseMap1>;
    ADDRESSU      = WRAP;
    ADDRESSV      = WRAP;
    ADDRESSW      = WRAP;
    MAGFILTER     = filtering;
    MINFILTER     = filtering;
    MIPFILTER     = filtering;
   MAXANISOTROPY = anisotropyLevel;
};
texture diffuseMap2 : TEXTURE_1;
sampler samplerMap2 = sampler_state
{
    Texture       = <diffuseMap2>;
    ADDRESSU      = WRAP;
    ADDRESSV      = WRAP;
    ADDRESSW      = WRAP;
    MAGFILTER     = filtering;
    MINFILTER     = filtering;
    MIPFILTER     = filtering;
   MAXANISOTROPY = anisotropyLevel;
};
texture diffuseMap3 : TEXTURE_2;
sampler samplerMap3 = sampler_state
{
    Texture       = <diffuseMap3>;
    ADDRESSU      = WRAP;
    ADDRESSV      = WRAP;
    ADDRESSW      = WRAP;
    MAGFILTER     = filtering;
    MINFILTER     = filtering;
    MIPFILTER     = filtering;
   MAXANISOTROPY = anisotropyLevel;
};
texture diffuseMap4 : TEXTURE_3;
sampler samplerMap4 = sampler_state
{
    Texture       = <diffuseMap4>;
    ADDRESSU      = WRAP;
    ADDRESSV      = WRAP;
    ADDRESSW      = WRAP;
    MAGFILTER     = filtering;
    MINFILTER     = filtering;
    MIPFILTER     = filtering;
   MAXANISOTROPY = anisotropyLevel;
};
texture diffuseMap5 : TEXTURE_4;
sampler samplerMap5 = sampler_state
{
    Texture       = <diffuseMap5>;
    ADDRESSU      = WRAP;
    ADDRESSV      = WRAP;
    ADDRESSW      = WRAP;
    MAGFILTER     = filtering;
    MINFILTER     = filtering;
    MIPFILTER     = filtering;
   MAXANISOTROPY = anisotropyLevel;
};
texture lightMap : TEXTURE_7;
sampler samplerLightmap = sampler_state
{
    Texture       = <lightMap>;
    ADDRESSU      = WRAP;
    ADDRESSV      = WRAP;
    ADDRESSW      = WRAP;
    MAGFILTER     = filtering;
    MINFILTER     = filtering;
    MIPFILTER     = filtering;
   MAXANISOTROPY = anisotropyLevel;
};
struct VSInput
{
   float4 position  : POSITION0;
   float2 texCoords : TEXCOORD0;
};
struct VSOutput2
{
   float4 position   : POSITION0;
   float2 texCoords1 : TEXCOORD0;
   float2 texCoords2 : TEXCOORD1;
   float2 texCoords3 : TEXCOORD2;
};
struct VSOutput3
{
   float4 position   : POSITION0;
   float2 texCoords1 : TEXCOORD0;
   float2 texCoords2 : TEXCOORD1;
   float2 texCoords3 : TEXCOORD2;
   float2 texCoords4 : TEXCOORD3;
};
struct VSOutput4
{
   float4 position   : POSITION0;
   float2 texCoords1 : TEXCOORD0;
   float2 texCoords2 : TEXCOORD1;
   float2 texCoords3 : TEXCOORD2;
   float2 texCoords4 : TEXCOORD3;
   float2 texCoords5 : TEXCOORD4;
};
struct VSOutput2F
{
   float4 position   : POSITION0;
   float2 texCoords1 : TEXCOORD0;
   float2 texCoords2 : TEXCOORD1;
   float2 texCoords3 : TEXCOORD2;
   float4 position2  : TEXCOORD5;
};
struct VSOutput3F
{
   float4 position   : POSITION0;
   float2 texCoords1 : TEXCOORD0;
   float2 texCoords2 : TEXCOORD1;
   float2 texCoords3 : TEXCOORD2;
   float2 texCoords4 : TEXCOORD3;
   float4 position2  : TEXCOORD5;
};
struct VSOutput4F
{
   float4 position   : POSITION0;
   float2 texCoords1 : TEXCOORD0;
   float2 texCoords2 : TEXCOORD1;
   float2 texCoords3 : TEXCOORD2;
   float2 texCoords4 : TEXCOORD3;
   float2 texCoords5 : TEXCOORD4;
   float4 position2  : TEXCOORD5;
};
float4 LightMap(float2 texCoords)
{
   if(haveLightmap)
   {
      return tex2D(samplerLightmap, texCoords);
   }
   else
   {
      return float4(1.0f, 1.0f, 1.0f, 1.0f);
   }
}
float FogValue(float4 position)
{
   return clamp((fogRange.y - length(position.xyz)) / fogRange.z, 0.0f, 1.0f);
}
void VSMain2(in VSInput IN, out VSOutput2 OUT)
{
   OUT.position   = mul(IN.position,  worldViewProjMatrix);
   OUT.texCoords1 = mul(IN.texCoords, texture1Matrix);
   OUT.texCoords2 = mul(IN.texCoords, texture2Matrix);
   OUT.texCoords3 = IN.texCoords;
}
void VSMain2F(in VSInput IN, out VSOutput2F OUT)
{
   OUT.position   = mul(IN.position,  worldViewProjMatrix);
   OUT.position2  = mul(IN.position,  worldViewMatrix);
   OUT.texCoords1 = mul(IN.texCoords, texture1Matrix);
   OUT.texCoords2 = mul(IN.texCoords, texture2Matrix);
   OUT.texCoords3 = IN.texCoords;
}
void VSMain3(in VSInput IN, out VSOutput3 OUT)
{
   OUT.position   = mul(IN.position,  worldViewProjMatrix);
   OUT.texCoords1 = mul(IN.texCoords, texture1Matrix);
   OUT.texCoords2 = mul(IN.texCoords, texture2Matrix);
   OUT.texCoords3 = mul(IN.texCoords, texture3Matrix);
   OUT.texCoords4 = IN.texCoords;
}
void VSMain3F(in VSInput IN, out VSOutput3F OUT)
{
   OUT.position   = mul(IN.position,  worldViewProjMatrix);
   OUT.position2  = mul(IN.position,  worldViewMatrix);
   OUT.texCoords1 = mul(IN.texCoords, texture1Matrix);
   OUT.texCoords2 = mul(IN.texCoords, texture2Matrix);
   OUT.texCoords3 = mul(IN.texCoords, texture3Matrix);
   OUT.texCoords4 = IN.texCoords;
}
void VSMain4(in VSInput IN, out VSOutput4 OUT)
{
   OUT.position   = mul(IN.position,  worldViewProjMatrix);
   OUT.texCoords1 = mul(IN.texCoords, texture1Matrix);
   OUT.texCoords2 = mul(IN.texCoords, texture2Matrix);
   OUT.texCoords3 = mul(IN.texCoords, texture3Matrix);
   OUT.texCoords4 = mul(IN.texCoords, texture4Matrix);
   OUT.texCoords5 = IN.texCoords;
}
void VSMain4F(in VSInput IN, out VSOutput4F OUT)
{
   OUT.position   = mul(IN.position,  worldViewProjMatrix);
   OUT.position2  = mul(IN.position,  worldViewMatrix);
   OUT.texCoords1 = mul(IN.texCoords, texture1Matrix);
   OUT.texCoords2 = mul(IN.texCoords, texture2Matrix);
   OUT.texCoords3 = mul(IN.texCoords, texture3Matrix);
   OUT.texCoords4 = mul(IN.texCoords, texture4Matrix);
   OUT.texCoords5 = IN.texCoords;
}
float4 PSMain2(in VSOutput2 IN) : COLOR
{
   float4 diffuse1 = tex2D(samplerMap1, IN.texCoords1);
   float4 diffuse2 = tex2D(samplerMap2, IN.texCoords2);
   float4 mask     = tex2D(samplerMap3, IN.texCoords3);
   return (diffuse1 * mask.x + diffuse2 * mask.y) * LightMap(IN.texCoords3);
}
float4 PSMain2F(in VSOutput2F IN) : COLOR
{
   float4 diffuse1 = tex2D(samplerMap1, IN.texCoords1);
   float4 diffuse2 = tex2D(samplerMap2, IN.texCoords2);
   float4 mask     = tex2D(samplerMap3, IN.texCoords3);
   float4 result   = (diffuse1 * mask.x + diffuse2 * mask.y) * LightMap(IN.texCoords3);
   float fog       = FogValue(IN.position2);
   return fogColor * (1.0f - fog) + result * fog;
}
float4 PSMain3(in VSOutput3 IN) : COLOR
{
   float4 diffuse1 = tex2D(samplerMap1, IN.texCoords1);
   float4 diffuse2 = tex2D(samplerMap2, IN.texCoords2);
   float4 diffuse3 = tex2D(samplerMap3, IN.texCoords3);
   float4 mask     = tex2D(samplerMap4, IN.texCoords4);
   return (diffuse1 * mask.x + diffuse2 * mask.y + diffuse3 * mask.z) * LightMap(IN.texCoords4);
}
float4 PSMain3F(in VSOutput3F IN) : COLOR
{
   float4 diffuse1 = tex2D(samplerMap1, IN.texCoords1);
   float4 diffuse2 = tex2D(samplerMap2, IN.texCoords2);
   float4 diffuse3 = tex2D(samplerMap3, IN.texCoords3);
   float4 mask     = tex2D(samplerMap4, IN.texCoords4);
   float4 result   = (diffuse1 * mask.x + diffuse2 * mask.y + diffuse3 * mask.z) * LightMap(IN.texCoords4);
   float fog       = FogValue(IN.position2);
   return fogColor * (1.0f - fog) + result * fog;
}
float4 PSMain4(in VSOutput4 IN) : COLOR
{
   float4 diffuse1 = tex2D(samplerMap1, IN.texCoords1);
   float4 diffuse2 = tex2D(samplerMap2, IN.texCoords2);
   float4 diffuse3 = tex2D(samplerMap3, IN.texCoords3);
   float4 diffuse4 = tex2D(samplerMap4, IN.texCoords4);
   float4 mask     = tex2D(samplerMap5, IN.texCoords5);
   return (diffuse1 * mask.x + diffuse2 * mask.y + diffuse3 * mask.z + diffuse4 * mask.w) * LightMap(IN.texCoords5);
}
float4 PSMain4F(in VSOutput4F IN) : COLOR
{
   float4 diffuse1 = tex2D(samplerMap1, IN.texCoords1);
   float4 diffuse2 = tex2D(samplerMap2, IN.texCoords2);
   float4 diffuse3 = tex2D(samplerMap3, IN.texCoords3);
   float4 diffuse4 = tex2D(samplerMap4, IN.texCoords4);
   float4 mask     = tex2D(samplerMap5, IN.texCoords5);
   float4 result   = (diffuse1 * mask.x + diffuse2 * mask.y + diffuse3 * mask.z + diffuse4 * mask.w) * LightMap(IN.texCoords5);
   float fog       = FogValue(IN.position2);
   return fogColor * (1.0f - fog)+ result * fog;
}
technique Splatting2
{
   pass p0
   {
      AlphaBlendEnable = false;
      VertexShader     = compile vs_2_0 VSMain2();
      PixelShader      = compile ps_2_0 PSMain2();
   }
}
technique Splatting3
{
   pass p0
   {
      AlphaBlendEnable = false;
      VertexShader     = compile vs_2_0 VSMain3();
      PixelShader      = compile ps_2_0 PSMain3();
   }
}
technique Splatting4
{
   pass p0
   {
      AlphaBlendEnable = false;
      VertexShader     = compile vs_2_0 VSMain4();
      PixelShader      = compile ps_2_0 PSMain4();
   }
}
technique Splatting2Fog
{
   pass p0
   {
      AlphaBlendEnable = false;
      VertexShader     = compile vs_2_0 VSMain2F();
      PixelShader      = compile ps_2_0 PSMain2F();
   }
}
technique Splatting3Fog
{
   pass p0
   {
      AlphaBlendEnable = false;
      VertexShader     = compile vs_2_0 VSMain3F();
      PixelShader      = compile ps_2_0 PSMain3F();
   }
}
technique Splatting4Fog
{
   pass p0
   {
      AlphaBlendEnable = false;
      VertexShader     = compile vs_2_0 VSMain4F();
      PixelShader      = compile ps_2_0 PSMain4F();
   }
}

Here are 6 techniques in shader. For 2, 3 and 4 diffuse textures there area techniques both with and without the fog.
Mau wrote:BTW: is it possible in any way to use more than four blend textures on a terrain or mesh?

Yes, you can use more than 4 textures, you just need to modify a shader.
Image
Image

Knightmare

 
Posts: 335
Joined: Thu Mar 12, 2009 1:22 am

Re: Terrain texturing shader(splatting)

Postby Mau » Sun May 16, 2010 1:06 pm

Hm, I can't get it to work correctly. The code below results in a very bright mesh and only the texture of the heighest texture level is shown (which is the rock texture in this case). But it's far to bright.

In the code, I am creating a simple 5x5 dummy terrain plane for testing:

Code: Select all
; Include header file
Include "xors3d.bb"

; set application window caption
xAppTitle "Texture Splatting Test"

xGraphics3D 800, 600, 32, False, True

Cam% = xCreateCamera()
xPositionEntity Cam, 0,5, -5
xTurnEntity     Cam,50,0,0

Terr% = xCreateMesh   ()
Surf% = xCreateSurface(Terr)

;Tex_Terrain% = xLoadTexture("tex_test.jpg")
;xEntityTexture Terr, Tex_Terrain

Tex_Grass%   = xLoadTexture("tex_grass.jpg")
Tex_Dirt%    = xLoadTexture("tex_dirt.jpg")
Tex_Sand%    = xLoadTexture("tex_sand.jpg")
Tex_Rock%    = xLoadTexture("tex_rock.jpg")
Tex_Mask%    = xLoadTexture("tex_mask.png")

FX_Splatting% = xLoadFXFile("texture splatting.fx")
xSetEntityEffect Terr, FX_Splatting
xSetEffectTechnique(Terr, "Splatting4")

; I TRIED THIS FIRST, BUT DIDN'T WORK
;xSetEffectTexture Terr, "diffuseMap1", Tex_Grass, 0
;xSetEffectTexture Terr, "diffuseMap2", Tex_Dirt, 0
;xSetEffectTexture Terr, "diffuseMap3", Tex_Sand, 0
;xSetEffectTexture Terr, "diffuseMap4", Tex_Rock, 0
;xSetEffectTexture Terr, "diffuseMap5", Tex_Mask, 0

xEntityTexture Terr, Tex_Grass,0, 0
xEntityTexture Terr, Tex_Dirt, 0, 1
xEntityTexture Terr, Tex_Sand, 0, 2
xEntityTexture Terr, Tex_Rock, 0, 3
xEntityTexture Terr, Tex_Mask, 0, 4


; CREATE A FLAT PLANE FOR TERRAIN
gTerrCols% = 5
gTerrRows% = 5
gTileSize# = 1.0

u# = 0
v# = 0
x# = -(gTerrCols*gTileSize)/2
y# = 0
z# = -(gTerrRows*gTileSize)/2
Dim vx%(255,255)

; CREATE VERTICES
For row% = 0 To gTerrRows
   For col% = 0 To gTerrCols
      y = Rnd(0,1)
      u = col * (1.0/gTerrCols)
      v = 1.0 - (row * (1.0/gTerrRows))
      vx(col,row) = xAddVertex(Surf, x + col*gTileSize,y,z + row*gTileSize, u,v)
   Next
Next

; CREATE TRIANGLES
For row% = 0 To gTerrRows-1
   For col% = 0 To gTerrCols-1
      xAddTriangle(Surf, vx(col,row),vx(col,row+1),vx(col+1,row+1))
      xAddTriangle(Surf, vx(col,row),vx(col+1,row+1),vx(col+1,row))
   Next
Next

xUpdateNormals Terr




While Not xKeyDown(1)

   If xKeyHit(17) Then gShowWire = Not gShowWire : xWireFrame gShowWire
   
   xTurnEntity Terr,0,.1,0

   xRenderWorld : xFlip

Wend



What I also didn't understand yet is how the mask texture should look like. If you use 3 different terrain textures, they are defined by red, green and blue pixels in the mask, as far as I understand. But what if 4 or 5 different textures are used? What colors in the mask will represent those textures then?

Mau

 
Posts: 40
Joined: Thu Apr 29, 2010 10:32 am

Next

Return to Shaders

Who is online

Users browsing this forum: No registered users and 1 guest

Who is online

In total there is 1 user online :: 0 registered, 0 hidden and 1 guest (based on users active over the past 60 minutes)
Most users ever online was 26 on Tue Jan 12, 2010 2:10 pm

Users browsing this forum: No registered users and 1 guest
Copyright © 2009 Afterburner - Free GPL Template. All Rights Reserved.