Terrain shadows


Tweet blitz3d shaders terrain code-archives effects
(Posted 8 months ago) RonTek

Simple and fast shadows for blitz terrains without shaders.

This is a method that is aligning a small terrain on a bigger terrain (like a towel) and takes an orthographic render from above the player. The small terrain will then be mapped with this render, so it becomes a shadowmap.

This method is not object oriented and therefor it's pretty fast. It expects all Objects to be indexed in certain arrays. People may combine their meshbased terrains with blitz terrains to make use of it.
Currently it allows only one light, a miday sunlight.

Download Full Source + Media | Mirror

Image

; shadows for terrains, by jfk of csp
Graphics3D 1024,768,32,1
SetBuffer BackBuffer()
WBuffer 1


; ----- main camera and player pivot -----
Global camera=CreateCamera()
CameraRange camera,0.01,2000
CameraClsColor camera,100,150,200
Global player=CreatePivot()
TranslateEntity camera,0,5,0
EntityParent camera,player
MoveEntity player,0,100,0
EntityRadius player,5
EntityType player,2




; -----shadow camema -----
Global ShadowCam=CreateCamera()
CameraProjMode ShadowCam,2
HideEntity Shadowcam


; ----- a lit terrain -----
Global terrain=LoadTerrain("myhmap1.png")
Global towel_scale_Y#=100
ScaleEntity terrain,10,towel_scale_Y#,10
PositionEntity terrain,-TerrainSize(terrain)*5,0,-TerrainSize(terrain)*5
terrtex=LoadTexture("rock1.jpg")
EntityTexture terrain,terrtex
ScaleTexture terrtex,10,10
EntityType terrain,1
light=CreateLight()
RotateEntity light,-45,45,0
TerrainShading terrain,1
TerrainDetail terrain,1000



; ----- init shadow texture -----
Global ShadowTexSize=512 ; defines the resolution of the shadow texture
Global ShadowTex=CreateTexture(ShadowTexSize,ShadowTexSize,256)
Global shadow_Towel_Yoffset#=0.7 ; used to prevent "blinking" towel
; NOTE to make sure the offset is not so obvious, you should use characters with dark shoes 
; or trees with a darkish trunk etc.



; ----- create Shadow Towel -----
Global towel_size#=32 ; defines the number of segments
Global cam_towel=CreateTerrain(towel_size#)
EntityFX cam_towel,1
Global cam_towel_piv=CreatePivot()
Global towel_scale_XZ#=12 ; defines the XZ scale factor
ScaleEntity cam_towel,towel_scale_XZ#,towel_scale_Y#,towel_scale_XZ#
PositionEntity cam_towel,(-TerrainSize(cam_towel)*towel_scale_XZ#)/2.0,0,(-TerrainSize(cam_towel)*towel_scale_XZ#)/2.0,1
EntityParent cam_towel,cam_towel_piv
EntityTexture cam_towel,ShadowTex
TextureBlend shadowtex,2
EntityBlend cam_towel,2
ScaleTexture shadowtex,-towel_size#,-towel_size#
TerrainDetail cam_towel,1000


; ----- create some dummy scene objects -----
testtex=LoadTexture("colors.jpg")
Global num_o=500
Dim c(num_o),c_brush(num_o)
For i=0 To num_o
 c(i)=CreateCube()
 ScaleEntity c(i),2,20,2
 PositionEntity c(i),Rnd(-1280,1280),0,Rnd(-1280,1280)
 y#=TerrainY(terrain,EntityX(c(i)),0,EntityZ(c(i)) )
 PositionEntity c(i),EntityX(c(i)),y+5+Rand(1),EntityZ(c(i))
 EntityTexture c(i),testtex
 RotateEntity c(i),Rand(360),Rand(360),Rand(360)
 EntityColor c(i),100,100,100
 c_brush(i)=GetEntityBrush(c(i))
Next
; NOTE: all meshes and their brushes etc. (but the terrain) need to be indexed in this arrays to make 
; them cast shadows!


; ---------
; several brushes used to paint background and shadow casters during shadow map rendering
Global whitebrush=CreateBrush(255,255,255)
;Global whitebrush=CreateBrush(255,0,255) ; use this to make the towel visible (for debugging)
BrushFX whitebrush,1
Global shadowbrush=CreateBrush(140,140,140) ; defines the darkness of the shadows
BrushFX shadowbrush,1
Global terrainbrush=GetEntityBrush(terrain)


Collisions 2,1,2,2
; ----- main loop -----
While KeyDown(1)=0
 For i=0 To num_o
  TurnEntity c(i),1,2,3 ; show that it's dynamic 
 Next

 If KeyDown(200)=1 ; mouselook controls
  MoveEntity player,0,0,1
 EndIf
 If KeyDown(208)=1
  MoveEntity player,0,0,-1
 EndIf
 If KeyDown(205)=1
  MoveEntity player,1,0,0
 EndIf
 If KeyDown(203)=1
  MoveEntity player,-1,0,0
 EndIf
 msx#=0.25*(-MouseXSpeed())
 msy#=0.25*MouseYSpeed()
 MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
 TurnEntity player,0,msx#,0
 TurnEntity camera,msy#,0,0


 If KeyDown(57)=0
  TranslateEntity player,0,-.5,0; gravity
 Else
  TranslateEntity player,0,.5,0; allow to fly with space key
 EndIf

 UpdateShadows(terrain,cam_towel,cam_towel_piv)
 UpdateWorld()
 RenderWorld()
 old_t=t
 t=MilliSecs()
 Text 0,0,(1000.0/(t-old_t))+" fps"
 Text 0,16,"Tris rendered: "+TrisRendered()
 Flip
Wend
End



Function UpdateShadows(ground,towel,piv)
 x#=EntityX(player,1)
 z#=EntityZ(player,1)
 PositionEntity piv,x,shadow_Towel_Yoffset#,z,1
 RotateEntity piv,0,180,0,1
 ; align the shadow towel to the underlying terrain
 For i#=0 To TerrainSize(towel)-1
  x#=EntityX(towel,1)-(i*towel_scale_XZ#)
  For j#=0 To TerrainSize(towel)-1
   z#=EntityZ(towel,1)-(j*towel_scale_XZ#)
   tyl#=TerrainY(ground,x,0,z)
   ty#=((TerrainY#(ground,x,0,z))/towel_scale_Y#)
   ModifyTerrain towel,i,j,ty#
  Next
 Next

 ; hide borders
 For i#=0 To TerrainSize(towel)
   ModifyTerrain towel,i,TerrainSize(towel),0
 Next
 For j#=0 To TerrainSize(towel)
   ModifyTerrain towel,TerrainSize(towel),j,0
 Next
 UpdateShadowmap()
End Function






Function UpdateShadowmap()
 ; hide the towel, make the terrain white and all meshes grey
 For i=0 To num_o
  PaintEntity c(i),shadowbrush
  EntityFX c(i),1
 Next
 HideEntity cam_towel
 PaintEntity terrain, whitebrush
 ; toggle shadow camera (orthographic)
 HideEntity camera
 CameraClsColor shadowcam,255,255,255
 CameraZoom shadowcam,(.031 /towel_scale_XZ#)/(towel_size#/64.0) ; .028
 ShowEntity ShadowCam
 CameraProjMode ShadowCam,2
 ; take a render from above
 PositionEntity shadowcam, EntityX(player,1),1000,EntityZ(player,1)
 RotateEntity shadowcam,90,0,0
 CameraViewport shadowcam,0,0,ShadowTexSize,ShadowTexSize
 RenderWorld()
 ; copy that render to the shadow texture buffer
 CopyRect 0,0,ShadowTexSize,ShadowTexSize,0,0,BackBuffer(),TextureBuffer(ShadowTex)
 ;restore camera
 ShowEntity camera
 HideEntity ShadowCam
 ShowEntity cam_towel
 ; restore object materials
 PaintEntity terrain, terrainbrush
 For i=0 To num_o
  PaintEntity c(i),c_brush(i)
  EntityFX c(i),0
 Next
End Function

Reply To Topic (minimum 10 characters)

Please log in to reply