Here's what I do:
1. Init player camera and a shadow camera (sun position)
2. Init shadow texture:
ITexture *renderTarget = m_Driver->addRenderTargetTexture(core::dimension2d<u32>(256,256), "rt", ECF_A8R8G8B8);
3. Init shadow map shader:
m_Shader = gpu->addHighLevelShaderMaterialFromFiles( "VERT.vert",
"main",
irr::video::EVST_VS_2_0,
"FRAG.frag",
"main",
irr::video::EPST_PS_2_0,
&callback,
irr::video::EMT_SOLID,
0
);
Callback class:
class MyShaderCallBack : public irr::video::IShaderConstantSetCallBack
{
public:
virtual void OnSetConstants(irr::video::IMaterialRendererServices* services, irr::s32 userData)
{
irr::video::IVideoDriver *driver=services->getVideoDriver();
irr::core::matrix4 tMatrix;
irr::scene::ICameraSceneNode *shadowCam = graphics()->getShadowCamera();
tMatrix = shadowCam->getProjectionMatrix();
tMatrix *= shadowCam->getViewMatrix();
tMatrix *= driver->getTransform(irr::video::ETS_WORLD);
services->setVertexShaderConstant("tMatrix", tMatrix.pointer(), 16);
}
}callback;
Vertex shader for shadow map:
uniform mat4 tMatrix;
varying vec4 ShadowCoord;
void main()
{
gl_Position = ftransform();
ShadowCoord= tMatrix * gl_Vertex;
}
Fragment:
uniform sampler2D ShadowMap;
varying vec4 ShadowCoord;
void main()
{
vec4 Light = vec4(1,1,1,1);
vec2 smTCoords = ShadowCoord.xy / ShadowCoord.w / 2.0 + vec2(0.5, 0.5);
vec2 clampedSMPos = clamp(smTCoords, vec2(0.0, 0.0), vec2(1.0, 1.0));
if(clampedSMPos.x == smTCoords.x && clampedSMPos.y == smTCoords.y)
{
Light = texture2D(ShadowMap,smTCoords);
}
gl_FragColor = Light;
}
4. Main:
m_Driver->beginScene(true, true, 0, exposed);
//////// shadow pass ////////////
m_Scenemanager->setActiveCamera(shadowCam);
m_Driver->setRenderTarget(renderTarget, true, true, video::SColor(255,255,255,255));
shadowCam->render();
list<scene::ISceneNode*>::const_iterator shadedIter;
for(shadedIter=shaded.begin();shadedIter!=shaded.end(); ++shadedIter)
{
scene::ISceneNode* node = (*shadedIter);
video::E_MATERIAL_TYPE tempMat = node->getMaterial(0).MaterialType;
node->setMaterialType((video::E_MATERIAL_TYPE) m_Shader);
node->render();
node->setMaterialType(tempMat);
}
/////// render pass ///////////
m_Scenemanager->setActiveCamera(renderCam);
m_Driver->setRenderTarget(0,true,true,0);
m_Scenemanager->drawAll();
m_Driver->endScene();
Vertex shader for main render:
uniform mat4 tMatrix;
varying vec2 texCoords;
varying float shadowDist;
void main ()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec4 shadowPos=tMatrix*gl_Vertex/256.0;
shadowDist=shadowPos.z/2.0;
texCoords=shadowPos.xy;
texCoords=0.5*texCoords+0.5;
gl_Position = ftransform();
}
Fragment:
uniform sampler2D myTexture0;
uniform sampler2DShadow ShadowMap;
varying vec2 texCoords;
varying float shadowDist;
void main (void)
{
float shadow = shadow2DProj(ShadowMap,vec4(texCoords,0,1)).x;
vec4 color = texture2D(myTexture0, gl_TexCoord[0].st);
color *= shadow;
gl_FragColor = color;
}