I've been doing some tests on my own, and got to do a small shadow mapping system. But then, I quickly came to the conclusion that for correctly shadowing the reciever objects, you need to access the ZBuffer (as for the actual shadows being casted on objects that are infront of the caster), therefore there's no way to do it fast without shaders :/
If you want to test it out...
If you want to test it out...
Include "FastExt.bb" Include "ShadowMaps.bb" Graphics3D(1024, 768, 0, 2) InitExt() ; -------------------------------- AmbientLight(64, 64, 64) Local Plane = CreateSphere() ScaleEntity(Plane, 10, 0.1, 10) TranslateEntity(Plane, 0, -1, 0) Local Cube = CreateCube() ScaleEntity(Cube, 0.7, 0.7, 0.7) TranslateEntity(Cube, 0, 0.6, 0) Local Cone = CreateCone() ScaleEntity(Cone, 0.7, 0.7, 0.7) TranslateEntity(Cone, 0, 0, 2.5) Local Sphere = CreateSphere() ScaleEntity(Sphere, 0.7, 0.7, 0.7) TranslateEntity(Sphere, -1, 0, -2.5) Local Camera = CreateCamera() TranslateEntity(Camera, 0, 5, 10) PointEntity(Camera, Cube) Local Light.ShadowMap_Light = ShadowMap_CreateLight(1, 1000, 1024) TranslateEntity(Light\Light, 0, 8, 10) PointEntity(Light\Light, Cube) CubeCaster.ShadowMap_Caster = ShadowMap_AddCaster(Light, Cube) ShadowMap_AddReciever(Light, Cone) ShadowMap_AddReciever(Light, Sphere) ShadowMap_AddReciever(Light, Plane) ; -------------------------------- While(Not KeyHit(1)) MouseLook(Camera) If (KeyDown(2)) Then TranslateEntity(Cube, -.1, 0, 0) If (KeyDown(3)) Then TranslateEntity(Cube, .1, 0, 0) If (KeyDown(4)) Then TranslateEntity(Cube, 0, -.1, 0) If (KeyDown(5)) Then TranslateEntity(Cube, 0, .1, 0) TurnEntity(Cube, 0.1, 0.2, 0.4) UpdateWorld() HideEntity(Camera) ShadowMap_Update(Light) ShowEntity(Camera) RenderWorld() Flip(True) FPS() Wend ; -------------------------------- End Global FPSCount = 0 Global FPSCountTemp = 0 Global FPSTime = 0 Function FPS() If (MilliSecs()-FPSTime)>=1000 Then FPSTime = MilliSecs() FPSCount = FPSCountTemp FPSCountTemp = 0 EndIf FPSCountTemp = FPSCountTemp + 1 AppTitle(Str$(FPSCount)) Return FPSCount End Function Function MouseLook ( ent, mov# = 0.3 ) mxspd#=MouseXSpeed()*0.25 myspd#=MouseYSpeed()*0.25 campitch#=EntityPitch(ent)+myspd# If campitch#<-65 Then campitch#=-65 If campitch#>65 Then campitch#=65 RotateEntity ent,campitch#,EntityYaw(ent)-mxspd#,EntityRoll(ent) If KeyDown(17) MoveEntity ent,0,0,mov If KeyDown(31) MoveEntity ent,0,0,-mov If KeyDown(32) MoveEntity ent,mov,0,0 If KeyDown(30) MoveEntity ent,-mov,0,0 MoveMouse GraphicsWidth()/2,GraphicsHeight()/2 End Function ; --------------------------------------------------------------------------------------------------------- ; RecursiveAnimate ; --------------------------------------------------------------------------------------------------------- Function RecursiveAnimate(entity, mode=1, speed#=1.0, sequence=0, transition#=0.0) If (AnimLength(entity)<>-1) Then Animate(entity, mode, speed#, sequence, transition#) For i=1 To CountChildren(entity) RecursiveAnimate(GetChild(entity, i), mode, speed#, sequence, transition#) Next End Function ; --------------------------------------------------------------------------------------------------------- ; RecursiveExtractAnimSeq ; --------------------------------------------------------------------------------------------------------- Function RecursiveExtractAnimSeq(entity, first_frame, last_frame, anim_seq=0) If (AnimLength(entity)<>-1) Then ExtractAnimSeq(entity, first_frame, last_frame, anim_seq) For i=1 To CountChildren(entity) RecursiveExtractAnimSeq(GetChild(entity, i), first_frame, last_frame, anim_seq) Next End Function
Type ShadowMap_Light Field Light Field Camera Field Texture End Type Type ShadowMap_Caster Field Entity Field Shadow End Type Type ShadowMap_Reciever Field Entity End Type Global ShadowMap_Ambient, ShadowMap_Dot Function ShadowMap_CreateLight.ShadowMap_Light(LightType=1, Radius# = 1000.0, MapQuality=512) Local Light.ShadowMap_Light = New ShadowMap_Light Light\Light = CreateLight(LightType) Light\Camera = CreateCamera(Light\Light) CameraClsColor(Light\Camera, 255, 255, 255) CameraRange(Light\Camera, 1, Radius#) CameraProjMode(Light\Camera, 0) CameraViewport(Light\Camera, 0, 0, MapQuality, MapQuality) CameraZoom(Light\Camera, 0.1) Light\Texture = CreateTexture(MapQuality, MapQuality, 1+16+32+256+FE_ZRENDER) If (ShadowMap_Dot = 0) Then ShadowMap_Ambient = CreateTexture(1, 1, 1) SetBuffer(TextureBuffer(ShadowMap_Ambient)) Color(64, 64,64) Plot(0, 0) SetBuffer(BackBuffer()) ShadowMap_Dot = CreateTexture(1, 1, 1) SetBuffer(TextureBuffer(ShadowMap_Dot)) Color(255, 255,255) Plot(0, 0) SetBuffer(BackBuffer()) End If TextureCoords(Light\Texture, 1) Return Light End Function Function ShadowMap_DestroyLight(Light.ShadowMap_Light) FreeEntity(Light\Camera) FreeTexture(Light\Texture) Delete Light End Function Function ShadowMap_AddCaster.ShadowMap_Caster(Light.ShadowMap_Light, Entity) Local Caster.ShadowMap_Caster = New ShadowMap_Caster Caster\Entity = Entity Caster\Shadow = CopyEntity(Entity, Entity) Local Brush = CreateBrush() BrushFX(Brush, 1+8+16) BrushTexture(Brush, ShadowMap_Ambient, 0, 0) BrushTexture(Brush, ShadowMap_Dot, 0, 1) BrushTexture(Brush, ShadowMap_Dot, 0, 2) BrushTexture(Brush, ShadowMap_Dot, 0, 3) BrushTexture(Brush, ShadowMap_Dot, 0, 4) BrushTexture(Brush, ShadowMap_Dot, 0, 5) BrushTexture(Brush, ShadowMap_Dot, 0, 6) BrushTexture(Brush, ShadowMap_Dot, 0, 7) RecursivePaintEntity(Caster\Shadow, Brush) Return Caster End Function Function ShadowMap_AddReciever.ShadowMap_Reciever(Light.ShadowMap_Light, Entity) Local Reciever.ShadowMap_Reciever = New ShadowMap_Reciever Reciever\Entity = Entity EntityTexture(Entity, Light\Texture, 0, 0) ; If the Reciever has childs, add them as recievers too Local i For i=1 To CountChildren(Entity) ShadowMap_AddReciever(Light, GetChild(Entity, i)) Next Return Reciever End Function Function ShadowMap_Update(Light.ShadowMap_Light) ; >>>>> STEP 1 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; Prepare light texture buffer to be rendered. DebugLog("") CameraProjMode(Light\Camera, 2) SetBuffer(TextureBuffer(Light\Texture)) ; Clear buffer ClsColor(255, 255, 255) Cls() ; Render caster entities Local Caster.ShadowMap_Caster For Caster = Each ShadowMap_Caster ShowEntity(Caster\Shadow) RenderEntity(Light\Camera, Caster\Shadow) HideEntity(Caster\Shadow) Next ; Done rendering the shadow map SetBuffer(BackBuffer()) ; >>>>> STEP 2 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; Calculate all UVs for the recievers Local Reciever.ShadowMap_Reciever For Reciever = Each ShadowMap_Reciever If (EntityInView(Reciever\Entity, Light\Camera)=False) Then Goto Skip Local Surface, i, j For i=1 To CountSurfaces(Reciever\Entity) Surface = GetSurface(Reciever\Entity, i) For j=0 To CountVertices(Surface)-1 ; Project vertex from local space to object space TFormPoint(VertexX#(Surface, j), VertexY#(Surface, j), VertexZ#(Surface, j), Reciever\Entity, 0) ; Calculate UVs in camera space CameraProject(Light\Camera, TFormedX#(), TFormedY#(), TFormedZ#()) VertexTexCoords(Surface, j, ProjectedX#()/Float#(TextureWidth(Light\Texture)), ProjectedY#()/Float#(TextureHeight(Light\Texture)), 0, 1) Next Next .Skip Next ; Hide camera CameraProjMode(Light\Camera, 0) End Function Function RecursivePaintEntity(entity, brush) If (EntityClass$(entity)="Mesh") Then PaintEntity(entity, brush) For i=1 To CountChildren(entity) RecursivePaintEntity(GetChild(entity, i), brush) Next End Function