[Continued message]
And the code for the V1.1 CSM System:
//==========================================================
// Cubic Shadow Mapping -> CSM_ DBP code
//==========================================================
// CSM system by Bruce for use with the adapted shader
// from EVOLVED 'Cubic_Shadow_Mapping_For_CSM.fx'
//==========================================================
//Constants
//Tweakables
#constant CSM_EffectPath "FX/Cubic_Shadow_Mapping_For_CSM.fx"
#constant CSM_Vector4ID 1
#constant CSM_CameraMaskOnFunctionExit %0001
#constant CSM_DebugMessageBufferLength 9
//Untweakables
#constant CSM_MaxCubemaps 5
//Types
type CSM_XYZFloatType
X as float
Y as float
Z as float
endtype
type CSM_RGBType
R as byte
G as byte
B as byte
endtype
type CSM_LightType
LightID as integer
Pos as CSM_XYZFloatType
Range as float
Colour as CSM_RGBType
Active as boolean
CameraID as integer
ShadowImage as integer
LinkedObjectID as integer
LinkedObjectCameraToPointAtID as integer
RemoveAfterTime as integer
LightIsFlash as boolean
LightPulseTime as integer
LightPulsePhase as float
LightPulseSpeed as float
LightPulseColour1 as CSM_RGBType
LightPulseColour2 as CSM_RGBType
LightPulseRange1 as float
LightPulseRange2 as float
LightPulseLast as integer
LightPulseDoNotUpdateRange as boolean
LightPulseDoNotUpdateColour as boolean
endtype
type CSM_ObjectType
ObjectID as integer
DiffuseTexID as integer
NormalTexID as integer
EffectID as integer
endtype
//Globals
global CSM_EffectID as integer
global CSM_LightCount as integer
global CSM_LightActiveCount as integer
global CSM_LightArrayLength as integer
global CSM_ObjectCount as integer
global CSM_ShadowQuality as integer
global CSM_DebugOn as boolean
//Functions
/////////////////////
// Init system //
/////////////////////
//Start CSM
function CSM_Start(iShadowQuality as integer)
local i as integer
//Get fresh IDs
CSM_EffectID=CSM_GetFreeEffectID()
CSM_ShadowQuality=iShadowQuality
//Load effect
load effect CSM_EffectPath,CSM_EffectID,0
//Set var defaults
CSM_LightCount=-1 : CSM_LightActiveCount=-1
//Make array for lights
dim CSM_Lights() as CSM_LightType : CSM_LightArrayLength=-1
//Make array for objects
dim CSM_Objects() as CSM_ObjectType : CSM_ObjectCount=-1
//Make vector
null=make vector4(CSM_Vector4ID)
//Pre-calc sin func
dim CSM_Sin(360) as float
for i=0 to 360 : CSM_Sin(i)=0.5*(1+sin(i)) : Next i
//Debug setup
dim CSM_DebugMessages(CSM_DebugMessageBufferLength) as string
Endfunction
////////////////////////////
// Flush/reset system //
////////////////////////////
function CSM_Flush()
local i as integer
//Remove all the lights
for i=0 to CSM_LightArrayLength
CSM_LightRemove(CSM_Lights(0).LightID)
Next i
//Reset light array length var
CSM_LightArrayLength=-1
//Objects should be automatiacally taken care of when they are deleted
CSM_Update()
Endfunction
//////////////////////
// Objects //
//////////////////////
//Add object textures & set up for shadows
function CSM_ObjectTexture(ObjectID as integer, DiffuseTextureID as integer, NormalTextureID as integer)
if CSM_DebugOn>0
if object exist(ObjectID)=0
CSM_DebugAddMessage(get time$()+ ": CSM_ObjectTexture -> ERROR: Object does not exist, ObjectID="+str$(ObjectID))
exitfunction
endif
if image exist(DiffuseTextureID)=0 then CSM_DebugAddMessage(get time$()+ ": CSM_ObjectTexture -> ERROR: Diffuse texture does not exist, TextureID="+str$(DiffuseTextureID))
if image exist(NormalTextureID)=0 then CSM_DebugAddMessage(get time$()+ ": CSM_ObjectTexture -> ERROR: Normal texture does not exist, TextureID="+str$(NormalTextureID))
endif
//Add object data
add to queue CSM_Objects() : inc CSM_ObjectCount,1
CSM_Objects().ObjectID=ObjectID : CSM_Objects().DiffuseTexID=DiffuseTextureID : CSM_Objects().NormalTexID=NormalTextureID
CSM_Objects().EffectID=CSM_EffectID
//Apply diffuse and normal textures
if DiffuseTextureID>0 then texture object ObjectID,0,DiffuseTextureID
if NormalTextureID>0 then texture object ObjectID,1,NormalTextureID
//Apply cubemaps
for i=0 to CSM_LightArrayLength
Apply Cube Map To Object ObjectID,2+i,1+i
next i
//Set effect
set object effect ObjectID,CSM_EffectID
Endfunction
//Remove object
function CSM_ObjectRemove(ObjectID as integer)
local i as integer
for i=0 to CSM_ObjectCount
if CSM_Objects(i).ObjectID=ObjectID
if object exist(ObjectID)=1 then set object mask ObjectID,%0001
array delete element CSM_Objects(),i
dec CSM_ObjectCount,1
exitfunction
Endif
next i
Endfunction
//Set object transparency
function CSM_ObjectAlphaEnable(ObjectID as integer, AlphaEnabled as boolean)
local i as integer
if CSM_DebugOn>0
if object exist(ObjectID)=0
CSM_DebugAddMessage(get time$()+ ": CSM_ObjectAlphaEnable -> ERROR: Object does not exist, ObjectID="+str$(ObjectID))
exitfunction
endif
endif
for i=0 to CSM_ObjectCount
if CSM_Objects(i).ObjectID=ObjectID
if AlphaEnabled=1
if CSM_Objects(i).EffectID=CSM_EffectID
CSM_Objects(i).EffectID=CSM_GetFreeEffectID()
load effect CSM_EffectPath,CSM_Objects(i).EffectID,0
else
CSM_DebugAddMessage(get time$()+ ": CSM_ObjectAlphaEnable -> WARNING: Object already alpha enabled!, ObjectID="+str$(ObjectID))
endif
set object transparency ObjectID,2
else
if CSM_Objects(i).EffectID<>CSM_EffectID then delete effect CSM_Objects(i).EffectID
CSM_Objects(i).EffectID=CSM_EffectID
set object transparency ObjectID,1
endif
set object effect ObjectID,CSM_Objects(i).EffectID
exitfunction
Endif
Next i
Endfunction
//Set the alpha value of the obejct
function CSM_ObjectAlphaSet(ObjectID as integer, Alpha as float)
local i as integer
if CSM_DebugOn>0
if object exist(ObjectID)=0
CSM_DebugAddMessage(get time$()+ ": CSM_ObjectAlphaSet -> ERROR: Object does not exist, ObjectID="+str$(ObjectID))
exitfunction
endif
if Alpha>1.0 OR Alpha<0.0
CSM_DebugAddMessage(get time$()+ ": CSM_ObjectAlphaSet -> ERROR: Alpha value must be a float in the range 0.0 to 1.0, Alpha="+str$(Alpha))
if Alpha>1.0 then Alpha=1.0
if Alpha<0.0 then Alpha=0.0
CSM_DebugAddMessage(get time$()+ ": CSM_ObjectAlphaSet -> WARNING: Alpha value capped in valid range, Alpha="+str$(Alpha))
endif
endif
for i=0 to CSM_ObjectCount
if CSM_Objects(i).ObjectID=ObjectID
if CSM_Objects(i).EffectID=CSM_EffectID
if CSM_DebugOn>0 then CSM_DebugAddMessage(get time$()+ ": CSM_ObjectAlphaSet -> ERROR: Object using default CSM effect, probable cause: object alpha not enabled.")
exitfunction
endif
set effect constant float CSM_Objects(i).EffectID,"Alpha",Alpha
endif
Next i
Endfunction
//////////////////////
// Lights //
//////////////////////
//Add a light to the system
function CSM_LightAdd(PosX as float,PosY as float,PosZ as float, Range as float)
local rLightID as integer
if CSM_DebugOn>0
if CSM_LightArrayLength+1>CSM_MaxCubemaps
CSM_DebugAddMessage(get time$()+ ": CSM_LightAdd -> ERROR: No more lights can be created (MAX="+str$(CSM_MaxCubemaps+1)+")")
exitfunction -1
else
CSM_DebugAddMessage(get time$()+ ": CSM_LightAdd -> Light created, LightID="+str$(CSM_LightCount+1))
endif
endif
//Add to queue and inc vals
add to queue CSM_Lights() : CSM_LightArrayLength=array count(CSM_Lights())
inc CSM_LightCount,1 : CSM_Lights().LightID=CSM_LightCount : rLightID=CSM_LightCount
//Save data
CSM_Lights().Pos.X=PosX : CSM_Lights().Pos.Y=PosY : CSM_Lights().Pos.Z=PosZ : CSM_Lights().Range=Range
//Set default vals
CSM_Lights().Active=1 : inc CSM_LightActiveCount,1 : CSM_Lights().LinkedObjectCameraToPointAtID=-1
CSM_Lights().Colour.R=255.0 : CSM_Lights().Colour.G=255.0 : CSM_Lights().Colour.B=255.0
//Make camera, cubemap & image
CSM_Lights().CameraID=CSM_GetFreeCameraID() : CSM_Lights().ShadowImage=CSM_GetFreeImageID()
make camera CSM_Lights().CameraID : set camera to image CSM_Lights().CameraID,CSM_Lights().ShadowImage,CSM_ShadowQuality,CSM_ShadowQuality : color backdrop CSM_Lights().CameraID,rgb(255,255,255)
Make Dynamic Cube Map CSM_LightArrayLength+1,CSM_ShadowQuality
//Add cubemap to objects
CSM_LightAddCubemapToObjects(CSM_Lights().LightID)
endfunction rLightID
//Remove a light from the system
function CSM_LightRemove(LightID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightRemove -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
dec CSM_LightArrayLength,1
if CSM_Lights(QueueIndex).Active>0 then dec CSM_LightActiveCount,1
delete dynamic cube map QueueIndex+1
delete camera CSM_Lights(QueueIndex).CameraID
delete image CSM_Lights(QueueIndex).ShadowImage
array delete element CSM_Lights(),QueueIndex
Endfunction
//Add a flash to the system
function CSM_LightFlashAdd(PosX as float,PosY as float,PosZ as float, Range as float, FlashDuration as integer)
local rLightID as integer : rLightID=CSM_LightAdd(PosX,PosY,PosZ, Range)
if CSM_DebugOn>0
if rLightID<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightFlashAdd -> ERROR: Light creation failed.")
exitfunction -1
endif
endif
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(rLightID)
CSM_Lights(QueueIndex).RemoveAfterTime=timer()+FlashDuration
CSM_Lights(QueueIndex).LightIsFlash=1
Endfunction rLightID
///////////////////////////////////
// Apply cubemaps to objects //
///////////////////////////////////
//Apply a new light's cubemap to previously added objects
function CSM_LightAddCubemapToObjects(LightID as integer)
local i as integer
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightAddCubemapToObjects -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
for i=0 to CSM_ObjectCount
if object exist(CSM_Objects(i).ObjectID)=0
if CSM_DebugOn>0
CSM_DebugAddMessage(get time$()+ ": CSM_LightAddCubemapToObjects -> ERROR: Object does not exist, ObjectID="+str$(CSM_Objects(i).ObjectID)+")")
endif
else
Apply Cube Map To Object CSM_Objects(i).ObjectID,2+QueueIndex,QueueIndex+1
endif
Next i
endfunction
//Re-apply all cubemaps to all objects
function CSM_ObjectCubemapsRefresh()
local i as integer : local j as integer
for i=0 to CSM_ObjectCount
for j=0 to CSM_LightArrayLength
if CSM_DebugOn>0
if object exist(CSM_Objects(i).ObjectID)=0 then CSM_DebugAddMessage(get time$()+ ": CSM_LightAddCubemapToObjects -> ERROR: Object does not exist, ObjectID="+str$(CSM_Objects(i).ObjectID)+")")
endif
Apply Cube Map To Object CSM_Objects(i).ObjectID,2+j,j+1
next j
Next i
endfunction
//////////////////////////////
// Set light properties //
//////////////////////////////
//Set light active
function CSM_LightSetActive(LightID as integer, Active as boolean)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightSetActive -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
if CSM_Lights(QueueIndex).Active=0 and Active=1 then inc CSM_LightActiveCount,1
if CSM_Lights(QueueIndex).Active=1 and Active=0 then dec CSM_LightActiveCount,1
CSM_Lights(QueueIndex).Active=Active
endfunction
//Set light range
function CSM_LightSetRange(LightID as integer, Range as float)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightSetRange -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
if Range<5 then CSM_DebugAddMessage(get time$()+ ": CSM_LightSetRange -> WARNING: Light range is small; a light which doesn't effect objects may give lighting artifacts.")
endif
CSM_Lights(QueueIndex).Range=Range
endfunction
//Set light position
function CSM_LightSetPosition(LightID as integer, PosX as float,PosY as float,PosZ as float)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightSetPosition -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
CSM_Lights(QueueIndex).Pos.X=PosX : CSM_Lights(QueueIndex).Pos.Y=PosY : CSM_Lights(QueueIndex).Pos.Z=PosZ
endfunction
//Set light colour
function CSM_LightSetColour(LightID as integer, R as byte, G as byte, B as byte)
local fR as float : local fG as float : local fB as float
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightSetColour -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
CSM_Lights(QueueIndex).Colour.R=R : CSM_Lights(QueueIndex).Colour.G=G : CSM_Lights(QueueIndex).Colour.B=B
endfunction
//Set linked object
function CSM_LightSetLinkedObject(LightID as integer, ObjectID as integer, CameraToPointAtID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightSetLinkedObject -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
if object exist(ObjectID)=0
CSM_DebugAddMessage(get time$()+ ": CSM_LightSetLinkedObject -> ERROR: Object does not exist. (ObjectID="+str$(ObjectID)+")")
exitfunction
endif
if camera exist(CameraToPointAtID)=0
CSM_DebugAddMessage(get time$()+ ": CSM_LightSetLinkedObject -> ERROR: Camera does not exist. (CameraID="+str$(CameraToPointAtID)+")")
exitfunction
endif
endif
CSM_Lights(QueueIndex).LinkedObjectID=ObjectID
if CameraToPointAtID>-1 then CSM_Lights(QueueIndex).LinkedObjectCameraToPointAtID=CameraToPointAtID
endfunction
//Set light pulse
function CSM_LightSetPulse(LightID as integer, PulseTime as float, PulsePhase as integer, Range1 as float, Range2 as float, ColourR1 as byte, ColourG1 as byte, ColourB1 as byte, ColourR2 as byte, ColourG2 as byte, ColourB2 as byte)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightSetPulse -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
if Range<5 then CSM_DebugAddMessage(get time$()+ ": CSM_LightSetPulse -> WARNING: Light range is small; a light which doesn't effect objects may create lighting artifacts.")
endif
CSM_Lights(QueueIndex).LightPulseSpeed =360.0/PulseTime //deg/ms
CSM_Lights(QueueIndex).LightPulsePhase =PulsePhase
CSM_Lights(QueueIndex).LightPulseLast =timer()
if ColourR1=ColourR2 and ColourG1=ColourG2 and ColourB1=ColourB2
CSM_Lights(QueueIndex).LightPulseDoNotUpdateColour =1
else
CSM_Lights(QueueIndex).LightPulseColour1.R =ColourR1
CSM_Lights(QueueIndex).LightPulseColour1.G =ColourG1
CSM_Lights(QueueIndex).LightPulseColour1.B =ColourB1
CSM_Lights(QueueIndex).LightPulseColour2.R =ColourR2
CSM_Lights(QueueIndex).LightPulseColour2.G =ColourG2
CSM_Lights(QueueIndex).LightPulseColour2.B =ColourB2
endif
if Range1=Range2
CSM_Lights(QueueIndex).LightPulseDoNotUpdateRange =1
else
CSM_Lights(QueueIndex).LightPulseRange1 =Range1
CSM_Lights(QueueIndex).LightPulseRange2 =Range2
endif
Endfunction
//////////////////////////////
// Get light properties //
//////////////////////////////
//Get light exist
function CSM_LightExist(LightID as integer)
if CSM_LightGetArrayIndexByID(LightID)>-1 then exitfunction 1
Endfunction 0
//Get light range
function CSM_LightGetRange(LightID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightGetRange -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
local rValue as float : rValue=CSM_Lights(QueueIndex).Range
endfunction rValue
//Get light position
function CSM_LightGetPositionX(LightID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightGetPositionX -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
local rValue as float : rValue=CSM_Lights(QueueIndex).Pos.X
endfunction rValue
function CSM_LightGetPositionY(LightID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightGetPositionY -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
local rValue as float : rValue=CSM_Lights(QueueIndex).Pos.Y
endfunction rValue
function CSM_LightGetPositionZ(LightID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightGetPositionZ -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
local rValue as float : rValue=CSM_Lights(QueueIndex).Pos.Z
endfunction rValue
//Get light colour
function CSM_LightGetColourR(LightID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightGetColourR -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
local rValue as byte : rValue=CSM_Lights(QueueIndex).Colour.R
endfunction rValue
function CSM_LightGetColourG(LightID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightGetColourG -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
local rValue as byte : rValue=CSM_Lights(QueueIndex).Colour.G
endfunction rValue
function CSM_LightGetColourB(LightID as integer)
local QueueIndex as integer : QueueIndex=CSM_LightGetArrayIndexByID(LightID)
if CSM_DebugOn>0
if QueueIndex<0
CSM_DebugAddMessage(get time$()+ ": CSM_LightGetColourB -> ERROR: LightID not found. (LightID="+str$(LightID)+")")
exitfunction
endif
endif
local rValue as byte : rValue=CSM_Lights(QueueIndex).Colour.B
endfunction rValue
//////////////////////////////
// Set fog properties //
//////////////////////////////
//Set fog colour
function CSM_FogSetColour(R as byte, G as byte, B as byte)
local fR as float : local fG as float : local fB as float
fR=(R*1.0)/255.0 : fG=(G*1.0)/255.0 : fB=(B*1.0)/255.0
set vector4 CSM_Vector4ID,fR,fG,fB,0.0 : set effect constant vector CSM_EffectID,"FogColor",CSM_Vector4ID
for i=0 to CSM_ObjectCount
if CSM_Objects(i).EffectID<>CSM_EffectID then set effect constant vector CSM_Objects(i).EffectID,"FogColor",CSM_Vector4ID
Next i
endfunction
//Set fog range
function CSM_FogSetRange(Range as float)
set effect constant float CSM_EffectID,"FogRange",Range
for i=0 to CSM_ObjectCount
if CSM_Objects(i).EffectID<>CSM_EffectID then set effect constant float CSM_Objects(i).EffectID,"FogRange",Range
Next i
endfunction
///////////////////////
// Update system //
///////////////////////
//Update the system
function CSM_Update()
local i as integer
local CurrentTime as integer : CurrentTime=timer()
//Check for object deletion
CSM_ObjectUpdate()
//Handle pulse lights
CSM_LightPulseUpdate()
//Sort array
CSM_LightUpdateArray()
//Place linked objects
for i=0 to CSM_LightArrayLength
if CSM_Lights(i).Active>0
//Update linked object
if CSM_Lights(i).LinkedObjectID>0
position object CSM_Lights(i).LinkedObjectID,CSM_Lights(i).Pos.X,CSM_Lights(i).Pos.Y,CSM_Lights(i).Pos.Z
if CSM_Lights(i).LinkedObjectCameraToPointAtID>-1
point object CSM_Lights(i).LinkedObjectID,camera position x(CSM_Lights(i).LinkedObjectCameraToPointAtID),camera position y(CSM_Lights(i).LinkedObjectCameraToPointAtID),camera position z(CSM_Lights(i).LinkedObjectCameraToPointAtID)
endif
endif
endif
Next i
//Render lighting -> Same cubemaps are used for all instances of the CSM shader
for i=0 to CSM_LightArrayLength
if CSM_Lights(i).Active>0
//Render depth map to cube map
set effect technique CSM_EffectID,"DepthMap_L"+str$(i)
Render Dynamic Cube Map i+1,CSM_Lights(i).CameraID,CSM_Lights(i).Pos.X,CSM_Lights(i).Pos.Y,CSM_Lights(i).Pos.Z
endif
Next i
//Set effect technique for default CSM shader and object shaders
set effect technique CSM_EffectID,"ShadowMapping_L"+str$(CSM_LightActiveCount)
for i=0 to CSM_ObjectCount
if CSM_Objects(i).EffectID<>CSM_EffectID
set effect technique CSM_Objects(i).EffectID,"ShadowMapping_L"+str$(CSM_LightActiveCount)
endif
Next i
//Set sync mask ready for exit
sync mask CSM_CameraMaskOnFunctionExit
//Delete on render
for i=0 to CSM_LightArrayLength
if CSM_Lights(i).LightIsFlash>0
if CurrentTime>CSM_Lights(i).RemoveAfterTime then CSM_LightRemove(CSM_Lights(i).LightID)
endif
Next i
//Print debugging data to screen
if CSM_DebugOn>0 then CSM_DebugPrint()
Endfunction
//Update objects
function CSM_ObjectUpdate()
local i as integer
for i=0 to CSM_ObjectCount
if object exist(CSM_Objects(i).ObjectID)=0
if CSM_DebugOn>0
CSM_DebugAddMessage(get time$()+ ": CSM_ObjectUpdate -> Object does not exist, removed from CSM system, ObjectID="+str$(CSM_Objects(i).ObjectID)+")")
endif
CSM_ObjectRemove(CSM_Objects(i).ObjectID)
dec i,1
endif
Next i
Endfunction
///////////////////////////////////////
// Light handling functions //
///////////////////////////////////////
//Sort array by active
function CSM_LightUpdateArray()
local i as integer
local Swapped as boolean
local tSwap as CSM_LightType
//Do a bubble sort by active
repeat
Swapped=0
for i=1 to CSM_LightArrayLength
if CSM_Lights(i-1).Active<CSM_Lights(i).Active
tSwap = CSM_Lights(i-1)
CSM_Lights(i-1) = CSM_Lights(i)
CSM_Lights(i) = tSwap
Swapped=1
endif
Next i
until Swapped=0
//Update shader data
CSM_LightUpdateShaderData()
Endfunction
//Update shader with newest data
function CSM_LightUpdateShaderData()
local i as integer : local j as integer
for i=0 to CSM_LightArrayLength
//Update colour data
local fR as float : local fG as float : local fB as float
fR=(CSM_Lights(i).Colour.R*1.0)/255.0 : fG=(CSM_Lights(i).Colour.G*1.0)/255.0 : fB=(CSM_Lights(i).Colour.B*1.0)/255.0
if fR>255.0 then fR=255.0 : if fG>255.0 then fG=255.0 : if fB>255.0 then fB=255.0
set vector4 CSM_Vector4ID,fR,fG,fB,0.0 : set effect constant vector CSM_EffectID,"LCol_"+str$(i),CSM_Vector4ID
//Update pos data
set vector4 CSM_Vector4ID,CSM_Lights(i).Pos.X,CSM_Lights(i).Pos.Y,CSM_Lights(i).Pos.Z,0 : set effect constant vector CSM_EffectID,"LPos_"+str$(i),CSM_Vector4ID
//Update range data
set effect constant float CSM_EffectID,"LRng_"+str$(i),CSM_Lights(i).Range
Next i
//Update other shader instances
for j=0 to CSM_ObjectCount
if CSM_Objects(j).EffectID<>CSM_EffectID
for i=0 to CSM_LightArrayLength
//Update colour data
local fR as float : local fG as float : local fB as float
fR=(CSM_Lights(i).Colour.R*1.0)/255.0 : fG=(CSM_Lights(i).Colour.G*1.0)/255.0 : fB=(CSM_Lights(i).Colour.B*1.0)/255.0
if fR>255.0 then fR=255.0 : if fG>255.0 then fG=255.0 : if fB>255.0 then fB=255.0
set vector4 CSM_Vector4ID,fR,fG,fB,0.0 : set effect constant vector CSM_Objects(j).EffectID,"LCol_"+str$(i),CSM_Vector4ID
//Update pos data
set vector4 CSM_Vector4ID,CSM_Lights(i).Pos.X,CSM_Lights(i).Pos.Y,CSM_Lights(i).Pos.Z,0 : set effect constant vector CSM_Objects(j).EffectID,"LPos_"+str$(i),CSM_Vector4ID
//Update range data
set effect constant float CSM_Objects(j).EffectID,"LRng_"+str$(i),CSM_Lights(i).Range
Next i
endif
Next j
Endfunction dist
//Update light properties for pulse lights
function CSM_LightPulseUpdate()
local i as integer : local InterpolatePercent as float
local CurrentTime as integer : CurrentTime=timer()
for i=0 to CSM_LightArrayLength
if CSM_Lights(i).LightPulseSpeed>0.0
inc CSM_Lights(i).LightPulsePhase, CSM_Lights(i).LightPulseSpeed*(CurrentTime-CSM_Lights(i).LightPulseLast)
if CSM_Lights(i).LightPulsePhase>360.0 then CSM_Lights(i).LightPulsePhase=0.0
InterpolatePercent = CSM_Sin(int(CSM_Lights(i).LightPulsePhase))
if CSM_Lights(QueueIndex).LightPulseDoNotUpdateColour=0
CSM_Lights(i).Colour.R = CSM_InterpolateByte(CSM_Lights(i).LightPulseColour1.R,CSM_Lights(i).LightPulseColour2.R,InterpolatePercent)
CSM_Lights(i).Colour.G = CSM_InterpolateByte(CSM_Lights(i).LightPulseColour1.G,CSM_Lights(i).LightPulseColour2.G,InterpolatePercent)
CSM_Lights(i).Colour.B = CSM_InterpolateByte(CSM_Lights(i).LightPulseColour1.B,CSM_Lights(i).LightPulseColour2.B,InterpolatePercent)
endif
if CSM_Lights(QueueIndex).LightPulseDoNotUpdateRange=0 then CSM_Lights(i).Range=CSM_InterpolateByte(CSM_Lights(i).LightPulseRange1,CSM_Lights(i).LightPulseRange2,InterpolatePercent)
CSM_Lights(i).LightPulseLast =CurrentTime
endif
next i
Endfunction
//Interpolate between two values given a percentage
function CSM_InterpolateFloat(Value1 as float, Value2 as float, Percentage as float)
local rOutput as float
rOutput=Value1+((Value2-Value1)*Percentage)
Endfunction rOutput
function CSM_InterpolateByte(Value1 as integer, Value2 as integer, Percentage as float)
local rOutput as integer
rOutput=Value1+((Value2-Value1)*Percentage)
if rOutput<0 then rOutput=0
if rOutput>255 then rOutput=255
Endfunction rOutput
///////////////////////////////
// Get queue index function //
///////////////////////////////
function CSM_LightGetArrayIndexByID(LightID as integer)
local i as integer
//Search lights array
for i=CSM_LightArrayLength to 0 step -1
if CSM_Lights(i).LightID=LightID
exitfunction i
endif
Next i
Endfunction -1
///////////////////////////////
// Debug functions //
///////////////////////////////
//Add a message to the debug message buffer
function CSM_DebugAddMessage(MessageString as string)
local i as integer
//Check message is not current
for i=0 to CSM_DebugMessageBufferLength
if CSM_DebugMessages(i)=MessageString then exitfunction
Next i
//Add message to queue
for i=0 to CSM_DebugMessageBufferLength-1
CSM_DebugMessages(i)=CSM_DebugMessages(i+1)
Next i
CSM_DebugMessages(CSM_DebugMessageBufferLength)=MessageString
Endfunction
//Print debug messages to screen
function CSM_DebugPrint()
local TextHeight as integer : TextHeight=(text height("A")+2)
local x as integer : local y as integer
local tablex as integer
local x1 as integer : local x2 as integer : local y1 as integer : local y2 as integer
//Print basic info at top of screen
x=20 : y=50
text x,y,"CSM debug data:": inc y,TextHeight
text x,y,"Active light count="+str$(CSM_LightActiveCount) : inc y,TextHeight
//Print light table next
local ColumnWidth as integer : ColumnWidth=125
inc y,TextHeight
tablex=20+(0.5*(text width("Shader light ID"))) : x=tablex
center text x,y,"Shader light ID": inc x,ColumnWidth : center text x,y,"CSM light ID" : inc x,ColumnWidth : center text x,y,"Position": inc x,ColumnWidth : center text x,y,"Colour": inc x,ColumnWidth : center text x,y,"Range": inc x,ColumnWidth : center text x,y,"Pulse speed": inc x,ColumnWidth : center text x,y,"Pulse phase": inc x,ColumnWidth : center text x,y,"Remove time": inc x,ColumnWidth
for i=0 to CSM_LightArrayLength
x=tablex : inc y,TextHeight
center text x,y,str$(i) : inc x,ColumnWidth
center text x,y,str$(CSM_Lights(i).LightID) : inc x,ColumnWidth
center text x,y,str$(int(CSM_Lights(i).Pos.X))+","+str$(int(CSM_Lights(i).Pos.Y))+","+str$(int(CSM_Lights(i).Pos.Z)) : inc x,ColumnWidth
center text x,y,str$(int(CSM_Lights(i).Colour.R))+","+str$(int(CSM_Lights(i).Colour.G))+","+str$(int(CSM_Lights(i).Colour.B)) : inc x,ColumnWidth
center text x,y,str$(CSM_Lights(i).Range) : inc x,ColumnWidth
center text x,y,left$(str$(CSM_Lights(i).LightPulseSpeed),7) : inc x,ColumnWidth
center text x,y,left$(str$(CSM_Lights(i).LightPulsePhase),7) : inc x,ColumnWidth
center text x,y,str$(CSM_Lights(i).RemoveAfterTime) : inc x,ColumnWidth
Next i
//Print debug messages at bottom of screen
y1=screen height()-((CSM_DebugMessageBufferLength+1)*TextHeight)-40 : x1=20
y2=screen height()-20 : x2 = screen width()-20
line x1,y1,x2,y1 : line x2,y1,x2,y2 : line x2,y2,x1,y2 : line x1,y2,x1,y1
x=x1+10 : y=y1+10
for i=CSM_DebugMessageBufferLength to 0 step -1
text x,y,CSM_DebugMessages(i) : inc y,TextHeight
Next i
Endfunction
//Set debugging on/off
function CSM_SetDebugOn(DebugState as boolean)
CSM_DebugOn=DebugState
Endfunction
///////////////////////////////
// Get free... functions //
///////////////////////////////
//Get a free ID
function CSM_GetFreeCameraID()
local i as integer
repeat : inc i : until camera exist(i)=0
Endfunction i
function CSM_GetFreeImageID()
local i as integer
repeat : inc i : until image exist(i)=0
Endfunction i
function CSM_GetFreeEffectID()
local i as integer
repeat : inc i : until effect exist(i)=0
Endfunction i
function CSM_GetFreeCubemapID()
local i as integer
repeat : inc i : until dynamic cube map exist(i)=0
Endfunction i
And here is the example's code:
//==========================================================
// Cubic Shadow Mapping
//==========================================================
// Shader By EVOLVED adapted for multiple lights by Bruce
// DBP code/CSM system by Bruce
//==========================================================
//Include the CSM source file or add it to your project
#include "Functions_CSM_V1_1.dba"
//This is CSM's set debug on function, with it you can turn debugging on or off (by setting 1 for on or 0 for off).
//This get explained a bit more later.
CSM_SetDebugOn(1)
//Setup Display -> set display to desktop screen resolution
load dll "user32.dll",1
Sw=call dll(1,"GetSystemMetrics",0)
Sh=call dll(1,"GetSystemMetrics",1)
delete dll 1
set display mode Sw,Sh,32,1 : set window off
sync on : sync rate 0
hide mouse
//Set Text
set text font "Verdana"
set text size 15
set text to bold
ink rgb(200,200,0),0
//Setup Camera -> Standard camera setup
backdrop on
color backdrop rgb(128,128,128)
autocam off
position camera 0,0,-150
set camera fov 85
xrotate camera 30
CamDis#=-100
//CSM start the Cubic Shadow Mapping functions.
CSM_Start(512)
//The number called with this function is the shadow quality (the resolution of the shadow maps).
//The higher the number, the better the shadows will look but the slower the shadow shader will run.
//Works with any number but powers of 2 are best, 256 is low quality, 512 is my preference and 1024+ is high quality
//Load Textures to apply to our objects
//-> the textures with '_n' after the name are normalmaps, you'll need them for the shader to work.
//If you don't know what a normal map is, google for it, there's loads of info on the web!
load image "Media/rockwall.dds",1
load image "Media/rockwall_n.dds",2
load image "Media/Floor.dds",4
load image "Media/Floor_n.dds",5
//Create Object -> Load and scale a teapot object
load object "Media/t-pot.x",1
scale object 1,4500,4500,4500
scale object texture 1,0,4,3
//When we apply our textures to our object, they have to be applied in a specific way, but the next command does all that for us!
//We call this command like this: CSM_ObjectTexture(Object_ID, Diffuse_Texture_ID, Normalmap_Texture_ID)
//and that's it! Our object is all set up for shadows and normal mapping! The textures must already be loaded and the object
//must exist, otherwise the command will fail.
CSM_ObjectTexture(1,1,2)
//NEW!! We can now call this function with negative numbers for the texture IDs (Diffuse, Normal, or both) to tell CSM not to
//apply that texture; if this is done we can apply the textures to the object ourselves.
////////////////////////////////////////////
///// ALPHA ////
////////////////////////////////////////////
//Before we can set an object's alpha value we must first enable it. We can enable or disable alpha with this function:
//CSM_ObjectAlphaEnable(1,1)
//Which is called like this: CSM_ObjectAlphaEnable(ObjectID as integer, AlphaEnabled as boolean)
//Now that alpha has been enabled we can set an alpha value. Alpha values are float values between 0.0 and 1.0 NOT 0 and 255!!
//That means to get 75% alpha we simply use an alpha value of 0.75. Let's set the teapot to 50% transparency:
//CSM_ObjectAlphaSet(1,0.5)
//This function is called like this: CSM_ObjectAlphaSet(ObjectID as integer, AlphaValue as float)
//Create floor -> make a floor object so we can see the shadows
make object box 2,500,1,500
scale object texture 2,0,5,5
position object 2,0,-65,0
//CSM -> Called like before
CSM_ObjectTexture(2,4,5)
//Make some random objects to cast shadows
for i=1 to 50
obj=3+i
prim=rnd(2)
if prim=0 then make object sphere obj,25
if prim=1 then make object cube obj,25
if prim=2 then make object cone obj,25
position object obj,rnd(500)-250,-50,rnd(500)-250
//Apply textures as before
CSM_ObjectTexture(obj,1,2)
//Objects made and not added to the CSM system using 'CSM_ObjectTexture' will still cast shadows. If you want an object NOT to
//cast a shadow then set the object mask so only camera 0 renders the object:
//set object mask ObjectID,%0001
//'%0001' are binary (all binary numbers start with '%' followed by the bits, which are read from right to left) flags
//for camera rendering. The '1' on the far right is for camera 0, the '0' to the left of the '1' is the flag for camera
//1, the next '0' for camera 2 and so on upto camera 32 (but you don't need to put in all the zeros!).
//With this line we are telling DBP that this obejct can only be seen by camera 0.
Next
//Light Flares -> These are objects simply to show us where the lights are!
//We'll use them later.
load image "Media/Flare.JPG",998
make object plain 998,50,50
texture object 998,998
ghost object on 998
set object ambient 998,0
Clone Object 999,998
Clone Object 1000,998
Clone Object 1001,998
Clone Object 1002,998
Clone Object 1003,998
//OK, so now we're going to add a light. We'll use the command 'CSM_LightAdd'
//the inputs are like so: CSM_LightAdd(Position sdX , Position Y , Position Z , Light Range)
mylight=CSM_LightAdd(0,75,50,200)
//the 'CSM_LightAdd' returns an integer, this is the light's ID which can be used to set, change or get
//the light's properties.
//We're going to set a property now:
CSM_LightSetLinkedObject(mylight,998,PFX_BloomCameraID)
//Often, you'll want to position an object at the light's source and point this object at a camera (e.g. lens flares).
//This function allows the system to automatically update the position of the object and point it at the camera ID we give.
//The inputs are so: CSM_LightSetLinkedObject(Light ID , Object ID , Camera to point at ID) the light, object and camera
//must exist or the command will fail (with debugging on).
//Let's make some other lights and link the objects we made earlier.
mylight=CSM_LightAdd(0,75,50,250)
CSM_LightSetLinkedObject(mylight,999,PFX_BloomCameraID)
mylight=CSM_LightAdd(-250,50,-250,150)
CSM_LightSetLinkedObject(mylight,1000,PFX_BloomCameraID)
//OK, now lights are cool but white is a bit boring. This next command allows us to change the colour of the light
//it is called like this: CSM_LightSetColour(Light ID , Red component as byte , Green component as byte , Blue component as byte)
//Here I'll set a random colour.
CSM_LightSetColour(mylight,rnd(255),rnd(255),rnd(255))
mylight=CSM_LightAdd(250,50,-250,150)
CSM_LightSetColour(mylight,rnd(255),rnd(255),rnd(255))
CSM_LightSetLinkedObject(mylight,1001,0)
mylight=CSM_LightAdd(-250,50,250,150)
CSM_LightSetLinkedObject(mylight,1002,PFX_BloomCameraID)
//One more thing we can do is make a pulsating light, we can vary the range or the colour or both, the system will handle interpolation and updating
//automatically, this one function is all we need:
//CSM_LightSetPulse(Light ID , Pulse duration in milliseconds , Starting phase angle, Range 1 , Range 2, R1 , G1 , B1 , R2 , G2 , B2)
CSM_LightSetPulse(mylight,5000.0,0, 75.0,250.0, rnd(255),rnd(255),rnd(255), rnd(255),rnd(255),rnd(255))
//The pulse function uses a sin-wave to interpolate the values. The starting phase angle is used to start the light a certain way through the pulse
//e.g. if we wanted a light with a very long duration, say 10 or 20 mins, and wanted it to start bright but then get darker (to simulate
//a day/night cycle for example) then we would set the phase time appropriately:
//CSM_LightSetPulse(mylight,500000.0, 90, 10.0,1000.0, 255,255,255, 255,255,255)
//The pahse angle here is 90 degrees so the pulse will start at the brightest point of the pulse. 180 degrees is the darkest point of the pulse.
//This is an important function. It resets all the cubemaps on all the objects associated with the CSM system.
//This should be the first thing you try when debugging CSM lights, put this command in after all the objects are set up but before your
//main loop. It is called without inputs. There shouldn't be any problems here so we won't call it now.
//CSM_ObjectCubemapsRefresh()
`Start loop
do
`Control Camera
position camera PFX_BloomCameraID,0,0,0
if mouseclick()=0
xrotate camera PFX_BloomCameraID,camera angle x(PFX_BloomCameraID)-mousemovey()*0.25
yrotate camera PFX_BloomCameraID,camera angle y(PFX_BloomCameraID)+mousemovex()*0.25
if camera angle x(PFX_BloomCameraID)>80 then xrotate camera PFX_BloomCameraID,80
if camera angle x(PFX_BloomCameraID)<-60 then xrotate camera PFX_BloomCameraID,-60
endif
if mouseclick()>0 then CamDis#=CamDis#-mousemovey()*0.25
CamDis#=CamDis#+mousemovez()*0.25
if CamDis#>-20 then CamDis#=-20
if CamDis#<-300 then CamDis#=-300
move camera PFX_BloomCameraID,CamDis#
if camera position y(PFX_BloomCameraID)<-60 then position camera PFX_BloomCameraID,camera position x(PFX_BloomCameraID),-60,camera position z(PFX_BloomCameraID)
mousemovex()=0
mousemovey()=0
`Rotate object
if KEYSTATE(19)=1 and rotate=1 and nopress=0 then rotate=0:nopress=1
if KEYSTATE(19)=1 and rotate=0 and nopress=0 then rotate=1:nopress=1
if rotate=1
rotate object 1,0,object angle y(1)+0.5,0
endif
`Move Light(s)
if KEYSTATE(38)=1 and MoveLight=1 and nopress=0 then MoveLight=0:nopress=1
if KEYSTATE(38)=1 and MoveLight=0 and nopress=0 then MoveLight=1:nopress=1
if MoveLight=0
ang#=wrapvalue(ang#+0.25)
ang2#=wrapvalue(ang#+120)
//CSM
//Here we will set a new position for lights 0 and 1 (the first and second lights), this function
//is called so: CSM_LightSetPosition(Light ID, Position X , Position Y , Position Z) there's
//not much more to say about it.
CSM_LightSetPosition(0,cos(ang#)*90,80,sin(ang#)*90)
CSM_LightSetPosition(1,cos(ang2#)*90,80,sin(ang2#)*90)
endif
`Change Texture
if KEYSTATE(20)=1 and nopress=0
delete image 1:delete image 2
inc image
if image>4 then image=1
if image=1 then load image "Media/rockwall.dds",1 :load image "Media/rockwall_n.dds",2
if image=2 then load image "Media/wall1.dds",1:load image "Media/wall1_n.dds",2
if image=3 then load image "Media/oldwall3.dds",1:load image "Media/oldwall3_n.dds",2
if image=4 then load image "Media/rock4_1.dds",1 :load image "Media/rock4_1_n.dds",2
//Retexture objects
for i=1 to 100
if object exist(i)=1 and i<>2 then CSM_ObjectTexture(i,1,2)
Next i
nopress=1
endif
`Change Object
if Spacekey()=1 and nopress=0
delete object 1
inc object
if object>5 then object=1
if object=1 then load object "Media/t-pot.x",1:scale object 1,4500,4500,4500:scale object texture 1,0,4,3
if object=2 then load object "Media/Tosus.x",1:scale object texture 1,0,1.5,1
if object=3 then make object box 1,75,75,75
if object=4 then make object sphere 1,75,40,40:scale object texture 1,0,2,1
if object=5 then make object cylinder 1,75:scale object texture 1,0,3,1
CSM_ObjectTexture(1,1,2)
set object effect 1,1
nopress=1
endif
`Text
center text sw/2,15,"T - Change Texture Space - Change Object R - Rotate Object L - Move Light"
center text sw/2,30,"Return - Flashlight Arrowkeys - Turn lights on/off Control - Debug text"
center text sw/2,45,"FPS "+str$(screen fps())+" @ "+str$(sw)+"x"+str$(sh)
//Here we can turn lights on and off, we can do that with the 'CSM_LightSetActive' function
//it is called like this: CSM_LightSetActive(Light ID , Active) where 'Active' is 0 for off
//and 1 for on. This will not remove a light from the system and should be used to temporarily
//turn lights off or on. To remove a light permanently, the function 'CSM_LightRemove(Light ID)'
//Should be used.
CSM_LightSetActive(0,1-upkey())
CSM_LightSetActive(1,1-downkey())
CSM_LightSetActive(3,1-leftkey())
CSM_LightSetActive(2,1-rightkey())
//Make light flash when return is pressed
if returnkey()>0 and nopress=0
//Here is a useful function (e.g. for weapon muzzle flashes). Here we will create a light flash. This is a light which
//will automatically be removed after a certain amount of time. It is called like this:
//Light ID = CSM_LightFlashAdd(Position X , Position Y , Position Z , Range , Duration in milliseconds)
//When the time is over the light will be automatically deleted (it must be made again, you cannot turn it back on with
//'CSM_LightSetActive'). The settings for this type of light can be set just like a normal light.
mylight=CSM_LightFlashAdd(250,50,250,150,500)
CSM_LightSetColour(mylight,rnd(255),rnd(255),rnd(255))
CSM_LightSetLinkedObject(mylight,1003,0)
// CSM_LightSetPulse(mylight,500.0,0, 75.0,250.0, rnd(255),rnd(255),rnd(255), rnd(255),rnd(255),rnd(255))
//We could use the rem'd-out line above to make a pulsating light flash. Try it and see.
nopress=1
Endif
//Unlock keys on lift
if (KEYSTATE(19)+KEYSTATE(38)+KEYSTATE(20)+spacekey()+returnkey())=0 then nopress=0
//This is an example of two functions which weren't used in this demo:
// if CSM_LightExist(mylight)=1
// CSM_LightRemove(mylight)
// endif
//The 'CSM_LightExist' function is called with a light ID and returns a boolean (1 for light does exist and 0 for light
//doesn't exist) and the 'CSM_LightRemove' function is called with a light ID and permanently deletes the light (it must
//be made again, you cannot turn it back on with 'CSM_LightSetActive').
//And one more function we didn't use:
//CSM_ObjectRemove( ObjectID as integer )
//This function DOES NOT DELETE THE OBJECT, only removes it from the CSM system so that it is no longer affected by the
//shader and will not cast shadows.
//And a new function:
//CSM_Flush()
//This function is called without arguments. This function returns the CSM system to the state it was in when first started.
//Basically this is an easy way to reset the system eg. between levels.
//This function MUST be called in your loop after you have positioned, coloured, etc. all your lights & objects
//but BEFORE the sync function.
CSM_Update()
//Here we are again, the CSM_SetDebugOn function. This function just sets debugging on or off, the CSM_Update function prints
//debug data to the screen. Turning debugging on will reduce performance, turning debugging off will skip error catching/handling.
CSM_SetDebugOn(controlkey())
//Sync the screen and loop back to the top.
sync mask %01 : sync
loop
All these and the DBP project file are in the download along with a compiled .exe of the example (7MB total).
Comments welcome!
Thanks,
Bruce
"... Why the hell did I chose game creation as a hobby!?" - Burning Feet Man