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 // Shader based on work by Fabien Sanglard
// Released under GNU FDL license, without invariant (so DFSG-compliant, see // Released under the terms of CC-BY 3.0
// http://wiki.debian.org/DFSGLicenses#Exception)
uniform sampler2D BumpTex; //The bump-map uniform sampler2D BumpTex; //The bump-map
uniform sampler2D DecalTex; //The texture 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 // New bumpmapping
vec3 BumpNorm = vec3(texture2D(BumpTex, gl_TexCoord[0].xy)); varying vec3 lightVec;
//Get the color of the texture varying vec3 halfVec;
vec3 DecalCol = vec3(texture2D(DecalTex, gl_TexCoord[0].xy)); varying vec3 eyeVec;
//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 void main()
float NdotL = max(dot(BumpNorm, LightDirTransformed), 0.0) / 3.0 * 2.1 + 0.5; {
//Calculate the final color gl_FragColor // lookup normal from normal map, move from [0,1] to [-1, 1] range, normalize
vec3 diffuse = NdotL * passcolor.xyz * DecalCol; vec3 normal = 2.0 * texture2D (BumpTex, gl_TexCoord[0].st).rgb - 1.0;
//Set the color of the fragment... If you want specular lighting or other types add it here normal = normalize (normal);
gl_FragColor = vec4(diffuse, passcolor.w);
// 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 // Shader based on work by Fabien Sanglard
// Released under GNU FDL license, without invariant (so DFSG-compliant, see // Released under the terms of CC-BY 3.0
// http://wiki.debian.org/DFSGLicenses#Exception)
varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;
uniform vec3 lightdir;
void main()
{
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; 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; int bumptex = 1;
services->setPixelShaderConstant("BumpTex", (float*)&bumptex, 1); services->setPixelShaderConstant("BumpTex", (float*)&bumptex, 1);
// TODO: check the position of the sun // 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
You have to calculate the light position in (model)view Space. It can be done, by transforming the light positions and rotations // comes from the camera gives good results
with the modelviewmatrix, after the camera is set. You should do this calculations before the shader runs, but it is also possible const float lightdir[] = {0.0f, 0.0f, -1.0f};
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};
services->setVertexShaderConstant("lightdir", lightdir, 3); services->setVertexShaderConstant("lightdir", lightdir, 3);
} }
}; };