|
How do i texture terrain using the vertex normal?
#411144
11/13/12 18:19
11/13/12 18:19
|
Joined: Aug 2005
Posts: 238
Caermundh
OP
Member
|
OP
Member
Joined: Aug 2005
Posts: 238
|
Hi! I am attempting to write a multi-texture terrain shader that will apply either a rock texture or a grass texture based on the normal of the current vertex in the terrain geometry. If the vertex is "flat" (or near flat) with respect to the world space, apply the grass texture to it, if it is not flat (IE a cliff or wall) apply the rock texture to it. As you can see from the attached screenshot, what i have is close but not quite. Im still getting grass halfway up the walls in many areas and in some areas im getting rock where the surface is flat enough it should have grass. Screenshot: [url=http://s1126.beta.photobucket.com/user/caermundh/media/terrain_screenshot.png.html#/user/caermundh/media/terrain_screenshot.png.html?&_suid=135283034745306911133684460592][/url] Here is the shader code i am using:
MATERIAL* drakanterrianmat =
{ skin1 = rock_bmap;
skin2 = grass_bmap;
effect = "const float4x4 matWorldViewProj;
const float4x4 matWorld;
const float4 vecAmbient;
const float4 vecSunDir;
float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 1.0f;
float DiffuseIntensity = 1.0f;
float4 SunColor = {0.9f,0.9f,0.5f,1.0f};
texture entSkin1;
texture mtlSkin1;
texture mtlSkin2;
sampler ColorMapSampler=sampler_state
{ Texture = <entSkin1>;
AddressU = Clamp;
AddressV = Clamp;
};
sampler RockMapSampler=sampler_state
{ Texture = <mtlSkin1>;
AddressU = Wrap;
AddressV = Wrap;
};
sampler GrassMapSampler=sampler_state
{ Texture = <mtlSkin2>;
AddressU = Wrap;
AddressV = Wrap;
};
struct VS_Input
{ float4 InPos :POSITION;
float3 InNormal :NORMAL;
float2 InTex :TEXCOORD0;
};
struct VS_Output
{ float4 OutPos :POSITION;
float2 OutTex :TEXCOORD0;
float3 OutNormal :TEXCOORD1;
float2 OutPMTex :TEXCOORD2;
};
struct PS_Input
{ float2 InTex :TEXCOORD0;
float3 InNormal :TEXCOORD1;
float2 InPMTex :TEXCOORD2;
};
VS_Output vs(VS_Input input)
{ VS_Output output;
output.OutPos=mul(input.InPos,matWorldViewProj);
output.OutNormal=normalize(mul(input.InNormal,matWorld));
output.OutTex = input.InTex*512;
output.OutPMTex = input.InTex;
return output;
}
float4 ps(PS_Input input) : COLOR0
{ float3 Normal = normalize(input.InNormal);
float Orientation = dot(float3(0,1,0),Normal);
float4 Color = tex2D(ColorMapSampler,input.InPMTex);
float4 Ambient = AmbientIntensity*vecAmbient;
float4 Diffuse = DiffuseIntensity*saturate(dot(vecSunDir,Normal));
float4 ReturnTexture;
Diffuse *= SunColor;
if(Orientation>0.75)
{ ReturnTexture = tex2D(GrassMapSampler, input.InTex);
}
else
{ ReturnTexture = tex2D(RockMapSampler, input.InTex);
}
return (Ambient+Diffuse)*ReturnTexture;
}
technique ApplyTextures
{ pass P0
{ VertexShader = compile vs_2_0 vs();
PixelShader = compile ps_2_0 ps();
}
}";
}
To be honest im more than a bit fuzzy on how exatly normals work to begin with. Can someone tell me how to fix this shader so it does what its supposed to do?
|
|
|
Re: How do i texture terrain using the vertex normal?
[Re: Caermundh]
#411152
11/13/12 19:17
11/13/12 19:17
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
I can try to fix it but it would be a great help if you upload a very small test-project which includes a terrain file, the shader, the textures and a main script to start it.
Last edited by Kartoffel; 11/13/12 19:17.
POTATO-MAN saves the day! - Random
|
|
|
Re: How do i texture terrain using the vertex normal?
[Re: Caermundh]
#411189
11/13/12 22:19
11/13/12 22:19
|
Joined: Jun 2009
Posts: 2,210 Bavaria, Germany
Kartoffel
Expert
|
Expert
Joined: Jun 2009
Posts: 2,210
Bavaria, Germany
|
I thought about triplanar texture mapping which should give pretty good results.
about the test file: I don't think you can upload it here in the forum but you can upload it to a file hoster (like mediafire).
Last edited by Kartoffel; 11/13/12 22:19.
POTATO-MAN saves the day! - Random
|
|
|
Re: How do i texture terrain using the vertex normal?
[Re: Kartoffel]
#411194
11/13/12 23:42
11/13/12 23:42
|
Joined: Aug 2005
Posts: 238
Caermundh
OP
Member
|
OP
Member
Joined: Aug 2005
Posts: 238
|
Ok, heres the modified shader:
MATERIAL* drakanterrianmat =
{ skin1 = rock_bmap;
skin2 = grass_bmap;
effect = "const float4x4 matWorldViewProj;
const float4x4 matWorld;
const float4 vecAmbient;
const float4 vecSunDir;
float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 1.0f;
float DiffuseIntensity = 1.0f;
float4 SunColor = {0.9f,0.9f,0.5f,1.0f};
float Normal_y;
texture entSkin1;
texture mtlSkin1;
texture mtlSkin2;
sampler ColorMapSampler=sampler_state
{ Texture = <entSkin1>;
AddressU = Clamp;
AddressV = Clamp;
};
sampler RockMapSampler=sampler_state
{ Texture = <mtlSkin1>;
AddressU = Wrap;
AddressV = Wrap;
};
sampler GrassMapSampler=sampler_state
{ Texture = <mtlSkin2>;
AddressU = Wrap;
AddressV = Wrap;
};
struct VS_Input
{ float4 InPosition :POSITION;
float3 InNormal :NORMAL;
float2 InTexture :TEXCOORD0;
};
struct VS_Output
{ float4 OutPosition :POSITION;
float2 OutTexture :TEXCOORD0;
float3 OutNormal :TEXCOORD1;
float2 OutBlendTex :TEXCOORD2;
};
struct PS_Input
{ float2 InTexture :TEXCOORD0;
float2 InNormal :TEXCOORD1;
float3 InBlendTex :TEXCOORD2;
};
VS_Output vs(VS_Input Input)
{ VS_Output Output;
Output.OutPosition=mul(Input.InPosition,matWorldViewProj);
Output.OutNormal=normalize(mul(Input.InNormal,matWorld));
Output.OutTexture = Input.InTexture*512;
Output.OutBlendTex = Input.InTexture;
Normal_y = Input.InNormal.y;
return Output;
}
float4 ps(PS_Input Input) : COLOR0
{ float4 Ambient = AmbientIntensity*vecAmbient;
float4 Diffuse = DiffuseIntensity*saturate(dot(vecSunDir,normalize(Input.InNormal)));
float4 Color = tex2D(ColorMapSampler,Input.InBlendTex);
float4 GrassTexture = tex2D(GrassMapSampler, Input.InTexture);
float4 RockTexture = tex2D(RockMapSampler, Input.InTexture);
float4 ReturnTexture = lerp(RockTexture,GrassTexture,Normal_y);
Diffuse *= SunColor;
return (Ambient+Diffuse)*ReturnTexture;
}
technique ApplyTextures
{ pass P0
{ VertexShader = compile vs_2_0 vs();
PixelShader = compile ps_2_0 ps();
}
}";
}
This does not work at all. If i use "float4 ReturnTexture = lerp(RockTexture,GrassTexture,Input.InNormal.y);" instead, i still have grass climbing halfway up the walls.
|
|
|
Re: How do i texture terrain using the vertex normal?
[Re: Caermundh]
#411233
11/14/12 16:24
11/14/12 16:24
|
Joined: Aug 2005
Posts: 238
Caermundh
OP
Member
|
OP
Member
Joined: Aug 2005
Posts: 238
|
@Kartoffel: uploaded a test level to mediafire: http://www.mediafire.com/?7kysisresg7anvsYou can move the camera around with the arrow keys plus the left and right mouse buttons: Left Mouse: move camera foward Right Mouse: move camera backwards Up Arrow: move camera up Down Arrow: move camera down Left arrow: strafe camera left right arrow: strafe camera right
|
|
|
|