Hi guys,
I come from the "DarkGDK Realm" and I hope someone here can help me out with a shader
I know
Shadow Mapping can be a complex subject, but I was following a tutorial for XNA and everything worked fine until now.
I can't really adress what's wrong, but I'll try to descirbe:
First of all, here's my shader:
//------- Constants --------
float4x4 xWorldViewProjection : WORLDVIEWPROJECTION;
float4x4 xLightWorldViewProjection : WORLDVIEWPROJECTION;
float4x4 xRot : WORLDINVERSETRANSPOSE;
float4 xLightPos;
float xLightPower = 2.0f;
float xMaxDepth = 100.0f;
//------- Texture Samplers --------
Texture xColoredTexture < string Name = ""; >;
sampler ColoredTextureSampler = sampler_state
{
texture = <xColoredTexture> ;
magfilter = LINEAR;
minfilter = LINEAR;
mipfilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
Texture xShadowMap < string Name = ""; >;
sampler ShadowMapSampler = sampler_state
{
texture = <xShadowMap> ;
magfilter = LINEAR;
minfilter = LINEAR;
mipfilter = LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
//------ structs -------
struct SMapVertexToPixel
{
float4 Position : POSITION;
float3 Position2D : TEXCOORD0;
};
struct SMapPixelToFrame
{
float4 Color : COLOR0;
};
struct SSceneVertexToPixel
{
float4 Position : POSITION;
float4 ShadowMapSamplingPos : TEXCOORD0;
float4 RealDistance : TEXCOORD1;
float2 TexCoords : TEXCOORD2;
float3 Normal : TEXCOORD3;
float3 Position3D : TEXCOORD4;
};
struct SScenePixelToFrame
{
float4 Color : COLOR0;
};
//------- Vertex Shaders --------
SMapVertexToPixel ShadowMapVertexShader( float4 inPos : POSITION)
{
SMapVertexToPixel Output = (SMapVertexToPixel)0;
Output.Position = mul(inPos, xLightWorldViewProjection);
Output.Position2D = Output.Position;
return Output;
}
SSceneVertexToPixel ShadowedSceneVertexShader( float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL)
{
SSceneVertexToPixel Output = (SSceneVertexToPixel)0;
Output.Position = mul(inPos, xWorldViewProjection);
Output.ShadowMapSamplingPos = mul(inPos, xLightWorldViewProjection);
Output.RealDistance = Output.ShadowMapSamplingPos.z/xMaxDepth;
Output.TexCoords = inTexCoords;
Output.Normal = mul(inNormal, xRot);
Output.Position3D = inPos;
return Output;
}
//------- Pixel Shaders --------
float DotProduct(float4 LightPos, float3 Pos3D, float3 Normal)
{
float3 LightDir = normalize(LightPos - Pos3D);
return dot(LightDir, Normal);
}
SMapPixelToFrame ShadowMapPixelShader(SMapVertexToPixel PSIn)
{
SMapPixelToFrame Output = (SMapPixelToFrame)0;
Output.Color = PSIn.Position2D.z/xMaxDepth;
return Output;
}
SScenePixelToFrame ShadowedScenePixelShader(SSceneVertexToPixel PSIn)
{
SScenePixelToFrame Output = (SScenePixelToFrame)0;
float2 ProjectedTexCoords;
ProjectedTexCoords[0] = PSIn.ShadowMapSamplingPos.x/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
ProjectedTexCoords[1] = -PSIn.ShadowMapSamplingPos.y/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
if ((saturate(ProjectedTexCoords.x) == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords.y) == ProjectedTexCoords.y))
{
float StoredDepthInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).x;
if ((PSIn.RealDistance.x - 1.0f/100.0f) <= StoredDepthInShadowMap)
{
float DiffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal);
float4 ColorComponent = tex2D(ColoredTextureSampler, PSIn.TexCoords);
Output.Color = ColorComponent*DiffuseLightingFactor*xLightPower;
}
}
return Output;
}
//------- Techniques --------
technique ShadowMap
{
pass Pass0
{
VertexShader = compile vs_2_0 ShadowMapVertexShader();
PixelShader = compile ps_2_0 ShadowMapPixelShader();
}
}
technique ShadowedScene
{
pass Pass0
{
VertexShader = compile vs_2_0 ShadowedSceneVertexShader();
PixelShader = compile ps_2_0 ShadowedScenePixelShader();
}
}
Since DarkGDK commands are almost the same as DBPro, I'll post my code here. (Sould not be too hard to understand)
#include "DarkGDK.h"
int ScreenWidth = 800, ScreenHeight = 600, ScreenDepth = 32;
float DebugCamSpeed = 0.4f;
int UserCam = 0, LightCam = 1;
// prototypes
void DebugInput ( );
void DebugOutput ( );
// main entry point
void DarkGDK ( void )
{
// setup
dbSyncOn ( );
dbSyncRate ( 0 );
dbSetWindowPosition ( 0, 0 );
dbSetDisplayModeVSync ( ScreenWidth, ScreenHeight, ScreenDepth, 0 );
dbColorBackdrop ( 0 );
dbBackdropOn ( );
dbAutoCamOff ( );
// objects
int light = 1;
dbMakeObjectSphere ( light, 2 );
int ground = 10;
dbMakeObjectBox ( ground, 100, 1, 100 );
dbPositionObject ( ground, 0, 0, 0 );
int cube = 20;
dbMakeObjectCube ( cube, 5 );
dbPositionObject ( cube, 30, 3, 0 );
int sphere = 30;
dbMakeObjectSphere ( sphere, 10 );
dbPositionObject ( sphere, -30, 10, 0 );
int box = 40;
dbMakeObjectBox ( box, 20, 40, 20 );
dbPositionObject ( box, 0, 20, 30 );
// camera
dbPositionCamera ( UserCam, 0, 10, -50 );
// effect
int effect = 1;
dbLoadEffect ( "Shadow.fx", effect, 0 );
// light
float lx = -50, ly = 50, lz = 50,
lax = 45, lay = 135, laz = 0;
dbPositionObject ( light, lx, ly, lz );
int VL = 1;
dbMakeVector3 ( VL );
dbSetVector3 ( VL, lx, ly, lz );
dbSetEffectConstantVector ( effect, "xLightPos", VL );
int LightImage = 100;
dbMakeCamera ( LightCam );
dbColorBackdrop ( LightCam, dbRGB ( 255, 255, 255 ) );
dbSetCameraToImage ( LightCam, 100, 256, 256 );
dbPositionCamera ( LightCam, lx, ly, lz );
dbRotateCamera ( LightCam, lax, lay, laz );
// textures
int dirt = 5;
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 );
// set effects
dbSetObjectEffect ( box, effect );
dbSetObjectEffect ( cube, effect );
dbSetObjectEffect ( sphere, effect );
dbSetObjectEffect ( ground, effect );
// main loop
while ( LoopGDK ( ) )
{
// effect update
// pass 1 - depth map
dbSetEffectTechnique ( effect, "ShadowMap" );
dbSyncMask ( 1 << LightCam );
dbFastSync ();
// pass 2 - scene
dbSetEffectTechnique ( effect, "ShadowedScene" );
dbSyncMask ( 1 << UserCam );
// 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 cx = dbCameraPositionX(UserCam),
cy = dbCameraPositionY(UserCam),
cz = dbCameraPositionZ(UserCam),
cax = dbCameraAngleX(UserCam),
cay = dbCameraAngleY(UserCam),
caz = dbCameraAngleZ(UserCam);
cax += dbMouseMoveY();
cay += dbMouseMoveX();
if ( cax > 80 ) cax = 80;
if ( cax < -80 ) cax = -80;
dbPositionCamera ( UserCam, cx, cy, cz );
dbRotateCamera ( UserCam, cax, cay, caz );
if ( dbKeyState ( 200 ) )
dbMoveCamera ( UserCam, DebugCamSpeed );
if ( dbKeyState ( 208 ) )
dbMoveCamera ( UserCam, -DebugCamSpeed );
}
void DebugOutput ( )
{
dbInk ( dbRGB ( 255, 0, 0 ), 0 );
dbText ( 0, 0, dbStr( dbScreenFPS() ) );
}
Now the problem is this:
The Depth-Map pass works fine, because I can see it in the pasted image when pressing '1'.
This image is then passed back to the shader (for use in second technique) through texture stage 1 of the objects. (texture stage 0 is the color-texture)
But the objects are not drawn after the second pass! (I can only see the small sphere that represents the light and has no effect assigned to it)
So I guess the problem is in the 'ShadowedScene' technique/pass!
Any help is greatly appreciated.
(Edit: Screenshot attached.)
Now the plot thickens, the fps decreases, and the awesomeness goes through the roof.