// when DEBUG_VIEW is defined, texture using the RGB portion of the
// shadow pass, to verify that projection is correct
//#define DEBUG_VIEW
float Script : STANDARDSGLOBAL <
string UIWidget = "none";
string ScriptClass = "scene";
string ScriptOrder = "standard";
string ScriptOutput = "color";
string Script = "Technique=Main;";
> = 0.8; // version #
float4 ClearColor <
string UIWidget = "color";
string UIName = "background";
> = {0,0,0,0.0};
float ClearDepth = 1.0;
float4 ShadowClearColor <
string UIWidget = "none";
> = {1,1,1,0.0};
/************* "UN-TWEAKABLES," TRACKED BY CPU APPLICATION **************/
float4x4 WorldITXf : WorldInverseTranspose ;
float4x4 WorldViewProjXf : WorldViewProjection ;
float4x4 WorldXf : World ;
float4x4 ViewIXf : ViewInverse ;
float4x4 ViewITXf : ViewInverseTranspose ;
DECLARE_SHADOW_XFORMS("light0",LampViewXf,LampProjXf,ShadowViewProjXf)
DECLARE_SHADOW_BIAS
DECLARE_SHADOW_MAPS(ColorShadMap,ColorShadSampler,ShadDepthTarget,ShadDepthSampler)
///////////////////////////////////////////////////////////////
/// TWEAKABLES ////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
////////////////////////////////////////////// spot light
float3 SpotLightPos : POSITION <
string UIName = "Light Posistion";
string Object = "SpotLight";
string Space = "World";
> = {-1.0f, 1.0f, 0.0f};
float3 SpotLightColor : Diffuse <
string UIName = "Lamp";
string Object = "SpotLight";
string UIWidget = "Color";
> = {0.8f, 1.0f, 0.4f};
float SpotLightIntensity <
string UIName = "Light Intensity";
string UIWidget = "slider";
float UIMin = 0.0;
float UIMax = 12;
float UIStep = 0.1;
> = 1;
float SpotLightCone <
string UIWidget = "slider";
float UIMin = 0.0;
float UIMax = 90.5;
float UIStep = 0.1;
string UIName = "Cone Angle";
> = 45.0f;
static float CosSpotAng = cos(radians(SpotLightCone));
////////////////////////////////////////////// ambient light
float3 AmbiLightColor : Ambient
<
string UIName = "Ambient";
> = {0.07f, 0.07f, 0.07f};
////////////////////////////////////////////// surface attributes
float3 SurfColor : Diffuse
<
string UIName = "Surface";
string UIWidget = "Color";
> = {1.0f, 0.7f, 0.3f};
float Kd
<
string UIWidget = "slider";
float UIMin = 0.0;
float UIMax = 1.5;
float UIStep = 0.01;
string UIName = "Diffuse";
> = 1.0;
float Ks
<
string UIWidget = "slider";
float UIMin = 0.0;
float UIMax = 1.5;
float UIStep = 0.01;
string UIName = "Specular";
> = 1.0;
float SpecExpon : SpecularPower
<
string UIWidget = "slider";
float UIMin = 1.0;
float UIMax = 128.0;
float UIStep = 1.0;
string UIName = "Specular power";
> = 12.0;
////////////////////////////////////////////////////////////////////////////
/// SHADER CODE BEGINS /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
/*********************************************************/
/*********** pixel shader ********************************/
/*********************************************************/
float4 useShadowPS(ShadowingVertexOutput IN) : COLOR
{
#ifdef DEBUG_VIEW
return tex2Dproj(ColorShadSampler,IN.LProj); // show the RGB render instead
#else /*!DEBUG_VIEW */
//
// shading...
//
float3 Nn = normalize(IN.WNormal);
float3 Vn = normalize(IN.WView);
float falloff = 1.0 / dot(IN.LightVec,IN.LightVec);
float3 Ln = normalize(IN.LightVec);
float3 Hn = normalize(Vn + Ln);
float hdn = dot(Hn,Nn);
float ldn = dot(Ln,Nn);
float4 litVec = lit(ldn,hdn,SpecExpon);
ldn = litVec.y * SpotLightIntensity;
float cone = normalize(IN.LProj.xyz).z;
cone = max((float)0,((cone-CosSpotAng)/(((float)1.0)-CosSpotAng)));
float3 ambiContrib = SurfColor * AmbiLightColor;
float3 diffContrib = SurfColor*(Kd*ldn * SpotLightColor);
float3 specContrib = ((ldn * litVec.z * Ks) * SpotLightColor);
float3 result = diffContrib + specContrib;
//
// shadowing.....
//
float4 shadowed = tex2Dproj(ShadDepthSampler,IN.LProj);
return float4((cone*falloff*shadowed.x*result)+ambiContrib,1);
#endif /*!DEBUG_VIEW */
}
////////////////////////////////////////////////////////////////////
/// TECHNIQUES /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
technique Main <
string Script = "Pass=MakeShadow;"
"Pass=UseShadow;";
> {
pass MakeShadow <
string Script = "RenderColorTarget0=ColorShadMap;"
"RenderDepthStencilTarget=ShadDepthTarget;"
"RenderPort=light0;"
"ClearSetColor=ShadowClearColor;"
"ClearSetDepth=ClearDepth;"
"Clear=Color;"
"Clear=Depth;"
"Draw=geometry;";
> {
VertexShader = compile vs_2_0 shadowGenVS(WorldXf,WorldITXf,ShadowViewProjXf);
ZEnable = true;
ZWriteEnable = true;
ZFunc = LessEqual;
CullMode = None;
// no pixel shader
}
pass UseShadow <
string Script = "RenderColorTarget0=;"
"RenderDepthStencilTarget=;"
"RenderPort=;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=ClearDepth;"
"Clear=Color;"
"Clear=Depth;"
"Draw=geometry;";
> {
//VertexShader = compile vs_2_0 mainCamVS();
VertexShader = compile vs_2_0 shadowUseVS(WorldXf,WorldITXf, WorldViewProjXf,
ShadowViewProjXf,ViewIXf,ShadBiasXf, SpotLightPos);
ZEnable = true;
ZWriteEnable = true;
ZFunc = LessEqual;
CullMode = None;
PixelShader = compile ps_2_a useShadowPS();
}
}
/***************************** eof ***/
]]>; \
sampler SampName = sampler_state { \
texture = ; \
AddressU = AddrMode; \
AddressV = AddrMode; \
MipFilter = LINEAR; \
MinFilter = LINEAR; \
MagFilter = LINEAR; \
};
//
// Simple 2D File Textures
//
// example usage: FILE_TEXTURE_2D(GlowMap,GlowSampler,"myfile.dds")
//
#define FILE_TEXTURE_2D(TextureName,SamplerName,Diskfile) FILE_TEXTURE_2D_MODAL(TextureName,SamplerName,(Diskfile),WRAP)
//
// Use this variation of DECLARE_QUAD_TEX() if you want a *scaled* render target
//
// example usage: DECLARE_SIZED_QUAD_TEX(GlowMap,GlowSampler,"A8R8G8B8",1.0)
#define DECLARE_SIZED_QUAD_TEX(TexName,SampName,PixFmt,Multiple) texture TexName : RENDERCOLORTARGET < \
float2 ViewPortRatio = {Multiple,Multiple}; \
int MipLevels = 1; \
string Format = PixFmt ; \
string UIWidget = "None"; \
>; \
sampler SampName = sampler_state { \
texture = ; \
AddressU = CLAMP; \
AddressV = CLAMP; \
MipFilter = POINT; \
MinFilter = LINEAR; \
MagFilter = LINEAR; \
};
//
// Use this macro to easily declare typical color render targets
//
// example usage: DECLARE_QUAD_TEX(ObjMap,ObjSampler,"A8R8G8B8")
#define DECLARE_QUAD_TEX(TextureName,SamplerName,PixelFormat) DECLARE_SIZED_QUAD_TEX(TextureName,SamplerName,(PixelFormat),1.0)
//
// Use this macro to easily declare variable-sized depth render targets
//
// example usage: DECLARE_SIZED_QUAD_DEPTH_BUFFER(DepthMap,"D24S8",0.5)
#define DECLARE_SIZED_QUAD_DEPTH_BUFFER(TextureName,PixelFormat,Multiple) texture TextureName : RENDERDEPTHSTENCILTARGET < \
float2 ViewPortRatio = {Multiple,Multiple}; \
string Format = (PixelFormat); \
string UIWidget = "None"; \
>;
//
// Use this macro to easily declare typical depth render targets
//
// example usage: DECLARE_QUAD_DEPTH_BUFFER(DepthMap,"D24S8")
#define DECLARE_QUAD_DEPTH_BUFFER(TexName,PixFmt) DECLARE_SIZED_QUAD_DEPTH_BUFFER(TexName,PixFmt,1.0)
//
// declare exact-sized arbitrary texture
//
// example usage: DECLARE_SIZED_TEX(BlahMap,BlahSampler,"R32F",128,1)
#define DECLARE_SIZED_TEX(Tex,Samp,Fmt,Wd,Ht) texture Tex : RENDERCOLORTARGET < \
float2 Dimensions = { Wd, Ht }; \
string Format = Fmt ; \
string UIWidget = "None"; \
int miplevels=1;\
>; \
sampler Samp = sampler_state { \
texture = ; \
AddressU = CLAMP; \
AddressV = CLAMP; \
MipFilter = NONE; \
MinFilter = LINEAR; \
MagFilter = LINEAR; \
};
//
// declare exact-sized square texture, as for shadow maps
//
// example usage: DECLARE_SQUARE_QUAD_TEX(ShadMap,ShadObjSampler,"A16R16G16B16F",512)
#define DECLARE_SQUARE_QUAD_TEX(TexName,SampName,PixFmt,Size) DECLARE_SIZED_TEX(TexName,SampName,(PixFmt),Size,Size)
//
// likewise for shadow depth targets
//
// example usage: DECLARE_SQUARE_QUAD_DEPTH_BUFFER(ShadDepth,"D24S8",512)
#define DECLARE_SQUARE_QUAD_DEPTH_BUFFER(TextureName,PixelFormat,Size) texture TextureName : RENDERDEPTHSTENCILTARGET < \
float2 Dimensions = { Size, Size }; \
string Format = (PixelFormat) ; \
string UIWidget = "None"; \
>;
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// Utility Functions ////////
////////////////////////////////////////////////////////////////////////////
//
// Scale inputs for use with texture-based lookup tables. A value ranging from zero to one needs
// a slight scaling and offset to be sure to point at the centers of the first and last pixels
// of that lookup texture. Pass the integer size of the table in TableSize
// For now we'll assume that all tables are 1D, square, or cube-shaped -- all axes of equal size
//
// Cost of this operation for pixel shaders: two const-register
// entries and a MAD (one cycle)
QUAD_REAL scale_lookup(QUAD_REAL Value,const QUAD_REAL TableSize)
{
QUAD_REAL scale = ((TableSize - 1.0)/TableSize);
QUAD_REAL shift = (0.5 / TableSize);
return (scale*Value + shift);
}
QUAD_REAL2 scale_lookup(QUAD_REAL2 Value,const QUAD_REAL TableSize)
{
QUAD_REAL scale = ((TableSize - 1.0)/TableSize);
QUAD_REAL shift = (0.5 / TableSize);
return (scale.xx*Value + shift.xx);
}
QUAD_REAL3 scale_lookup(QUAD_REAL3 Value,const QUAD_REAL TableSize)
{
QUAD_REAL scale = ((TableSize - 1.0)/TableSize);
QUAD_REAL shift = (0.5 / TableSize);
return (scale.xxx*Value + shift.xxx);
}
// pre-multiply and un-pre-mutliply functions. The precision
// of thse operatoions is often limited to 8-bit so don't
// always count on them!
// The macro value of NV_ALPHA_EPSILON, if defined, is used to
// avoid IEEE "NaN" values that may occur when erroneously
// dividing by a zero alpha (thanks to Pete Warden @ Apple
// Computer for the suggestion in GPU GEMS II)
// multiply color by alpha to turn an un-premultipied
// pixel value into a premultiplied one
QUAD_REAL4 premultiply(QUAD_REAL4 C)
{
return QUAD_REAL4((C.w*C.xyz),C.w);
}
#define NV_ALPHA_EPSILON 0.0001
// given a premultiplied pixel color, try to undo the premultiplication.
// beware of precision errors
QUAD_REAL4 unpremultiply(QUAD_REAL4 C)
{
#ifdef NV_ALPHA_EPSILON
QUAD_REAL a = C.w + NV_ALPHA_EPSILON;
return QUAD_REAL4((C.xyz / a),C.w);
#else /* ! NV_ALPHA_EPSILON */
return QUAD_REAL4((C.xyz / C.w),C.w);
#endif /* ! NV_ALPHA_EPSILON */
}
/////////////////////////////////////////////////////////////////////////////////////
// Structure Declaration ////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
struct QuadVertexOutput {
QUAD_REAL4 Position : POSITION;
QUAD_REAL2 UV : TEXCOORD0;
};
/////////////////////////////////////////////////////////////////////////////////////
// Hidden tweakables declared by this .fxh file /////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
#ifndef NO_TEXEL_OFFSET
#ifdef TWEAKABLE_TEXEL_OFFSET
QUAD_REAL QuadTexOffset = 0.5;
#else /* !TWEAKABLE_TEXEL_OFFSET */
QUAD_REAL QuadTexOffset < string UIWidget="None"; > = 0.5;
#endif /* !TWEAKABLE_TEXEL_OFFSET */
QUAD_REAL2 QuadScreenSize : VIEWPORTPIXELSIZE < string UIWidget="None"; >;
#endif /* NO_TEXEL_OFFSET */
////////////////////////////////////////////////////////////
////////////////////////////////// vertex shaders //////////
////////////////////////////////////////////////////////////
QuadVertexOutput ScreenQuadVS(
QUAD_REAL3 Position : POSITION,
QUAD_REAL3 TexCoord : TEXCOORD0
) {
QuadVertexOutput OUT;
OUT.Position = QUAD_REAL4(Position, 1);
#ifdef NO_TEXEL_OFFSET
OUT.UV = TexCoord.xy;
#else /* NO_TEXEL_OFFSET */
QUAD_REAL2 off = QUAD_REAL2(QuadTexOffset/(QuadScreenSize.x),QuadTexOffset/(QuadScreenSize.y));
OUT.UV = QUAD_REAL2(TexCoord.xy+off);
#endif /* NO_TEXEL_OFFSET */
return OUT;
}
//////////////////////////////////////////////////////
////////////////////////////////// pixel shaders /////
//////////////////////////////////////////////////////
// add glow on top of model
QUAD_REAL4 TexQuadPS(QuadVertexOutput IN,uniform sampler2D InputSampler) : COLOR
{
QUAD_REAL4 texCol = tex2D(InputSampler, IN.UV);
return texCol;
}
QUAD_REAL4 TexQuadBiasPS(QuadVertexOutput IN,uniform sampler2D InputSampler,QUAD_REAL TBias) : COLOR
{
QUAD_REAL4 texCol = tex2Dbias(InputSampler, QUAD_REAL4(IN.UV,0,TBias));
return texCol;
}
//////////////////////////////////////////////////////////////////
/// Macros to define passes within Techniques ////////////////////
//////////////////////////////////////////////////////////////////
// older HLSL syntax
#define TEX_TECH(TechName,SamplerName) technique TechName { \
pass TexturePass { \
VertexShader = compile vs_2_0 ScreenQuadVS(); \
AlphaBlendEnable = false; ZEnable = false; \
PixelShader = compile ps_2_a TexQuadPS(SamplerName); } }
#define TEX_BLEND_TECH(TechName,SamplerName) technique TechName { \
pass TexturePass { \
VertexShader = compile vs_2_0 ScreenQuadVS(); \
ZEnable = false; AlphaBlendEnable = true; \
SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; \
PixelShader = compile ps_2_a TexQuadPS(SamplerName); } }
// newer HLSL syntax
#define TEX_TECH2(TechName,SamplerName,TargName) technique TechName { \
pass TexturePass < \
string ScriptFunction = "RenderColorTarget0=" (TargName) ";" \
"DrawInternal=Buffer;"; \
> { \
VertexShader = compile vs_2_0 ScreenQuadVS(); \
AlphaBlendEnable = false; ZEnable = false; \
PixelShader = compile ps_2_a TexQuadPS(SamplerName); } }
#define TEX_BLEND_TECH2(TechName,SamplerName) technique TechName { \
pass TexturePass < \
string ScriptFunction = "RenderColorTarget0=" (TargName) ";" \
"DrawInternal=Buffer;"; \
> { \
VertexShader = compile vs_2_0 ScreenQuadVS(); \
ZEnable = false; AlphaBlendEnable = true; \
SrcBlend = SrcAlpha; DestBlend = InvSrcAlpha; \
PixelShader = compile ps_2_a TexQuadPS(SamplerName); } }
#endif /* _QUAD_FXH */
////////////// eof ///
]]>
//////////////////////////////////////////////
// CONSTANTS /////////////////////////////////
//////////////////////////////////////////////
// Some user-assignable macros -- define their values before including
// "shadowMap.fxh" to override these defaults
#ifndef SHADOW_SIZE
#define SHADOW_SIZE 512
#endif /* !SHADOW_SIZE */
// other formats include "D24X8_SHADOWMAP" and "D16_SHADOWMAP"
#ifndef SHADOW_FORMAT
#define SHADOW_FORMAT "D24S8_SHADOWMAP"
#endif /* SHADOW_FORMAT */
#ifndef MAX_SHADOW_BIAS
#define MAX_SHADOW_BIAS 0.00015
#endif /* !MAX_SHADOW_BIAS */
// Define BLACK_SHADOW_PASS before including "shadowMap.fxh" for a SLIGHTLY faster generation
// of the "throwaway" RGB buffer created when generating depth maps
// #define BLACK_SHADOW_PASS
//////////////////////////////////////////////////////
//// VM FUNCTIONS ////////////////////////////////////
//////////////////////////////////////////////////////
// #define SHAD_BIT_DEPTH 16 /* only significant for DirectX8 */
float4x4 make_bias_mat(float BiasVal)
{
float fTexWidth = SHADOW_SIZE;
float fTexHeight = SHADOW_SIZE;
// float fZScale = pow(2.0,((float)SHAD_BIT_DEPTH))-1.0; // dx8
float fZScale = 1.0; //dx9
float fOffsetX = 0.5f + (0.5f / fTexWidth);
float fOffsetY = 0.5f + (0.5f / fTexHeight);
float4x4 result = float4x4(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, fZScale, 0.0f,
fOffsetX, fOffsetY, -BiasVal, 1.0f );
return result;
}
//////////////////////////////////////////////////////
// DECLARATION MACROS ////////////////////////////////
//////////////////////////////////////////////////////
//
// Create standard biasing tweakable slider, and create a
// static global bias transofrm at the same time
// Typical usage: SHADOW_XFORMS("light0",L0ViewXf,L0ProjXf,L0VPXf)
//
#define DECLARE_SHADOW_BIAS float ShadBias < string UIWidget = "slider"; \
float UIMin = 0; float UIMax = MAX_SHADOW_BIAS; float UIStep = 0.00001; \
string UIName = "Shadow Bias"; > = 0.0001; \
static float4x4 ShadBiasXf = make_bias_mat(ShadBias);
//
// Declare standard setup for lamp transofrms using "frustrum."
// Typical usage: SHADOW_XFORMS("light0",L0ViewXf,L0ProjXf,L0VPXf)
//
#define DECLARE_SHADOW_XFORMS(LampName,LampView,LampProj,LampViewProj) \
float4x4 LampView : View < string frustum = (LampName); >; \
float4x4 LampProj : Projection < string frustum = (LampName); >; \
static float4x4 LampViewProj = mul(LampView,LampProj);
//
// Declare standard square_sized shadow map targets.
// Typical use: DECLARE_SHADOW_MAPS(ColorShadMap,ColorShadSampler,ShadDepthTarget,ShadDepthSampler)
//
#define DECLARE_SHADOW_MAPS(CTex,CSamp,DTex,DSamp) \
texture CTex : RENDERCOLORTARGET < float2 Dimensions = {SHADOW_SIZE,SHADOW_SIZE}; \
string Format = "x8b8g8r8" ; string UIWidget = "None"; >; \
sampler CSamp = sampler_state { texture = ; \
AddressU = CLAMP; AddressV = CLAMP; \
MipFilter = NONE; MinFilter = LINEAR; MagFilter = LINEAR; }; \
texture DTex : RENDERDEPTHSTENCILTARGET < float2 Dimensions = {SHADOW_SIZE,SHADOW_SIZE}; \
string format = (SHADOW_FORMAT); string UIWidget = "None"; >; \
sampler DSamp = sampler_state { texture = ; \
AddressU = CLAMP; AddressV = CLAMP; \
MipFilter = NONE; MinFilter = LINEAR; MagFilter = LINEAR; };
/////////////////////////////////////////////////////////
// Structures ///////////////////////////////////////////
/////////////////////////////////////////////////////////
/* data from application vertex buffer */
struct ShadowAppData {
float3 Position : POSITION;
float4 UV : TEXCOORD0; // provided for potential use
float4 Normal : NORMAL; // ignored if BLACK_SHADOW_PASS
};
// Connector from vertex (no pixel shader needed) for simple shadow
struct ShadowVertexOutput {
float4 HPosition : POSITION;
float4 diff : COLOR0;
};
//
// Connector from vertex to pixel shader for typical usage. The
// "LProj" member is the crucial one for shadow mapping.
//
struct ShadowingVertexOutput {
float4 HPosition : POSITION;
float2 UV : TEXCOORD0;
float3 LightVec : TEXCOORD1;
float3 WNormal : TEXCOORD2;
float3 WView : TEXCOORD3;
float4 LProj : TEXCOORD4; // current position in light-projection space
};
/////////////////////////////////////////////////////////
// Vertex Shaders ///////////////////////////////////////
/////////////////////////////////////////////////////////
//
// Use this vertex shader for GENERATING shadows. It needs to know some transforms
// from your scene, pass them as uniform aguments in the technique like so:
// VertexShader = compile vs_2_0 shadowGenVS(WorldXf,WorldITXf,ShadowViewProjXf);
// Note that a color is returned because DirectX requires you to render an RGB value in
// addition to the depth map. If BLACK_SHADOW_PASS is defined this will just be black,
// otherwise it will encode the object-space normal as a color, which can be useful
// for debugging. Either way, no pixel shader is required for the shadow-generation pass.
//
ShadowVertexOutput shadowGenVS(ShadowAppData IN,
uniform float4x4 WorldXform,
uniform float4x4 WorldITXform,
uniform float4x4 ShadowVPXform) {
ShadowVertexOutput OUT = (ShadowVertexOutput)0;
float4 Po = float4(IN.Position.xyz,(float)1.0); // object coordinates
float4 Pw = mul(Po,WorldXform); // "P" in world coordinates
float4 Pl = mul(Pw,ShadowVPXform); // "P" in light coords
OUT.HPosition = Pl; // screen clipspace coords
#ifndef BLACK_SHADOW_PASS
// shading this just for amusement in the texture pane
float4 N = mul(IN.Normal,WorldITXform); // world coords
N = normalize(N);
OUT.diff = 0.5 + 0.5 * N;
#else /* !BLACK_SHADOW_PASS */
OUT.diff = float4(0,0,0,1);
#endif /* !BLACK_SHADOW_PASS */
return OUT;
}
//
// A typical vertex shader for USING shadows. It needs to know some transforms
// from your scene, pass them as uniform aguments in the technique like so:
// VertexShader = compile vs_2_0
// shadowUseVS(WorldXf,WorldITXf,WorldViewProjXf,
// ShadowViewProjXf,ViewIXf,ShadBiasXf, LightPosition);
// Note that a color is returned because DirectX requires you to render an RGB value in
// addition to the depth map. If BLACK_SHADOW_PASS is defined this will just be black,
// otherwise it will encode the object-space normal as a color, which can be useful
// for debugging. Either way, no pixel shader is required for the shadow-generation pass.
//
ShadowingVertexOutput shadowUseVS(ShadowAppData IN,
uniform float4x4 WorldXform,
uniform float4x4 WorldITXform,
uniform float4x4 WVPXform,
uniform float4x4 ShadowVPXform,
uniform float4x4 ViewIXform,
uniform float4x4 BiasXform,
uniform float3 LightPosition) {
ShadowingVertexOutput OUT = (ShadowingVertexOutput)0;
OUT.WNormal = mul(IN.Normal,WorldITXform).xyz; // world coords
float4 Po = float4(IN.Position.xyz,(float)1.0); // "P" in object coordinates
float4 Pw = mul(Po,WorldXform); // "P" in world coordinates
float4 Pl = mul(Pw,ShadowVPXform); // "P" in light coords
//OUT.LProj = Pl; // ...for pixel-shader shadow calcs
OUT.LProj = mul(Pl,BiasXform); // bias to make texcoord
//
OUT.WView = normalize(ViewIXform[3].xyz - Pw.xyz); // world coords
OUT.HPosition = mul(Po,WVPXform); // screen clipspace coords
OUT.UV = IN.UV.xy; // pass-thru
OUT.LightVec = LightPosition - Pw.xyz; // world coords
return OUT;
}
#if 0
//
// TYPICAL USAGE: This code matches shadRPortHW.fx
//
/*********************************************************/
/*********** pixel shader ********************************/
/*********************************************************/
//
// Typical pixel shader that uses ShadowVertexOutput data -- all you need for the shadow
// is one tex2Dproj() call!
//
// In this shader, when DEBUG_VIEW is defined, show the RGB portion of the
// shadow pass, to verify that projection is correct
float4 useShadowPS(ShadowingVertexOutput IN) : COLOR
{
#ifdef DEBUG_VIEW
return tex2Dproj(ColorShadSampler,IN.LProj); // show the RGB render instead
#else /*!DEBUG_VIEW */
//
// shading...
//
float3 Nn = normalize(IN.WNormal);
float3 Vn = normalize(IN.WView);
float falloff = 1.0 / dot(IN.LightVec,IN.LightVec);
float3 Ln = normalize(IN.LightVec);
float3 Hn = normalize(Vn + Ln);
float hdn = dot(Hn,Nn);
float ldn = dot(Ln,Nn);
float4 litVec = lit(ldn,hdn,SpecExpon);
ldn = litVec.y * SpotLightIntensity;
float cone = normalize(IN.LProj.xyz).z;
cone = max((float)0,((cone-CosSpotAng)/(((float)1.0)-CosSpotAng)));
float3 ambiContrib = SurfColor * AmbiLightColor;
float3 diffContrib = SurfColor*(Kd*ldn * SpotLightColor);
float3 specContrib = ((ldn * litVec.z * Ks) * SpotLightColor);
float3 result = diffContrib + specContrib;
//
// shadowing.....
//
float4 shadowed = tex2Dproj(ShadDepthSampler,IN.LProj);
return float4((cone*falloff*shadowed.x*result)+ambiContrib,1);
#endif /*!DEBUG_VIEW */
}
////////////////////////////////////////////////////////////////////
/// TECHNIQUES /////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
technique Main <
string Script = "Pass=MakeShadow;"
"Pass=UseShadow;";
> {
pass MakeShadow <
string Script = "RenderColorTarget0=ColorShadMap;"
"RenderDepthStencilTarget=ShadDepthTarget;"
"RenderPort=light0;"
"ClearSetColor=ShadowClearColor;"
"ClearSetDepth=ClearDepth;"
"Clear=Color;"
"Clear=Depth;"
"Draw=geometry;";
> {
VertexShader = compile vs_2_0 shadCamVS();
ZEnable = true;
ZWriteEnable = true;
ZFunc = LessEqual;
CullMode = None;
// no pixel shader
}
pass UseShadow <
string Script = "RenderColorTarget0=;"
"RenderDepthStencilTarget=;"
"RenderPort=;"
"ClearSetColor=ClearColor;"
"ClearSetDepth=ClearDepth;"
"Clear=Color;"
"Clear=Depth;"
"Draw=geometry;";
> {
VertexShader = compile vs_2_0 mainCamVS();
ZEnable = true;
ZWriteEnable = true;
ZFunc = LessEqual;
CullMode = None;
PixelShader = compile ps_2_a useShadowPS();
}
}
#endif /* ZERO */
#endif /* _SHADOWMAP_FXH */
/***************************** eof ***/
]]>