Improving terrain shader
Hi all,
Currently I have a bit of a problem to figure something out for my terrain shader. First let me explain a bit about the current workings.
The system I am using a bit of a combination of texture spatting and using detail texturing. I have 1 colortexture, to add the detail I use a lookup table. Each channel represents one of three detail textures. These are then combined in the fragment shaders with normal mapping and then blended with the color texture. It`s a pretty simple system and gives nice results. Here are some screenshots of the terrain in action and a preview of the lookup table and the shaders.
http://img155.imageshack.us/my.php?image=61675359sl3.jpg
http://img132.imageshack.us/my.php?image=81021571zt3.jpg
http://img409.imageshack.us/my.php?image=detailmapbg4.jpg
Vertex shader:
uniform float F_MIN_VIEW_DISTANCE;
uniform float F_MAX_VIEW_DISTANCE;
varying vec2 ColorUV;
varying vec2 DetailUV;
varying vec2 CausticUV;
varying vec2 CoverageUV;
varying float Fog;
varying vec3 lightVec;
varying vec3 viewVec;
vec3 CalculateTangent()
{
vec3 binormal;
vec3 tangent;
vec3 c1 = cross( vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0));
vec3 c2 = cross( vec3(0.0, 1.0, 0.0), vec3(0.0, 1.0, 0.0));
if(length(c1)>length(c2))
{
tangent = c1;
}
else
{
tangent = -c2;
}
tangent = normalize(tangent);
return tangent;
}
void main(void)
{
vec4 Eye = ftransform();
gl_Position = Eye;
Fog = clamp((length(Eye) - F_MIN_VIEW_DISTANCE) / F_MAX_VIEW_DISTANCE, 0.0, 1.0);
ColorUV = gl_MultiTexCoord0.xy;
DetailUV = gl_MultiTexCoord1.xy;
CausticUV = gl_MultiTexCoord2.xy;
CoverageUV = gl_MultiTexCoord3.xy;
vec3 n = normalize(gl_NormalMatrix * vec3(0.0, 1.0, 0.0));
vec3 t = normalize(gl_NormalMatrix * CalculateTangent());
vec3 b = normalize(cross(n, t));
vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
vec3 tmpVec = gl_LightSource[0].position.xyz - vVertex;
vec3 v;
v.x = dot(tmpVec , t);
v.y = dot(tmpVec , b);
v.z = dot(tmpVec , n);
lightVec = v;
vec3 vVec = -vVertex;
v.x = dot(vVec, t);
v.y = dot(vVec, b);
v.z = dot(vVec, n);
viewVec = v;
}
Fragment shader:
uniform sampler2D T_COLORMAP;
uniform sampler2D T_DETAILLOOKUPMAP;
uniform sampler2D T_DETAILMAP1;
uniform sampler2D T_DETAILMAP2;
uniform sampler2D T_DETAILMAP3;
uniform sampler2D T_DETAILNORMALMAP1;
uniform sampler2D T_DETAILNORMALMAP2;
uniform sampler2D T_DETAILNORMALMAP3;
uniform sampler2D T_CAUSTICMAP;
uniform int I_UNDER_WATER;
varying vec2 ColorUV;
varying vec2 DetailUV;
varying vec2 CausticUV;
varying vec2 CoverageUV;
uniform vec4 V_FOG_COLOR;
varying float Fog;
varying vec3 lightVec;
varying vec3 viewVec;
void main(void)
{
vec4 Color = texture2D(T_COLORMAP, ColorUV);
vec4 Weights = texture2D(T_DETAILLOOKUPMAP, CoverageUV);
vec4 Detail1 = texture2D(T_DETAILMAP1, DetailUV);
vec4 Detail2 = texture2D(T_DETAILMAP2, DetailUV);
vec4 Detail3 = texture2D(T_DETAILMAP3, DetailUV);
Weights = Weights / (Weights.x + Weights.y + Weights.z);
vec4 DetailFinal = (Detail1*Weights.x + Detail2*Weights.y + Detail3*Weights.z);
DetailFinal = Color + DetailFinal - 0.5;
if(I_UNDER_WATER == 0)
{
vec3 lVec = normalize(lightVec);
vec3 vVec = normalize(viewVec);
vec3 DetailNormal1 = normalize( texture2D(T_DETAILNORMALMAP1, DetailUV).xyz * 2.0 - 1.0);
vec3 DetailNormal2 = normalize( texture2D(T_DETAILNORMALMAP2, DetailUV).xyz * 2.0 - 1.0);
vec3 DetailNormal3 = normalize( texture2D(T_DETAILNORMALMAP3, DetailUV).xyz * 2.0 - 1.0);
vec3 DetailNormalFinal = normalize( ((DetailNormal1*Weights.x + DetailNormal2*Weights.y + DetailNormal3*Weights.z) * 2.0) - 1.0 );
float diffuse = max( dot(lVec, DetailNormalFinal ), 0.0 );
float specular = pow(clamp(dot(reflect(-lVec, DetailNormalFinal ), vVec), 0.0, 1.0), gl_FrontMaterial.shininess );
vec4 vAmbient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;
vec4 vDiffuse = gl_LightSource[0].diffuse * gl_FrontMaterial.diffuse * diffuse;
vec4 vSpecular = gl_LightSource[0].specular * gl_FrontMaterial.specular * specular;
gl_FragColor = mix( (vAmbient*DetailFinal + vDiffuse*DetailFinal + vSpecular) , V_FOG_COLOR, Fog);
}
else
{
vec4 Caustic = texture2D(T_CAUSTICMAP, CausticUV);
gl_FragColor = mix( DetailFinal + Caustic - 0.5, V_FOG_COLOR, Fog);
}
}
As you can see it now uses all 8 texture units and this is a problem because I need aditional ones for shadowmapping and adding some other stuff. As you can see in the shader I alreay have to compromise when I need to use caustics. Also Want to add parallaxmapping. I have already have a thought on how to fix this but there is one part I just cant figure out. I want to use one texture per detail instead of the 2 required now and the three I want to add parallaxmapping.
I want to create a texture like this:
----------------------------
|********|********|********|
|*Detail*|*Normal*|*Height*|
|********|********|********|
----------------------------
The V of the DetailUV doesnt have to change but Iam having trouble figuring out how to calculate the U. I dont care that the texture is a rectangle.
Any one any Idears?
Greetz
Luuk
ps. Sorry for not using codeblocks:)
[Edited by - Luuk van Venrooij on February 3, 2008 5:47:33 AM]
If you have 4 detail textures why not put them in the different channels of a single texture? red, green, blue, alpha? As a detail texture only needs the values between 0 and 255.
Just a suggestion, and something I was thinking of trying.
Just a suggestion, and something I was thinking of trying.
Multipass rendering would work but would probebly be to costfull. Also the idear with the layers wont work because my I 3 textures per detail. A grayscale color image, normal map and heightmap.
The only problem I have is calculating the U of the detailUV If use the textures Decribed in the above post.
The only problem I have is calculating the U of the detailUV If use the textures Decribed in the above post.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement