Add new fixed normal map shader, thanks to Fabien Sanglard\! (Only for single-UV-mapping atm, i.e. applies to minigolf balls but not overworld columns)

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10669 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2012-01-15 16:37:15 +00:00
parent cd6185c2ee
commit df0232456d
4 changed files with 97 additions and 54 deletions

Binary file not shown.

View File

@ -1,26 +1,42 @@
// By http://content.gpwiki.org/index.php/OpenGL:Tutorials:GLSL_Bump_Mapping
// Released under GNU FDL license, without invariant (so DFSG-compliant, see
// http://wiki.debian.org/DFSGLicenses#Exception)
// Shader based on work by Fabien Sanglard
// Released under the terms of CC-BY 3.0
uniform sampler2D BumpTex; //The bump-map
uniform sampler2D DecalTex; //The texture
varying vec4 passcolor; //Receiving the vertex color from the vertex shader
varying vec3 LightDir; //Receiving the transformed light direction
void main()
{
vec4 LightDirTransformed4 = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(LightDir[0], LightDir[1], LightDir[2], 0);
vec3 LightDirTransformed = vec3(LightDirTransformed4[0], LightDirTransformed4[1], LightDirTransformed4[2]);
//Get the color of the bump-map
vec3 BumpNorm = vec3(texture2D(BumpTex, gl_TexCoord[0].xy));
//Get the color of the texture
vec3 DecalCol = vec3(texture2D(DecalTex, gl_TexCoord[0].xy));
//Expand the bump-map into a normalized signed vector
BumpNorm = (BumpNorm -0.5) * 2.0;
//Find the dot product between the light direction and the normal
float NdotL = max(dot(BumpNorm, LightDirTransformed), 0.0) / 3.0 * 2.1 + 0.5;
//Calculate the final color gl_FragColor
vec3 diffuse = NdotL * passcolor.xyz * DecalCol;
//Set the color of the fragment... If you want specular lighting or other types add it here
gl_FragColor = vec4(diffuse, passcolor.w);
}
uniform sampler2D DecalTex; //The texture
// New bumpmapping
varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;
void main()
{
// lookup normal from normal map, move from [0,1] to [-1, 1] range, normalize
vec3 normal = 2.0 * texture2D (BumpTex, gl_TexCoord[0].st).rgb - 1.0;
normal = normalize (normal);
// compute diffuse lighting
float lamberFactor= max (dot (lightVec, normal), 0.0) ;
vec4 diffuseMaterial;
vec4 diffuseLight;
// compute specular lighting
vec4 specularMaterial ;
vec4 specularLight ;
float shininess ;
// compute ambient
vec4 ambientLight = vec4(0.3, 0.3, 0.3, 0.0);
if (lamberFactor > 0.0)
{
diffuseMaterial = texture2D (DecalTex, gl_TexCoord[0].st);
diffuseLight = vec4(0.7, 0.7, 0.7, 0.0);
gl_FragColor = diffuseMaterial * diffuseLight * lamberFactor ;
}
gl_FragColor += ambientLight;
}

View File

@ -1,24 +1,54 @@
// By http://content.gpwiki.org/index.php/OpenGL:Tutorials:GLSL_Bump_Mapping
// Released under GNU FDL license, without invariant (so DFSG-compliant, see
// http://wiki.debian.org/DFSGLicenses#Exception)
// Shader based on work by Fabien Sanglard
// Released under the terms of CC-BY 3.0
varying vec4 passcolor; //The vertex color passed
varying vec3 LightDir; //The transformed light direction, to pass to the fragment shader
attribute vec3 tangent; //The inverse tangent to the geometry
attribute vec3 binormal; //The inverse binormal to the geometry
uniform vec3 lightdir; //The direction the light is shining
void main()
{
//Put the color in a varying variable
passcolor = gl_Color;
//Put the vertex in the position passed
gl_Position = ftransform();
//Construct a 3x3 matrix from the geometrys inverse tangent, binormal, and normal
mat3 rotmat = mat3(tangent,binormal,gl_Normal);
//Rotate the light into tangent space
LightDir = rotmat * normalize(lightdir);
//Normalize the light
normalize(LightDir);
//Use the first set of texture coordinates in the fragment shader
gl_TexCoord[0] = gl_MultiTexCoord0;
}
varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;
uniform vec3 lightdir;
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
// Building the matrix Eye Space -> Tangent Space
vec3 n = normalize (gl_NormalMatrix * gl_Normal);
vec3 t = normalize (gl_NormalMatrix * gl_MultiTexCoord1.xyz); // tangent
vec3 b = cross (n, t);
vec3 vertexPosition = vec3(gl_ModelViewMatrix * gl_Vertex);
// transform light and half angle vectors by tangent basis
vec3 v;
v.x = dot (lightdir, t);
v.y = dot (lightdir, b);
v.z = dot (lightdir, n);
lightVec = normalize (v);
v.x = dot (vertexPosition, t);
v.y = dot (vertexPosition, b);
v.z = dot (vertexPosition, n);
eyeVec = normalize (v);
vertexPosition = normalize(vertexPosition);
// Normalize the halfVector to pass it to the fragment shader
// No need to divide by two, the result is normalized anyway.
// vec3 halfVector = normalize((vertexPosition + lightDir) / 2.0);
vec3 halfVector = normalize(vertexPosition + lightdir);
v.x = dot (halfVector, t);
v.y = dot (halfVector, b);
v.z = dot (halfVector, n);
// No need to normalize, t,b,n and halfVector are normal vectors.
//normalize (v);
halfVec = v ;
gl_Position = ftransform();
}

View File

@ -62,13 +62,10 @@ public:
int bumptex = 1;
services->setPixelShaderConstant("BumpTex", (float*)&bumptex, 1);
// TODO: check the position of the sun
/*
You have to calculate the light position in (model)view Space. It can be done, by transforming the light positions and rotations
with the modelviewmatrix, after the camera is set. You should do this calculations before the shader runs, but it is also possible
to pass the camera matrix (calculation in modelviewspace) or ModelMatrix (calculation in WorldSpace) to a shader.
*/
const float lightdir[] = {-0.5f, -0.5f, -1.0f};
// We could calculate light direction as coming from the sun (then we'd need to
// transform it into camera space). But I find that pretending light
// comes from the camera gives good results
const float lightdir[] = {0.0f, 0.0f, -1.0f};
services->setVertexShaderConstant("lightdir", lightdir, 3);
}
};