Well, that was a surprise.
Found what appears to be the cause of the bug - but not sure why at the moment.
I made several changes to the code (mainly for my benefit) but the crucial ones seem to be here (lines marked ***):
REM shadow shader
REM set light position
set vector4 1, lightX#, lightY#, lightZ#, 1 // correction by GG (probably not needed)
set effect constant vector ShadowMapShaderEffectID,"LightPosition",1
`Render shadow map
set effect technique ShadowMapShaderEffectID,"DepthMap"
hide object FullScreenShaderPlane ` this seems to be essential here - not obvious why ***
Render Dynamic Cube Map CubeMapID,ShadowMapCameraID, lightX#, lightY#, lightZ#
`Main Scene
set effect technique ShadowMapShaderEffectID,"ShadowMapping"
` sync mask 2^0 ` out of place - but why should this matter? ***
REM shadow shader
Here's the full code I used (I was using FullDesktop project setting):
`set window off
`set display mode 1280, 720, 32, 1
set display mode desktop width(), desktop height(), 32, 1
Reload Display Pointer // Needed for fullscreen shaders to work properly
Sync on
Sync Rate 60
sync
autocam off
hide mouse
Global BloomShaderEffectID as integer = 22
Global QuadShaderEffectID as integer = 23
Global FullScreenShaderPlane as integer = 5000
Global FullscreenShaderImage as integer = 2 ` I have no idea why this doesn't cause a conflict with object 1's nmap???
Global BackdropColor as dword
BackdropColor = rgb(40,40,40) // the camera 0 backdrop is not used this variable is for setting the bloom camera backdrop to the same value as camera 0.
Global NrOfbjects as integer = 100
// globals added by GG to simplify debugging
global lightX# = 30.0
global lightY# = 30.0 ` raised to make ground shadows easier to see - hopefully
global lightZ# = 0.0
global BloomCameraID = 2
global ShadowMapCameraID = 1
global ShadowMapShaderEffectID = 24
global CubeMapID = 1
global LightObjectID = 4
Color Backdrop BackdropColor
InitFullscreenShaders()
make camera ShadowMapCameraID
` set camera to image 2,3,256,256 ` not needed ?
Make Dynamic Cube Map CubeMapID,256
color backdrop ShadowMapCameraID,rgb(255,255,255)
load effect "fx/cubicshadowmapping.fx",ShadowMapShaderEffectID,0
load object "ast/char/boy2.x", 1
Apply Cube Map To Object 1,2,CubeMapID
set object effect 1, ShadowMapShaderEffectID
load image "ast/char/boy.png", 1
load image "ast/char/boy_nrm.png", 2
texture object 1, 0, 1
texture object 1, 1, 2
set object normals 1
set object texture 1, 0, 1, 1
position object 1, 0, -13, 0
scale object 1, 300, 300, 300
loop object 1, 20, 38
set object speed 1, 40
make object plain 2, 900, 900
position object 2, 0, -20, 0
xrotate object 2, 90
load image "ast/lev/rockwall2.png", 3
load image "ast/lev/rockwall2_nrm.png", 4
texture object 2, 0, 3
texture object 2, 1, 4
scale object texture 2, 7, 17
set object effect 2, ShadowMapShaderEffectID
Apply Cube Map To Object 2,2,CubeMapID
` marker object to denote light (and cube map camera) position
make object sphere LightObjectID, 3
color object LightObjectID, rgb(255,255,255)
set object light LightObjectID, 0
position object LightObjectID, lightX#, lightY#, lightZ#
`load object "ast/char/point.3ds", 3 ` not needed ? what is it and what does it do?
`scale listener 0.5 ` not needed
vec=make vector4(1) REM for light shader
do
`position object 3, camera position x(), camera position y(), camera position z()
`yrotate object 3, camera angle y() : move object 3, -100
set camera to follow object position x(1), object position y(1), object position z(1), wrapvalue( camera angle y() + mousemovex() / 2.0 ), 42, 42+mousemovey(), 7, 0 : point camera object position x(1), object position y(1)+30, object position z(1)
`if keystate(17) then point object 1, object position x(3), 0, object position z(3) : move object 1, -5 : xrotate object 1, 0
`if keystate(31) then point object 1, object position x(3), 0, object position z(3) : move object 1, 5 : xrotate object 1, 0
rem if mousemovey()<20 and mousemovey()>-20 then mousemovey()=camangview#
rem print camangview#
if keystate(30) then rot#=object angle y(1)-1 : yrotate object 1, rot#
if keystate(32) then rot#=object angle y(1)+1 : yrotate object 1, rot#
REM shadow shader
REM set light position
set vector4 1, lightX#, lightY#, lightZ#, 1 // correction by GG (probably not needed)
set effect constant vector ShadowMapShaderEffectID,"LightPosition",1
`Render shadow map
set effect technique ShadowMapShaderEffectID,"DepthMap"
hide object FullScreenShaderPlane ` this seems to be essential here - not obvious why
Render Dynamic Cube Map CubeMapID,ShadowMapCameraID, lightX#, lightY#, lightZ#
`Main Scene
set effect technique ShadowMapShaderEffectID,"ShadowMapping"
` sync mask 2^0 ` out of place - but why should this matter????
REM shadow shader
UpdateFullScreenShaders()
sync
loop
Function InitFullscreenShaders()
Local TempVector as integer = 5000
// Make the "bloom camera" and set the backdrop color
Make Camera BloomCameraID
Color Backdrop BloomCameraID, BackdropColor
// load the bloom shader as a camera effect and set the "bloom camera" to draw on "FullscreenShaderImage"
Load Camera Effect "fx/postbloom.fx",BloomShaderEffectID,0
Set Camera Effect BloomCameraID,BloomShaderEffectID,FullscreenShaderImage
// FullScreenShaderPlane is the "canvas" where the camera image is drawn and later displayed.
Make Object Plain FullScreenShaderPlane,2,2,1
Set Object Radius FullScreenShaderPlane,-1
// Load and apply the quad shader to the "canvas" plane. The quad shader aligns the "canvas" plane to point at the camera and stretches it across the screen.
Load Effect "fx/quad.fx",QuadShaderEffectID,0
Set Object Effect FullScreenShaderPlane,QuadShaderEffectID
// We need to set the "ViewSize" variable in the bloom shader so it knows how large our screen is.
null = Make Vector4(TempVector)
` Set Vector4 TempVector, Screen Width(), Screen Height(),0,0
Set Vector4 TempVector, desktop Width(), desktop Height(),0,0
Set Camera Effect Constant Vector BloomShaderEffectID,"ViewSize",TempVector
// ideally we also need to specify the InvViewSize variable for the quad shader (added by GG)
set vector4 TempVector, 1.0/desktop width(), 1.0/desktop height(), 0, 0
set effect constant vector QuadShaderEffectID, "InvViewSize", TempVector
null = Delete Vector4(TempVector)
// Texture the quad (canvas) plane with the image from the bloom camera.
Texture Object FullScreenShaderPlane,0, FullscreenShaderImage
EndFunction
Function UpdateFullScreenShaders()
// Before "sync" the bloom camera is placed at the correct position to view the scene.
position camera BloomCameraID,camera position x(0),camera position y(0),camera position z(0)
rotate camera BloomCameraID,camera angle x(0),camera angle y(0),camera angle z(0)
// Show all objects to the bloom camera. and hide the "canvas" plane so the bloom camera will not see it
ShowObjectsForFullscreenShader()
hide object FullScreenShaderPlane
// Sync the bloom camera and hide all objects again, performance degrades if both cameras has to draw all objects.
sync camera BloomCameraID
HideObjectsForFullscreenShader()
// show the "canvas plane".
show object FullScreenShaderPlane
// Tell the "Sync" command to only sync camera 0 from here on.
sync mask %001
EndFunction
Function HideObjectsForFullscreenShader()
// All objects in the scene has to be hidden after the scene has been drawn to the bloom camera.
// Performance degrades if objects are drawn to both cameras.
For i = 1 To NrOfbjects
IF Object Exist(i)
Hide Object i
Endif
Next
endfunction
Function ShowObjectsForFullscreenShader()
// Show all objects (to the bloom camera only)
For i = 1 To NrOfbjects
If Object Exist(i)
Show Object i
Endif
Next
Endfunction
The remaining issue is that the shadow is not animated - I think you need a bone shader for that (unless I've made another error somewhere...). I've got one somewhere. I'll dig out the demo.