Add fog support to water shader

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11184 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria
2012-05-04 01:33:13 +00:00
parent 05e467fb87
commit 157081edf2
4 changed files with 158 additions and 3 deletions

View File

@@ -0,0 +1,75 @@
// Shader based on work by Fabien Sanglard
// Released under the terms of CC-BY 3.0
uniform sampler2D BumpTex1; // Normal map 1
uniform sampler2D BumpTex2; // Normal map 2
uniform sampler2D DecalTex; //The texture
uniform vec2 delta1;
uniform vec2 delta2;
varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;
varying vec4 coord;
uniform vec4 fogColor;
uniform float fogFrom;
uniform float fogTo;
void main()
{
// lookup normal from normal map, move from [0,1] to [-1, 1] range, normalize
vec3 normal = 2.0 * texture2D (BumpTex1, gl_TexCoord[0].st + delta1).rgb - 1.0;
vec3 normal2 = 2.0 * texture2D (BumpTex2, gl_TexCoord[0].st + delta2).rgb - 1.0;
// scale normals
normal.y = 4.0*normal.y;
normal2.y = 4.0*normal2.y;
normal = (normalize(normal) + normalize(normal2))/2.0;
// compute diffuse lighting
float lamberFactor = max (dot (lightVec, normal), 0.0);
vec4 diffuseMaterial;
vec4 diffuseLight;
diffuseMaterial = texture2D (DecalTex, gl_TexCoord[0].st + vec2(delta1.x, 0.0));
diffuseLight = vec4(1.0, 1.0, 1.0, 1.0);
//if (lamberFactor < 0.7)
//{
// lamberFactor = 0.0;
//}
gl_FragColor = diffuseMaterial * (0.3 + lamberFactor*0.7);
// specular (phong)
vec3 R = normalize(reflect(lightVec, normal));
float specular = max(dot(R,eyeVec),0.0);
if (specular > 0.0)
{
// weak specular
specular = specular*specular;
specular = specular*specular;
float specular_weak = specular*0.05;
gl_FragColor += vec4(specular_weak, specular_weak, specular_weak, 0.0);
// strong specular
specular = specular*specular;
float specular_strong = specular*0.3;
gl_FragColor += vec4(specular_strong, specular_strong, specular_strong, 0.0);
}
if (coord.z > fogTo)
{
gl_FragColor = fogColor;
}
else if (coord.z > fogFrom)
{
float fogIntensity = (coord.z - fogFrom) / (fogTo - fogFrom);
gl_FragColor = fogIntensity*fogColor + (1.0 - fogIntensity)*gl_FragColor;
}
}

View File

@@ -0,0 +1,49 @@
// Shader based on work by Fabien Sanglard
// Released under the terms of CC-BY 3.0
varying vec3 lightVec;
varying vec3 halfVec;
varying vec3 eyeVec;
varying vec4 coord;
uniform vec3 lightdir;
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
// Building the matrix Eye Space -> Tangent Space
vec3 n = normalize (gl_NormalMatrix * gl_Normal);
// gl_MultiTexCoord1.xyz
vec3 t = normalize (gl_NormalMatrix * vec3(1.0, 0.0, 0.0)); // 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);
vertexPosition = normalize(vertexPosition);
eyeVec = normalize(-vertexPosition); // we are in Eye Coordinates, so EyePos is (0,0,0)
// 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();
coord = gl_Position;
}

View File

@@ -80,10 +80,16 @@ class WaterShaderProvider : public video::IShaderConstantSetCallBack
float m_dx_1, m_dy_1, m_dx_2, m_dy_2;
float m_water_shader_speed_1;
float m_water_shader_speed_2;
bool m_fog;
public:
LEAK_CHECK()
void enableFog(bool enable)
{
m_fog = enable;
}
WaterShaderProvider(float water_shader_speed_1,
float water_shader_speed_2)
@@ -95,6 +101,8 @@ public:
m_water_shader_speed_1 = water_shader_speed_1/100.0f;
m_water_shader_speed_2 = water_shader_speed_2/100.0f;
m_fog = false;
}
virtual void OnSetConstants(
@@ -132,6 +140,23 @@ public:
services->setVertexShaderConstant("delta1", &m_dx_1, 2);
services->setVertexShaderConstant("delta2", &m_dx_2, 2);
if (m_fog)
{
Track* t = World::getWorld()->getTrack();
float fogStart = t->getFogStart();
services->setPixelShaderConstant("fogFrom", (float*)&fogStart, 1);
float fogEnd = t->getFogEnd();
services->setPixelShaderConstant("fogTo", (float*)&fogEnd, 1);
video::SColor fogColor = t->getFogColor();
float fogColorVec[] = {fogColor.getRed()/255.0f,
fogColor.getGreen()/255.0f,
fogColor.getBlue()/255.0f, 1.0f};
services->setVertexShaderConstant("fogColor", fogColorVec, 4);
}
}
};
@@ -1090,8 +1115,11 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
m->setTexture(1, irr_driver->getTexture(file_manager->getTextureFile("waternormals.jpg")));
m->setTexture(2, irr_driver->getTexture(file_manager->getTextureFile("waternormals2.jpg")));
const char* vertex_shader = "shaders/water.vert";
const char* pixel_shader = "shaders/water.frag";
bool fog = World::getWorld()->getTrack()->isFogEnabled();
const char* vertex_shader = (fog ? "shaders/water_fog.vert" : "shaders/water.vert");
const char* pixel_shader = (fog ? "shaders/water_fog.frag" : "shaders/water.frag");
((WaterShaderProvider*)m_shaders[WATER_SHADER])->enableFog(fog);
// Material and shaders
IGPUProgrammingServices* gpu =

View File

@@ -457,7 +457,10 @@ public:
// ------------------------------------------------------------------------
ParticleKind* getSkyParticles () { return m_sky_particles; }
// ------------------------------------------------------------------------
bool isFogEnabled() const { return m_use_fog; }
bool isFogEnabled() const { return m_use_fog; }
float getFogStart() const { return m_fog_start; }
float getFogEnd() const { return m_fog_end; }
video::SColor getFogColor() const { return m_fog_color; }
// ------------------------------------------------------------------------
/** Whether this is an "internal" track. If so it won't be offered
* in the track seelction screen. */