November 28, 2020, 01:48:01 PM

Author Topic: [bb] Terrain shadows by jfk EO-11110 [ 1+ years ago ]  (Read 625 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
[bb] Terrain shadows by jfk EO-11110 [ 1+ years ago ]
« on: June 29, 2017, 12:28:41 AM »
Title : Terrain shadows
Author : jfk EO-11110
Posted : 1+ years ago

Description : 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.
Sorry for the lot of globals, you will sort it :)

Download with Media (1 heightmap image and 2 textures) from:
<a href="http://www.melog.ch/dl/csp_bb_terrainshadow_05_1.zip" target="_blank">http://www.melog.ch/dl/csp_bb_terrainshadow_05_1.zip[/url]


Code :
Code: BlitzBasic
  1. ; shadows for terrains, by jfk of csp
  2. Graphics3D 1024,768,32,1
  3. SetBuffer BackBuffer()
  4. WBuffer 1
  5.  
  6.  
  7. ; ----- main camera and player pivot -----
  8. Global camera=CreateCamera()
  9. CameraRange camera,0.01,2000
  10. CameraClsColor camera,100,150,200
  11. Global player=CreatePivot()
  12. TranslateEntity camera,0,5,0
  13. EntityParent camera,player
  14. MoveEntity player,0,100,0
  15. EntityRadius player,5
  16. EntityType player,2
  17.  
  18.  
  19.  
  20.  
  21. ; -----shadow camema -----
  22. Global ShadowCam=CreateCamera()
  23. CameraProjMode ShadowCam,2
  24. HideEntity Shadowcam
  25.  
  26.  
  27. ; ----- a lit terrain -----
  28. Global terrain=LoadTerrain("myhmap1.png")
  29. Global towel_scale_Y#=100
  30. ScaleEntity terrain,10,towel_scale_Y#,10
  31. PositionEntity terrain,-TerrainSize(terrain)*5,0,-TerrainSize(terrain)*5
  32. terrtex=LoadTexture("rock1.jpg")
  33. EntityTexture terrain,terrtex
  34. ScaleTexture terrtex,10,10
  35. EntityType terrain,1
  36. light=CreateLight()
  37. RotateEntity light,-45,45,0
  38. TerrainShading terrain,1
  39. TerrainDetail terrain,1000
  40.  
  41.  
  42.  
  43. ; ----- init shadow texture -----
  44. Global ShadowTexSize=512 ; defines the resolution of the shadow texture
  45. Global ShadowTex=CreateTexture(ShadowTexSize,ShadowTexSize,256)
  46. Global shadow_Towel_Yoffset#=0.7 ; used to prevent "blinking" towel
  47. ; NOTE to make sure the offset is not so obvious, you should use characters with dark shoes
  48. ; or trees with a darkish trunk etc.
  49.  
  50.  
  51.  
  52. ; ----- create Shadow Towel -----
  53. Global towel_size#=32 ; defines the number of segments
  54. Global cam_towel=CreateTerrain(towel_size#)
  55. EntityFX cam_towel,1
  56. Global cam_towel_piv=CreatePivot()
  57. Global towel_scale_XZ#=12 ; defines the XZ scale factor
  58. ScaleEntity cam_towel,towel_scale_XZ#,towel_scale_Y#,towel_scale_XZ#
  59. PositionEntity cam_towel,(-TerrainSize(cam_towel)*towel_scale_XZ#)/2.0,0,(-TerrainSize(cam_towel)*towel_scale_XZ#)/2.0,1
  60. EntityParent cam_towel,cam_towel_piv
  61. EntityTexture cam_towel,ShadowTex
  62. TextureBlend shadowtex,2
  63. EntityBlend cam_towel,2
  64. ScaleTexture shadowtex,-towel_size#,-towel_size#
  65. TerrainDetail cam_towel,1000
  66.  
  67.  
  68. ; ----- create some dummy scene objects -----
  69. testtex=LoadTexture("colors.jpg")
  70. Global num_o=500
  71. Dim c(num_o),c_brush(num_o)
  72. For i=0 To num_o
  73.  c(i)=CreateCube()
  74.  ScaleEntity c(i),2,20,2
  75.  PositionEntity c(i),Rnd(-1280,1280),0,Rnd(-1280,1280)
  76.  y#=TerrainY(terrain,EntityX(c(i)),0,EntityZ(c(i)) )
  77.  PositionEntity c(i),EntityX(c(i)),y+5+Rand(1),EntityZ(c(i))
  78.  EntityTexture c(i),testtex
  79.  RotateEntity c(i),Rand(360),Rand(360),Rand(360)
  80.  EntityColor c(i),100,100,100
  81.  c_brush(i)=GetEntityBrush(c(i))
  82. Next
  83. ; NOTE: all meshes and their brushes etc. (but the terrain) need to be indexed in this arrays to make
  84. ; them cast shadows!
  85.  
  86.  
  87. ; ---------
  88. ; several brushes used to paint background and shadow casters during shadow map rendering
  89. Global whitebrush=CreateBrush(255,255,255)
  90. ;Global whitebrush=CreateBrush(255,0,255) ; use this to make the towel visible (for debugging)
  91. BrushFX whitebrush,1
  92. Global shadowbrush=CreateBrush(140,140,140) ; defines the darkness of the shadows
  93. BrushFX shadowbrush,1
  94. Global terrainbrush=GetEntityBrush(terrain)
  95.  
  96.  
  97. Collisions 2,1,2,2
  98. ; ----- main loop -----
  99. While KeyDown(1)=0
  100.  For i=0 To num_o
  101.   TurnEntity c(i),1,2,3 ; show that it's dynamic
  102.  Next
  103.  
  104.  If KeyDown(200)=1 ; mouselook controls
  105.   MoveEntity player,0,0,1
  106.  EndIf
  107.  If KeyDown(208)=1
  108.   MoveEntity player,0,0,-1
  109.  EndIf
  110.  If KeyDown(205)=1
  111.   MoveEntity player,1,0,0
  112.  EndIf
  113.  If KeyDown(203)=1
  114.   MoveEntity player,-1,0,0
  115.  EndIf
  116.  msx#=0.25*(-MouseXSpeed())
  117.  msy#=0.25*MouseYSpeed()
  118.  MoveMouse GraphicsWidth()/2,GraphicsHeight()/2
  119.  TurnEntity player,0,msx#,0
  120.  TurnEntity camera,msy#,0,0
  121.  
  122.  
  123.  If KeyDown(57)=0
  124.   TranslateEntity player,0,-.5,0; gravity
  125.  Else
  126.   TranslateEntity player,0,.5,0; allow to fly with space key
  127.  EndIf
  128.  
  129.  UpdateShadows(terrain,cam_towel,cam_towel_piv)
  130.  UpdateWorld()
  131.  RenderWorld()
  132.  old_t=t
  133.  t=MilliSecs()
  134.  Text 0,0,(1000.0/(t-old_t))+" fps"
  135.  Text 0,16,"Tris rendered: "+TrisRendered()
  136.  Flip
  137. Wend
  138. End
  139.  
  140.  
  141.  
  142. Function UpdateShadows(ground,towel,piv)
  143.  x#=EntityX(player,1)
  144.  z#=EntityZ(player,1)
  145.  PositionEntity piv,x,shadow_Towel_Yoffset#,z,1
  146.  RotateEntity piv,0,180,0,1
  147.  ; align the shadow towel to the underlying terrain
  148.  For i#=0 To TerrainSize(towel)-1
  149.   x#=EntityX(towel,1)-(i*towel_scale_XZ#)
  150.   For j#=0 To TerrainSize(towel)-1
  151.    z#=EntityZ(towel,1)-(j*towel_scale_XZ#)
  152.    tyl#=TerrainY(ground,x,0,z)
  153.    ty#=((TerrainY#(ground,x,0,z))/towel_scale_Y#)
  154.    ModifyTerrain towel,i,j,ty#
  155.   Next
  156.  Next
  157.  
  158.  ; hide borders
  159.  For i#=0 To TerrainSize(towel)
  160.    ModifyTerrain towel,i,TerrainSize(towel),0
  161.  Next
  162.  For j#=0 To TerrainSize(towel)
  163.    ModifyTerrain towel,TerrainSize(towel),j,0
  164.  Next
  165.  UpdateShadowmap()
  166. End Function
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173. Function UpdateShadowmap()
  174.  ; hide the towel, make the terrain white and all meshes grey
  175.  For i=0 To num_o
  176.   PaintEntity c(i),shadowbrush
  177.   EntityFX c(i),1
  178.  Next
  179.  HideEntity cam_towel
  180.  PaintEntity terrain, whitebrush
  181.  ; toggle shadow camera (orthographic)
  182.  HideEntity camera
  183.  CameraClsColor shadowcam,255,255,255
  184.  CameraZoom shadowcam,(.031 /towel_scale_XZ#)/(towel_size#/64.0) ; .028
  185.  ShowEntity ShadowCam
  186.  CameraProjMode ShadowCam,2
  187.  ; take a render from above
  188.  PositionEntity shadowcam, EntityX(player,1),1000,EntityZ(player,1)
  189.  RotateEntity shadowcam,90,0,0
  190.  CameraViewport shadowcam,0,0,ShadowTexSize,ShadowTexSize
  191.  RenderWorld()
  192.  ; copy that render to the shadow texture buffer
  193.  CopyRect 0,0,ShadowTexSize,ShadowTexSize,0,0,BackBuffer(),TextureBuffer(ShadowTex)
  194.  ;restore camera
  195.  ShowEntity camera
  196.  HideEntity ShadowCam
  197.  ShowEntity cam_towel
  198.  ; restore object materials
  199.  PaintEntity terrain, terrainbrush
  200.  For i=0 To num_o
  201.   PaintEntity c(i),c_brush(i)
  202.   EntityFX c(i),0
  203.  Next
  204. End Function


Comments :


Plantagenet(Posted 1+ years ago)

 Very good, and faster than I expected :)


jfk EO-11110(Posted 1+ years ago)

 Thanks :) Imagine, use this with a forest with animated trees and leafs + masked textures.


puki(Posted 1+ years ago)

 Yeh, forest stuff!Right, go write the demo "jfk" - I'll wait here.


jfk EO-11110(Posted 1+ years ago)

 well, simply use trees instead of them cubes. Oh yes an don't rotate the trees - well you can do so but it may look strange ;)Using the animated trees from the simple tree creator from coppercircle (toolbox) will make this easy.I have to say this routine is not extremly flexible so far. It uses the terrain only by now. If you want to have shadows on other things too (rocks, buildings etc.) you maybe have to precalculate a hypotetical heightmap and use it to align the shadow towel. Depending on the resolution of this heightmap it may eat some megs of memory.


puki(Posted 1+ years ago)

 Okay "jfk", I have a Gig of memory - I'll get more if needed.  I won't need to precalculate a 'hypotetical heightmap' (whatever that is) if you do it for me.In fact, can you add in roads/pathways and river beds for me too?  Ideally, I want a big terrain (textured).  However - I don't mind if you you give me an absolutely huge terrain in chunks, coz I can assemble that in code on-the-fly.I'll wait here.


jfk EO-11110(Posted 1+ years ago)

 Probably you should press the "make soopadoopa doom3 buster fps and pizza" button, right there near the power button :)Well if I'll every write some real funky shadow code, I surely won't be able to resist from posting it to the blitz code archives. Then again, the russian shadow Revolution, with their Revolution Leader Andrej offers an impressive solution (see showcase) for 60$.


Ching(Posted 1+ years ago)

 Gimme a few weeks and a gallon of tequilla. I need to study this.


nazca(Posted 1+ years ago)

 if you enable fog on the shadow camera, and set the fog range to 0, you don't need to index all of the objects, plus you wouldn't need to have 2 brushes for every object. Great code tho!


 

SimplePortal 2.3.6 © 2008-2014, SimplePortal