OK. Here's the first draft:
DBPro code:
set display mode desktop width(), desktop height(), 32
reload display pointer
sync on : sync rate 60 : sync
` set up camera
autocam off
position camera 0, 100, -300
point camera 0, 0, 0
color backdrop 0
global cx#: global cy#
cx# = camera angle x()
cy# = camera angle y()
` Make Dynamic Cube Map <iID>, <size>, [mipmapped] - creates a cube map of the specified resolution valid ID = 1-10, optional mipmap parameter
make dynamic cube map 4, 512 ` not mipmapped by default(?)
load object "testing.dbo", 1 ` this object has 1 limb and FVF 530
set object texture 1, 0, 1 ` might not be needed when shader used
load image "rockwall2.png", 1 ` base texture
load image "rockwall2_NRM.png", 2 ` normal map
load image "test0.png", 3 ` light map
` Apply Cube Map To Object <objID>, <stage>, <iID>, [shader] - applies a cube map to an object stage, optional shader parameter, use shader=1 if using an object shader
texture object 1, 0 ` clear existing textures just in case
texture object 1, 0, 1
texture object 1, 1, 2
apply cube map to object 1, 2, 4, 1
texture object 1, 3, 3
` shadow map light marker object
make object sphere 2, 5
set object light 2, 0
set object specular 2, 0
create bitmap 1, 64, 64
cls rgb(255,0,0)
get image 10, 0, 0, 64, 64
texture object 2, 10
cls rgb(0.5*255, 0.9*255, 0.7*255)
get image 11, 0, 0, 64, 64
texture object 2, 11
set current bitmap 0
set object emissive 2, RGB(255,0,0)
position object 2, 0, 40, 0
load effect "cubic shadow mapping.fx", 1, 0
set object effect 1, 1
` set up shader stuff for shadow mapping
set effect technique 1, "ShadowMapping"
null = make vector4(1)
set vector4 1, 0, 40, 0, 1
set effect constant vector 1, "LightPosition", 1
set effect constant float 1, "LightRange", 2000
` used for testing combination of LM and base texture
`texture object 1, 0 ` clear the textures already applied
` set blend mapping on Object Number, Stage Index, Image Number, TexCoordMode, Blend Mode
`set blend mapping on 1, 0, 1, 0, 2
`set blend mapping on 1, 1, 3, 0, 4
repeat
positionCamera()
if leftkey()
LX# = -40.0
else
if rightkey()
LX# = 40.0
else
LX# = 0.0
endif
endif
position object 2, LX#, 40.0, 0.0
set vector4 1, LX#, 40, 0.0, 0.0
set effect constant vector 1, "LightPosition", 1
set effect technique 1, "DepthMap"
` Render Dynamic Cube Map <iID>, <camera>, <x>, <y>, <z> - renders a cube map with a camera (-1 for temp camera) at a position
render dynamic cube map 4, -1, LX#, 40, 0
set effect technique 1, "ShadowMapping"
text 20, 20, "Press and hold <c> to change shadow map colour to bright red"
text 20, 40, " left/right key to move shadow map light"
if inkey$() = "c"
set vector4 1, 0.9, 0.0, 0.0, 0.0
texture object 2, 10
else
set vector4 1, 0.5, 0.9, 0.7, 0.0
texture object 2, 11
endif
set effect constant vector 1, "LightColor", 1
sync
until spacekey()
end
function positionCamera()
control camera using arrowkeys 0,2,0
cx#=cx# + 0.1*mousemovey() : cy# = cy# + 0.1*mousemovex()
rotate camera cx#,cy#,0
endfunction
Shader code:
//====================================================
// Cubic Shadow Mapping
//====================================================
// By EVOLVED (with minor edits by Green Gandalf) (additional edits for light mapping by Green Gandalf)
// www.evolved-software.com
//====================================================
//--------------
// un-tweaks
//--------------
matrix WorldVP:WorldViewProjection;
matrix World:World;
matrix ViewInv:ViewInverse;
//--------------
// Tweaks
//--------------
float3 Ambient={0.0f,0.1f, 0.1f};
float4 LightPosition={0.0f,150.0f,0.0f,1.0f};
float3 LightColor={0.5f,0.9f,0.7f};
float LightRange=250.0f;
float4 FogColor={0.0f,0.5f,0.5f,1.0f};
float FogRange=2500.0f;
float Alpha=0.5f;
//--------------
// Textures
//--------------
texture BaseTX <string Name="";>;
sampler2D Base = sampler_state
{
texture = <BaseTX>;
};
texture NormalTX <string Name="";>;
sampler2D Normal = sampler_state
{
texture = <NormalTX>;
};
texture DepthMapTX <string Name=""; string Type = "CUBE";>;
samplerCUBE DepthMapSample = sampler_state
{
Texture = <DepthMapTX>;
};
texture LightMapTX <string Name="";>;
sampler2D LightMap = sampler_state
{
Texture = <LightMapTX>;
};
//--------------
// structs
//--------------
struct IN_Depth
{
float4 Pos:POSITION;
};
struct OUT_Depth
{
float4 OPos:POSITION;
float3 Depth:TEXCOORD1;
};
struct IN_NormalMap
{
float4 Pos:POSITION;
float2 UV:TEXCOORD;
float2 UV1:TEXCOORD1; // added by GG for light mapping
float3 Normal:NORMAL;
float3 Tangent:TANGENT;
float3 Binormal:BINORMAL;
};
struct OUT_NormalMap
{
float4 OPos:POSITION;
float2 Tex:TEXCOORD0;
float2 Tex1:TEXCOORD1; // added by GG for light mapping
float3 LightVec:TEXCOORD2; // tex coord references adjusted
float3 Attenuation:TEXCOORD3;
float3 ViewVec:TEXCOORD4;
float3 ShadowMap:TEXCOORD5;
float Fog:FOG;
};
//--------------
// vertex shaders
//--------------
OUT_Depth VS_Depth(IN_Depth IN)
{
OUT_Depth OUT;
OUT.OPos = mul(IN.Pos,WorldVP);
float3 WPos=mul(IN.Pos,World).xyz; // minor edits
float3 LightPos=LightPosition.xyz-WPos.xyz; // minor edits
OUT.Depth=-(LightPos/LightRange);
return OUT;
}
OUT_NormalMap VS_NormalMap(IN_NormalMap IN)
{
OUT_NormalMap OUT;
OUT.OPos=mul(IN.Pos,WorldVP);
OUT.Tex=IN.UV;
OUT.Tex1=IN.UV1; // added for lightmapping
float3x3 TBN={IN.Tangent,IN.Binormal,IN.Normal};
TBN=transpose(mul(TBN,(float3x3) World)); //minor edits
float3 WPos=mul(IN.Pos,World).xyz; // minor edits
float3 LightPos=LightPosition.xyz-WPos.xyz; // minor edit
float3 ViewPos=ViewInv[3].xyz-WPos; // minor edit
OUT.LightVec=mul(LightPos,TBN);
OUT.Attenuation=-(LightPos/LightRange);
OUT.ViewVec=mul(ViewPos,TBN);
OUT.ShadowMap=-LightPos;
OUT.Fog=1-saturate(dot(ViewPos/FogRange,ViewPos/FogRange));
return OUT;
}
//--------------
// pixel shaders
//--------------
float4 PS_Depth(OUT_Depth IN) : COLOR
{
// return float4(length(IN.Depth)+0.011f,0,0,1);
return float4(length(IN.Depth)+0.005f,0,0,1); // minor edit to offset by GG
}
float4 PS_NormalMap(OUT_NormalMap IN) : COLOR
{
float4 Texture=tex2D(Base,IN.Tex);
float3 NormalMap=tex2D(Normal,IN.Tex).rgb*2-1; // minor edits
float3 LightMP = tex2D(LightMap, IN.Tex1); // added by GG for lightmapping
float3 LightV=normalize(IN.LightVec);
float3 ViewV=normalize(IN.ViewVec);
NormalMap=normalize(NormalMap);
float specNormal=saturate(dot(reflect(-ViewV,NormalMap),LightV)); // variable name change by GG
float LightingSpecDiffuse=pow(specNormal,16)+saturate(dot(NormalMap,LightV)); // new variable name by GG
// float3 Light=LightColor*saturate(1-dot(IN.Attenuation,IN.Attenuation)); // clamped by GG
float3 Light=LightColor*saturate(1-length(IN.Attenuation)); // clamped and modified by GG
float Depth=length(IN.Attenuation);
//*
float shadowmap=1-(texCUBE(DepthMapSample,IN.ShadowMap+float3(-0.8f,-0.8f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMapSample,IN.ShadowMap+float3(0.0f,-0.8f,-0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMapSample,IN.ShadowMap+float3(0.8f,-0.8f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMapSample,IN.ShadowMap+float3(-0.8f,0.0f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMapSample,IN.ShadowMap+float3(0.0f,0.0f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMapSample,IN.ShadowMap+float3(0.8f,0.0f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMapSample,IN.ShadowMap+float3(-0.8f,0.8f,0.0f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMapSample,IN.ShadowMap+float3(0.0f,0.8f,0.8f)) < Depth ? 0.111f:0.0f);
shadowmap=shadowmap-(texCUBE(DepthMapSample,IN.ShadowMap+float3(0.8f,0.8f,-0.8f)) < Depth ? 0.111f:0.0f);
// */
// float shadowmap=1-(texCUBE(DepthMapSample,IN.ShadowMap).r < Depth ? 1.0f:0.0f);
// return float4(Texture*((Normal*Light*shadowmap)+Ambient),Texture.w*Alpha);
// return float4(Texture.rgb*((LightingSpecDiffuse*Light*shadowmap)+Ambient),Texture.w*Alpha); // minor edits by GG
return float4(Texture.rgb*((LightingSpecDiffuse*Light*shadowmap)+LightMP),Texture.w*Alpha); // edited by GG (assumes ambient is provided by light map)
}
//--------------
// techniques
//--------------
technique DepthMap
{
pass p1
{
VertexShader = compile vs_2_0 VS_Depth();
PixelShader = compile ps_2_0 PS_Depth();
}
}
technique ShadowMapping
{
pass p1
{
vertexShader = compile vs_2_0 VS_NormalMap();
pixelShader = compile ps_2_0 PS_NormalMap();
FOGCOLOR=(FogColor);
FOGENABLE=TRUE;
}
}
There's still a problem.
If you change the light position by holding the left or right keys, you'll see the shadows for your object are wrong. The pillars don't seem to be casting shadows for some reason. No time to investigate right now - but at least you've got the light map.
I've probably overlooked something simple.