Thanks!
Yes, it was lots of work, but very satisfying now
Here is the code:
Main.cpp
// SHADOW MAPPING DEMO
// =================================================================
// Sebastian Pauli, Oct 2009
#include "DarkGDK.h"
bool ShowHelp = true;
int ScreenWidth = 800, ScreenHeight = 600, ScreenDepth = 32;
int UserCam = 0,
LightCam = 1,
light[3] = { 1, 2, 3 },
ground = 10,
cube = 20,
sphere = 30,
box = 40,
plane = 50,
effect = 1,
LightImage = 100,
dirt = 5,
spot = 0,
spot1 = 6,
spot2 = 7,
LightView[3] = { 10, 11, 12 },
ShadowMapSize = 512;
float LightPos[3][3] = { { -50, 40, -50,},
{ 0, 40, 0 },
{ 50, 40, 50 } };
float LightTarget[3][3] = { { 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 } };
float LightPower[3] = { 1.0f, 1.0f, 1.0f };
float angle = 0.0f,
distance = 70.0f,
zoom = 150.0f;
// prototypes
void DebugInput ( );
void DebugOutput ( );
void PrintShaderErrors ( );
void PrintHelp ( );
// main entry point
void DarkGDK ( void )
{
// setup
dbSyncOn ( );
dbSyncRate ( 0 );
dbSetWindowTitle ( "Pauli's Shadow Mapping Demo" );
dbSetWindowPosition ( 0, 0 );
dbSetDisplayModeVSync ( ScreenWidth, ScreenHeight, ScreenDepth, 0 );
dbMaximizeWindow ( );
dbColorBackdrop ( 0 );
dbBackdropOn ( );
dbAutoCamOff ( );
dbHideMouse ( );
dbSetTextSize ( 25 );
// objects
dbMakeObjectSphere ( light[0], 2 );
dbMakeObjectSphere ( light[1], 2 );
dbMakeObjectSphere ( light[2], 2 );
dbMakeObjectBox ( ground, 150, 1, 150 );
dbPositionObject ( ground, 0, 0, 0 );
dbMakeObjectCube ( cube, 5 );
dbPositionObject ( cube, 30, 3, 0 );
dbMakeObjectSphere ( sphere, 10 );
dbPositionObject ( sphere, -30, 10, 0 );
dbMakeObjectBox ( box, 20, 40, 20 );
dbPositionObject ( box, 0, 20, 30 );
// camera
dbRotateCamera ( UserCam, 45, 45, 0 );
// effect
dbLoadEffect ( "ShadowMappingSpot3.fx", effect, 0 );
// light
for ( int L = 0; L < 3; L++ )
dbPositionObject ( light[L], LightPos[L][0], LightPos[L][1], LightPos[L][2] );
dbMakeCamera ( LightCam );
dbColorBackdrop ( LightCam, dbRGB ( 255, 255, 255 ) );
dbSetCameraToImage ( LightCam, LightImage, ShadowMapSize, ShadowMapSize );
dbPositionCamera ( LightCam, LightPos[0][0], LightPos[0][1], LightPos[0][2] );
dbPointCamera ( LightCam, LightTarget[0][0], LightTarget[0][1], LightTarget[0][2] );
dbSetCurrentCamera ( UserCam );
// textures
dbLoadImage ( "dirt.png", dirt );
dbTextureObject ( box, 0, dirt );
dbTextureObject ( cube, 0, dirt );
dbTextureObject ( sphere, 0, dirt );
dbTextureObject ( ground, 0, dirt );
// put shadow map in object's stage 1
dbTextureObject ( box, 1, LightImage );
dbTextureObject ( cube, 1, LightImage );
dbTextureObject ( sphere, 1, LightImage );
dbTextureObject ( ground, 1, LightImage );
// apply spot light image to object's stage 2
dbLoadImage ( "spot.png", spot1 );
dbLoadImage ( "spot2.png", spot2 );
spot = spot1;
dbTextureObject ( box, 2, spot );
dbTextureObject ( cube, 2, spot );
dbTextureObject ( sphere, 2, spot );
dbTextureObject ( ground, 2, spot );
// set effects
dbSetObjectEffect ( box, effect );
dbSetObjectEffect ( cube, effect );
dbSetObjectEffect ( sphere, effect );
dbSetObjectEffect ( ground, effect );
// light's view matrix
for ( int L = 0; L < 3; L++ )
dbMakeMatrix4 ( LightView[L] );
while ( LoopGDK ( ) )
{
// lights update & input
if ( dbUpKey ( ) ) // Up
for ( int L = 0; L < 3; L++ )
if ( LightPos[L][1] < 100 )
LightPos[L][1]++;
if ( dbDownKey ( ) ) // Down
for ( int L = 0; L < 3; L++ )
if ( LightPos[L][1] > 5 )
LightPos[L][1]--;
if ( dbRightKey ( ) ) // Right
for ( int L = 0; L < 3; L++ )
if ( LightPower[L] < 3 )
LightPower[L] += 0.02f;
if ( dbLeftKey ( ) ) // Left
for ( int L = 0; L < 3; L++ )
if ( LightPower[L] > 0 )
LightPower[L] -= 0.02f;
if ( dbKeyState ( 17 ) ) // W
distance--;
if ( dbKeyState ( 31 ) ) // S
distance++;
if ( dbKeyState ( 30 ) ) // A
angle--;
if ( dbKeyState ( 32 ) ) // D
angle++;
if ( distance < 1 ) distance = 1;
if ( distance > 500 ) distance = 500;
LightPos[0][0] = dbNewXValue ( 0, dbWrapValue ( angle ), distance );
LightPos[0][2] = dbNewZValue ( 0, dbWrapValue ( angle ), distance );
LightPos[1][0] = dbNewXValue ( 0, dbWrapValue ( angle + 120 ), distance );
LightPos[1][2] = dbNewZValue ( 0, dbWrapValue ( angle + 120 ), distance );
LightPos[2][0] = dbNewXValue ( 0, dbWrapValue ( angle - 120 ), distance );
LightPos[2][2] = dbNewZValue ( 0, dbWrapValue ( angle - 120 ), distance );
for ( int L = 0; L < 3; L++ )
dbPositionObject ( light[L], LightPos[L][0], LightPos[L][1], LightPos[L][2] );
// change spotlight image
if ( dbKeyState ( 15 ) )
{
while ( dbKeyState ( 15 ) ) { }
if ( spot == spot1 ) { spot = spot2; } else { spot = spot1; }
dbTextureObject ( box, 2, spot );
dbTextureObject ( cube, 2, spot );
dbTextureObject ( sphere, 2, spot );
dbTextureObject ( ground, 2, spot );
}
// effect update
int LPos[3] = { 15, 16, 17 },
LTarget[3] = { 18, 19, 20 },
LUp = 21,
LPos4[3] = { 22, 23, 24 };
dbMakeVector3 ( LUp ); dbSetVector3 ( LUp, 0, 1, 0 );
for ( int L = 0; L < 3; L++ )
{
dbMakeVector3 ( LPos[L] ); dbSetVector3 ( LPos[L], LightPos[L][0], LightPos[L][1], LightPos[L][2] );
dbMakeVector3 ( LTarget[L] ); dbSetVector3 ( LTarget[L], LightTarget[L][0], LightTarget[L][1], LightTarget[L][2] );
dbBuildLookAtLHMatrix4 ( LightView[L], LPos[L], LTarget[L], LUp );
dbMakeVector4 ( LPos4[L] ); dbSetVector4 ( LPos4[L], LightPos[L][0], LightPos[L][1], LightPos[L][2], 1 );
}
dbSetEffectConstantMatrix ( effect, "xLightView0", LightView[0] );
dbSetEffectConstantMatrix ( effect, "xLightView1", LightView[1] );
dbSetEffectConstantMatrix ( effect, "xLightView2", LightView[2] );
dbSetEffectConstantVector ( effect, "xLightPos0", LPos4[0] );
dbSetEffectConstantVector ( effect, "xLightPos1", LPos4[1] );
dbSetEffectConstantVector ( effect, "xLightPos2", LPos4[2] );
dbSetEffectConstantFloat ( effect, "xLightPower0", LightPower[0] );
dbSetEffectConstantFloat ( effect, "xLightPower1", LightPower[1] );
dbSetEffectConstantFloat ( effect, "xLightPower2", LightPower[2] );
// pass 1 - depth map
dbSetEffectTechnique ( effect, "ShadowMap" );
dbSyncMask ( 2 );
dbFastSync ( );
// pass 2 - scene
dbSetEffectTechnique ( effect, "ShadowedScene" );
dbSyncMask ( 1 );
// paste depth-map image to screen
if ( dbKeyState ( 2 ) )
dbPasteImage ( LightImage, 0, 0 );
// debug
DebugInput ( );
DebugOutput ( );
// update screen
dbSync ( );
}
// return to windows
return;
}
void DebugInput ( )
{
float cax = dbCameraAngleX(UserCam),
cay = dbCameraAngleY(UserCam),
caz = dbCameraAngleZ(UserCam);
cax += dbMouseMoveY();
cay += dbMouseMoveX();
float wheel = dbMouseMoveZ();
if ( wheel > 0 ) zoom -= 5;
if ( wheel < 0 ) zoom += 5;
if ( cax > 80 ) cax = 80;
if ( cax < 5 ) cax = 5;
dbPositionCamera ( UserCam, 0, 0, 0 );
dbRotateCamera ( UserCam, cax, cay, caz );
if ( zoom < 10 ) zoom = 10;
if ( zoom > 300 ) zoom = 300;
dbMoveCamera ( UserCam, -zoom );
if ( dbKeyState ( 59 ) )
{
while ( dbKeyState ( 59 ) ) { }
if ( ShowHelp ) { ShowHelp = false; } else { ShowHelp = true; }
}
}
void DebugOutput ( )
{
dbInk ( dbRGB ( 255, 0, 0 ), 0 );
dbCenterText ( ScreenWidth / 2, 0, dbStr( dbScreenFPS() ) );
dbSetCursor ( 0, 0 );
PrintHelp ();
PrintShaderErrors ();
}
void PrintShaderErrors ( )
{
dbPerformChecklistForEffectErrors ();
for ( int i = 0; i < dbChecklistQuantity (); i++ )
dbPrint ( dbChecklistString ( i ) );
}
void PrintHelp ( )
{
dbPrint ( "F1 - Help On/Off" );
dbPrint ( "" );
if ( ShowHelp )
{
dbPrint ( "MOUSE - View" );
dbPrint ( "MOUSEWHEEL - Zoom" );
dbPrint ( "W/S - Light distance" );
dbPrint ( "A/D - Light angle" );
dbPrint ( "UP/DOWN - Light height" );
dbPrint ( "LEFT/RIGHT - Light power" );
dbPrint ( "TAB - Change Spotlight Image" );
dbPrint ( "" );
dbPrint ( "ESC - Quit" );
}
}
Now the plot thickens, the fps decreases, and the awesomeness goes through the roof.