Add code to make normal maps work. Joerg: don't worry about this change being done near a release, we have no track atm using this feature, so this code will remain sleeping until, probably, 0.8
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10070 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
f3532da9cd
commit
35aa87674d
23
data/shaders/normalmap.frag
Normal file
23
data/shaders/normalmap.frag
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// 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)
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
//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, LightDir), 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);
|
||||||
|
}
|
24
data/shaders/normalmap.vert
Normal file
24
data/shaders/normalmap.vert
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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)
|
||||||
|
|
||||||
|
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 geometry’s 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;
|
||||||
|
}
|
@ -33,10 +33,37 @@
|
|||||||
#include "io/xml_node.hpp"
|
#include "io/xml_node.hpp"
|
||||||
#include "utils/string_utils.hpp"
|
#include "utils/string_utils.hpp"
|
||||||
|
|
||||||
|
#include <IGPUProgrammingServices.h>
|
||||||
|
#include <IMaterialRendererServices.h>
|
||||||
|
#include <IShaderConstantSetCallBack.h>
|
||||||
|
using namespace irr::video;
|
||||||
|
|
||||||
const unsigned int UCLAMP = 1;
|
const unsigned int UCLAMP = 1;
|
||||||
const unsigned int VCLAMP = 2;
|
const unsigned int VCLAMP = 2;
|
||||||
|
|
||||||
|
|
||||||
|
class NormalMapProvider : public video::IShaderConstantSetCallBack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LEAK_CHECK()
|
||||||
|
|
||||||
|
virtual void OnSetConstants(irr::video::IMaterialRendererServices *services, s32 userData)
|
||||||
|
{
|
||||||
|
// Irrlicht knows this is actually a GLint and makes the conversion
|
||||||
|
int decaltex = 0.0f;
|
||||||
|
services->setPixelShaderConstant("DecalTex", (float*)&decaltex, 1);
|
||||||
|
|
||||||
|
// Irrlicht knows this is actually a GLint and makes the conversion
|
||||||
|
int bumptex = 1.0f;
|
||||||
|
services->setPixelShaderConstant("BumpTex", (float*)&bumptex, 1);
|
||||||
|
|
||||||
|
// TODO: check the position of the sun
|
||||||
|
const float lightdir[] = {0.5f, 0.5f, 1.0f};
|
||||||
|
services->setVertexShaderConstant("lightdir", lightdir, 3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Create a new material using the parameters specified in the xml file.
|
/** Create a new material using the parameters specified in the xml file.
|
||||||
* \param node Node containing the parameters for this material.
|
* \param node Node containing the parameters for this material.
|
||||||
@ -44,7 +71,6 @@ const unsigned int VCLAMP = 2;
|
|||||||
*/
|
*/
|
||||||
Material::Material(const XMLNode *node, int index)
|
Material::Material(const XMLNode *node, int index)
|
||||||
{
|
{
|
||||||
|
|
||||||
node->get("name", &m_texname);
|
node->get("name", &m_texname);
|
||||||
if (m_texname=="")
|
if (m_texname=="")
|
||||||
{
|
{
|
||||||
@ -248,6 +274,7 @@ void Material::init(unsigned int index)
|
|||||||
m_normal_map = false;
|
m_normal_map = false;
|
||||||
m_parallax_map = false;
|
m_parallax_map = false;
|
||||||
m_is_heightmap = false;
|
m_is_heightmap = false;
|
||||||
|
m_normal_map_provider = NULL;
|
||||||
|
|
||||||
for (int n=0; n<EMIT_KINDS_COUNT; n++)
|
for (int n=0; n<EMIT_KINDS_COUNT; n++)
|
||||||
{
|
{
|
||||||
@ -297,6 +324,12 @@ Material::~Material()
|
|||||||
irr_driver->removeTexture(m_texture);
|
irr_driver->removeTexture(m_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_normal_map_provider != NULL)
|
||||||
|
{
|
||||||
|
m_normal_map_provider->drop();
|
||||||
|
m_normal_map_provider = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// If a special sfx is installed (that isn't part of stk itself), the
|
// If a special sfx is installed (that isn't part of stk itself), the
|
||||||
// entry needs to be removed from the sfx_manager's mapping, since other
|
// entry needs to be removed from the sfx_manager's mapping, since other
|
||||||
// tracks might use the same name.
|
// tracks might use the same name.
|
||||||
@ -450,7 +483,7 @@ void Material::setSFXSpeed(SFXBase *sfx, float speed) const
|
|||||||
/** Sets the appropriate flags in an irrlicht SMaterial.
|
/** Sets the appropriate flags in an irrlicht SMaterial.
|
||||||
* \param material The irrlicht SMaterial which gets the flags set.
|
* \param material The irrlicht SMaterial which gets the flags set.
|
||||||
*/
|
*/
|
||||||
void Material::setMaterialProperties(video::SMaterial *m) const
|
void Material::setMaterialProperties(video::SMaterial *m)
|
||||||
{
|
{
|
||||||
// !!======== This method is only called for materials that can be found in
|
// !!======== This method is only called for materials that can be found in
|
||||||
// materials.xml, if you want to set flags for all surfaces, see
|
// materials.xml, if you want to set flags for all surfaces, see
|
||||||
@ -513,14 +546,38 @@ void Material::setMaterialProperties(video::SMaterial *m) const
|
|||||||
}
|
}
|
||||||
if (m_normal_map)
|
if (m_normal_map)
|
||||||
{
|
{
|
||||||
video::ITexture* tex = irr_driver->getTexture(m_normal_map_tex) ;
|
IVideoDriver* video_driver = irr_driver->getVideoDriver();
|
||||||
if (m_is_heightmap)
|
if (video_driver->queryFeature(video::EVDF_ARB_GLSL) &&
|
||||||
|
video_driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0) &&
|
||||||
|
video_driver->queryFeature(video::EVDF_RENDER_TO_TARGET))
|
||||||
{
|
{
|
||||||
irr_driver->getVideoDriver()->makeNormalMapTexture( tex );
|
ITexture* tex = irr_driver->getTexture(m_normal_map_tex);
|
||||||
|
if (m_is_heightmap)
|
||||||
|
{
|
||||||
|
video_driver->makeNormalMapTexture( tex );
|
||||||
|
}
|
||||||
|
m->setTexture(1, tex);
|
||||||
|
|
||||||
|
if (m_normal_map_provider == NULL)
|
||||||
|
{
|
||||||
|
m_normal_map_provider = new NormalMapProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Material and shaders
|
||||||
|
IGPUProgrammingServices* gpu = video_driver->getGPUProgrammingServices();
|
||||||
|
s32 material_type = gpu->addHighLevelShaderMaterialFromFiles(
|
||||||
|
(file_manager->getDataDir() + "shaders/normalmap.vert").c_str(), "main",
|
||||||
|
video::EVST_VS_2_0,
|
||||||
|
(file_manager->getDataDir() + "shaders/normalmap.frag").c_str(), "main",
|
||||||
|
video::EPST_PS_2_0,
|
||||||
|
m_normal_map_provider,
|
||||||
|
video::EMT_SOLID_2_LAYER );
|
||||||
|
m->MaterialType = (E_MATERIAL_TYPE)material_type;
|
||||||
|
m->Lighting = false;
|
||||||
|
m->ZWriteEnable = true;
|
||||||
|
|
||||||
|
modes++;
|
||||||
}
|
}
|
||||||
m->setTexture(1, tex);
|
|
||||||
m->MaterialType = video::EMT_NORMAL_MAP_SOLID;
|
|
||||||
modes++;
|
|
||||||
}
|
}
|
||||||
if (m_parallax_map)
|
if (m_parallax_map)
|
||||||
{
|
{
|
||||||
@ -630,3 +687,5 @@ void Material::adjustForFog(scene::ISceneNode* parent, video::SMaterial *m,
|
|||||||
parent->setMaterialFlag(video::EMF_FOG_ENABLE, m_fog && use_fog);
|
parent->setMaterialFlag(video::EMF_FOG_ENABLE, m_fog && use_fog);
|
||||||
}
|
}
|
||||||
} // adjustForFog
|
} // adjustForFog
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -38,6 +38,8 @@ class XMLNode;
|
|||||||
class SFXBase;
|
class SFXBase;
|
||||||
class ParticleKind;
|
class ParticleKind;
|
||||||
|
|
||||||
|
class NormalMapProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup graphics
|
* \ingroup graphics
|
||||||
*/
|
*/
|
||||||
@ -156,6 +158,9 @@ private:
|
|||||||
|
|
||||||
std::string m_mask;
|
std::string m_mask;
|
||||||
|
|
||||||
|
/** Only used if normal maps are used */
|
||||||
|
NormalMapProvider* m_normal_map_provider;
|
||||||
|
|
||||||
void init (unsigned int index);
|
void init (unsigned int index);
|
||||||
void install (bool is_full_path=false);
|
void install (bool is_full_path=false);
|
||||||
void initCustomSFX(const XMLNode *sfx);
|
void initCustomSFX(const XMLNode *sfx);
|
||||||
@ -168,7 +173,7 @@ public:
|
|||||||
~Material ();
|
~Material ();
|
||||||
|
|
||||||
void setSFXSpeed(SFXBase *sfx, float speed) const;
|
void setSFXSpeed(SFXBase *sfx, float speed) const;
|
||||||
void setMaterialProperties(video::SMaterial *m) const;
|
void setMaterialProperties(video::SMaterial *m);
|
||||||
void adjustForFog(scene::ISceneNode* parent, video::SMaterial *m, bool use_fog) const;
|
void adjustForFog(scene::ISceneNode* parent, video::SMaterial *m, bool use_fog) const;
|
||||||
|
|
||||||
/** Returns the ITexture associated with this material. */
|
/** Returns the ITexture associated with this material. */
|
||||||
@ -253,7 +258,6 @@ public:
|
|||||||
} // getZipperParameter
|
} // getZipperParameter
|
||||||
|
|
||||||
bool isNormalMap() const { return m_normal_map; }
|
bool isNormalMap() const { return m_normal_map; }
|
||||||
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user