[bb] basic directional shadows by Kalisme [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:42

Previous topic - Next topic

BlitzBot

Title : basic directional shadows
Author : Kalisme
Posted : 1+ years ago

Description : I actually posted this in a forum a while ago...
This it pretty much the basis of the ShaKAL shadow library I was working on ages ago.
Hope it helps.


Code :
Code (blitzbasic) Select
;Attempt at explaining directional shadows
;-Kevin Laherty (kalisme@hotmail.com)

;This is mearly a re-release of a pseudo-tutorial I released ages ago.
;I refur to this as a pseudo-tutorial because I'm actually quite
;concerned that this will seem like total utter jibberish
;since I'm horrible at explaining things...
;This is based off code that someone posted in a forum
;a few years ago (great learning material).
;I don't know his name, but if you know who I'm talking about
;please inform me, he deserves alot of credit.

;Anywho, this code casts a directional shadow from a caster entity
;onto a receiver entity. It may not be the most stunning style
;of casting shadows, but it's quite fast (when coded right)
;and seems to blend quite well into a blitz3d game engine.
;I hope I help at least one person and someone uses it to
;fancy-up a game n_n

;This was also the basis of my ShaKAL library I was working on
;a long time ago. (If anyone remembers it)

Graphics3D 800,600
SetBuffer BackBuffer()
AmbientLight 0,0,0

;Ssize:
;the size of the shadows texture.
;(remember To use base 2... eg: 2 4 8 16 32 64 128 256 512)
;make sure it's smaller than the games resolution...
;eg: you can't render a 512x512 map on a 320x240 screen...
Global ssize=64
Global shadow_tex=CreateTexture(ssize,ssize,16+32) ;create the shadow texture
;Xscale:
;lets say the default zoom the shadow camera is 1.(it's actually .06, but 1 sounds easyier :P )
;so if Xscale = 1, the zoom = 1/Xscale# = 1
;but if Xscale is smaller than 1 it will make the camera zoom in more.
;It's hard for me to explain... play with it, you'll get it in time.
Global Xscale#=1*(.8/4)

;creating and setting up the shadow rendering camera.
shadowcam=CreateCamera()
CameraViewport shadowcam,0,0,ssize,ssize ;the viewport the shadows will be rendered through.
CameraClsColor shadowcam,255,255,255 ;Yup, white background for shadow textures.
CameraProjMode shadowcam,2 ;Orthographic view, sorry, I've only figured out very simple directional shadows.
CameraZoom shadowcam,.06/xscale# ;though the function "shadow_test" does this every time it's used, here it is for you to see anyway. It's not needed here.
CameraFogMode shadowcam,1 ;The fog is put on so it seems like everythings white... to make a caster visable to the camera, disable fogging to that object.
CameraFogRange shadowcam,1,1
CameraFogColor shadowcam,255,255,255

HideEntity shadowcam ;we don't want it onscreen now.

;just setting up the scene========
camera=CreateCamera() ;<-the game camera
PositionEntity camera,0,5,-15
scene=CreateSphere() ;<-later used as the receiver.
ScaleEntity scene,20,1,20
caster=CreateCone() ;<-the object that shall cast a shadow.
UpdateNormals caster
EntityShininess caster, .2
EntityColor caster,200,0,0
RotateEntity caster,40,90,60
PositionEntity caster, 0,2,0
ScaleEntity caster, 1,2,1.5
light=CreateLight(2) ;<-the light source
vis_light = CreateSphere(12,light) ;<-sphere used to make the light source visable.
EntityColor vis_light,0,200,0
EntityFX vis_light,1
PositionEntity light,-20,8,-1
;=================================

;placing the shadow texture onto the receiver...
;but If you make a shadow lib For a game,
;You'll probably want this in the actual function... not here.
EntityTexture scene,shadow_tex

;Main loop============================================
While quit=0
Cls
MoveEntity light,0,0,1:TurnEntity light,0,-5,0 ;A rotating light source. Much more intresting.
TurnEntity caster,0,0,.5
RenderWorld
UpdateWorld
If KeyHit(1) Then quit=1
shadow_test(shadowcam,camera,light,caster,scene) ;<- our function.

Text 500,10,"Xscale#: "+ Xscale#
Text 500,20,"zoom: "+ .06/Xscale#
Text 300,30,"hit ''<-'' & ''->'' to change the Xscale#."
Flip

If KeyHit(203) Then xscale#=Xscale#*.8
If KeyHit(205) Then xscale#=Xscale#*1.2
Wend
End
;=====================================================



;shadow_test function:
;I made this to help explain the how the real magic is done.
;used like so:
;shadow_test(s_camera,g_camera,s_light,s_caster,s_receiver)
;
;>s_camera
; The shadow camera used to render the shadows.
;
;>g_camera
; The in game camera used to render the game.
;
;>s_light
; The light source.
;
;>s_caster
; The object that shadows are casted from.
;
;>s_receiver
; Where the shadows land onto.
Function shadow_test(s_camera,g_camera,s_light,s_caster,s_receiver)

CameraZoom s_camera,.06/xscale# ;<-setting up the zoom for the shadow rendering camera.

cleartexture(shadow_tex) ;<- I added this because alot of graphics cards seem to render fog differant to mine.. Hopefully this fixes the blurring problem.
HideEntity g_camera ;The in game camera must be hidden,
ShowEntity s_camera ;and the shadow camera must become visable.

EntityFX s_caster,1+8 ;<- setting up the caster:
EntityColor s_caster,0,0,0 ;It needs to be black and unnefexted by fog and lights.

;The shadow rendering camera must be placed at
;the light source Then pointed at the caster.
PositionEntity s_camera,EntityX(s_light,1),EntityY(s_light,1),EntityZ(s_light,1)
PointEntity s_camera,s_caster

;Here we render the camera and convert it to a texture.
RenderWorld()
Color 255,255,255: Rect 0,0,ssize,ssize,0 ;<-this rectangle is used to cull anything that tries to poke outside of the textures boundry box.
CopyRect 0,0,ssize,ssize,0,0,BackBuffer(),TextureBuffer(shadow_tex)

;The surface and verticy loop.
;This loops through every surface of the receiver mesh,
;Then every surfaces vertecies.
;Our main focus should be the
;"Tformpoint" And "vertextexcoords" commands.
;These commands actually paint the texture onto the
;receiver correctly.
For s=1 To CountSurfaces(s_receiver)
surf=GetSurface(s_receiver,s)
For v=0 To CountVertices(surf)-1
TFormPoint VertexX(surf,v),VertexY(surf,v),VertexZ(surf,v),s_receiver,s_camera
VertexTexCoords surf,v,(TFormedX()/Xscale#)/32+0.5,1-((TFormedY()/Xscale#)/32+.5)
Next
Next


;Here we just switch the attributes of the caster back to normal.
;In an actual game engine you might have to make this more complex.
;I suggest keeping the old attributes in tempory memory then
;calling them back at about this point.
EntityFX s_caster,0
EntityColor s_caster,200,0,0

;here we hide the shadow camera and bring back the game camera,
;ready to go back to the main game loop like nothing ever happend.
ShowEntity g_camera
HideEntity s_camera

End Function


;This last little function holds no real importance, it just clears a texture and makes it white.
;I added this because when I first released this code I found alot of graphics cards don't make
;the fog as thick as mine (I'm guessing it's because my card it cheap), and the shadow texture
;Grabbed the old shadow texture off the ground and blurred with the new one...
;very annoying and unpretty.... Oh well... Hope this works much better.
Function cleartexture(tex)
SetBuffer TextureBuffer( tex )
Color 255,255,255
Rect 0,0,TextureWidth(tex)+1,TextureHeight(tex)+1
SetBuffer BackBuffer()
End Function


Comments :


Pepsi(Posted 1+ years ago)

 Yep I remmember it! Still have your previous shadow demos :) Nice work. Whenever I get to actaully make a game, one day, this is diffenitly what I want to use for the shadow system. Thanks!


jfk EO-11110(Posted 1+ years ago)

 Pretty good. I tried this:   ScaleEntity scene,20,10,20   TranslateEntity scene,0,-10,0The shadow is still aligned correctly on the non-flat ground!


puki(Posted 1+ years ago)

 It casts a shadow and a 'hidden' rectangle.  It's hidden as you are casting onto a white surface.I naturally changed the scene's colour to 1,1,1 and was greeted by the rectangle grinning at me as it played with the shadow.The rectangle has to go - I don't like it.


Kalisme(Posted 1+ years ago)

 Puki: It casts the shadow texture (which happens to be a rectangle) onto a surface mesh and lines up the texture to come from the light source. The background is white because I use a blend mode that removes white in shaKAL. The white rectangle around the rendered shadow camera is just a safe-guard I guess, just incase the shadow object sorta pokes out of view of the camera... without the white rectangle culling the edges it creates ugly black lines.Well, that's my explanation, but of course you can change anything you want, its public domain now =D


Naughty Alien(Posted 1+ years ago)

 Puki is right..its really producing ugly rectangle...actually on any given color different than 255,255,255 .. it means for real purpose its not possible to use this system..


Kalisme(Posted 1+ years ago)

 oh... now I think I understand.I just want to point out this is more reading material than a system that can be directly put into a game. I wouldn't recomend using it like that at all. I just wanted to give a brief explanation of the method I use so that I could help others program there own shadow system. I guess I should of pointed that out. Sorry guys.


Naughty Alien(Posted 1+ years ago)

 hey..Kalisme, this is nice piece of code buddy..I was just hoping that its ready for use immidiatelly, thats all ;)


DareDevil(Posted 1+ years ago)

 this a good method ;)I changed and optimized  your system and post the new solution ;)


DareDevil(Posted 1+ years ago)

 The  my version

Type Shadow
Field Obj
Field ShwTexSize
Field ShwTex
Field ShwInit

End Type


Graphics3D 1024,768,32,2
SetBuffer BackBuffer()
AmbientLight 0,0,0

Global Xscale#=1*(.8/2)

shadowcam=CreateCamera()
CameraProjMode shadowcam,2
CameraFogMode shadowcam,1
CameraFogRange shadowcam,1,1
CameraFogColor shadowcam,255,255,255
HideEntity shadowcam

Local camera=CreateCamera() ;<-the game camera
PositionEntity camera,0,5,-15

;scene=CreateSphere() ;<-later used as the receiver.
Local scene=CreateCube() ;<-later used as the receiver.
ScaleEntity scene,20,1,20
PositionEntity scene,0,-1,0
Local IDScene.Shadow = SW_AddObject(scene)


Local caster=CreateCone(32) ;<-the object that shall cast a shadow.
PositionEntity caster, 0,3,0
RotateEntity caster,40,90,60
ScaleEntity caster, 1,2,1.5
UpdateNormals caster
EntityColor caster,200,0,0
Local IDCaster.Shadow = SW_AddObject(caster)

Local caster1=CreateSphere(32) ;<-the object that shall cast a shadow.
PositionEntity caster1,0,1,0
EntityColor caster1,0,0,200
UpdateNormals caster1
Local IDCaster1.Shadow = SW_AddObject(caster1)


Local light=CreateLight(2) ;<-the light source
Local vis_light = CreateSphere(12,light) ;<-sphere used to make the light source visable.
EntityColor vis_light,0,200,0
EntityFX vis_light,1
PositionEntity light,-20,8,-1
;=================================
While quit=0
;===>
If KeyHit(1) Then quit=1
If KeyHit(203) Then Xscale#=Xscale#*.9
If KeyHit(205) Then Xscale#=Xscale#*1.1

;===>
SW_ResetShadow();
;===>
MoveEntity light,0,0,0.25:TurnEntity light,0,-1.25,0 ;A rotating light source. Much more intresting.
TurnEntity caster,0,0,.5
UpdateWorld

shadow_test1(shadowcam,camera,light,IDCaster ,IDScene) ;<- our function.
shadow_test1(shadowcam,camera,light,IDCaster1,IDScene) ;<- our function.
shadow_test1(shadowcam,camera,light,IDCaster ,IDCaster1) ;<- our function.

RenderWorld()
;===>
Text 500,10,"Xscale#: "+ Xscale#
Text 500,20,"zoom: "+ .06/Xscale#
Text 300,30,"hit ''<-'' & ''->'' to change the Xscale#."
Flip
;===>
Wend
End
;=====================================================


Function shadow_test1( s_camera, g_camera, s_light, caster.Shadow, s_receiver.Shadow)
;===>
;Stop
;===>
HideEntity g_camera ;The in game camera must be hidden,
ShowEntity s_camera ;and the shadow camera must become visable.
;===>
If s_receiverShwInit=True Then
CameraClsMode s_camera, False, True
Else
CameraClsMode s_camera, True, True
s_receiverShwInit = True
EndIf
;===>
Local TSize = s_receiverShwTexSize
;===>
CameraClsColor s_camera,255,255,255
CameraZoom s_camera,.06/Xscale# ;<-setting up the zoom for the shadow rendering camera.
CameraViewport s_camera,0,0,TSize,TSize ;the viewport the shadows will be rendered through.
CameraProjMode s_camera,2 ;Orthographic view, sorry, I've only figured out very simple directional shadows.
;===>
SW_HideObject()
;===>
Local s_caster=CopyEntity( casterObj )
EntityFX s_caster,1+8 ;<- setting up the caster:
EntityColor s_caster,0,0,0 ;It needs to be black and unnefexted by fog and lights.
ShowEntity s_caster
;===>
PositionEntity s_camera,EntityX(s_light,True),EntityY(s_light,True),EntityZ(s_light,True)
PointEntity s_camera,s_receiverObj
RenderWorld()
;===>
CopyRect 0,0,TSize,TSize,0,0,BackBuffer(),TextureBuffer(s_receiverShwTex)
;===>
Local CurObj = s_receiverObj
For s=1 To CountSurfaces(CurObj)
Local surf=GetSurface(CurObj,s)
For v=0 To CountVertices(surf)-1
TFormPoint VertexX(surf,v), VertexY(surf,v), VertexZ(surf,v), CurObj, s_camera
VertexTexCoords surf,v,(TFormedX()/Xscale#)/32+0.5,1-((TFormedY()/Xscale#)/32+.5)
Next
Next
;===>
SW_ShowObject()
;===>
ShowEntity g_camera
HideEntity s_camera
FreeEntity s_caster
;===>

End Function


Function SW_AddObject.Shadow( Obj)
Local SW_Size = 512
Local CurModel.Shadow = New Shadow
CurModelObj = Obj
CurModelShwInit = False
CurModelShwTex = CreateTexture( SW_Size, SW_Size, 16+32)
CurModelShwTexSize = SW_Size

EntityTexture CurModelObj,CurModelShwTex
;===>
SetBuffer(TextureBuffer(CurModelShwTex))
ClsColor 255,64,255
Cls
SetBuffer(BackBuffer())
;===>
Return CurModel
End Function

Function SW_ResetShadow()
Local CurModel.Shadow
For CurModel=Each Shadow
CurModelShwInit = False
Next
End Function

Function SW_HideObject()
Local CurModel.Shadow
For CurModel=Each Shadow
HideEntity CurModelObj
Next
End Function

Function SW_ShowObject()
Local CurModel.Shadow
For CurModel=Each Shadow
ShowEntity CurModelObj
Next
End Function




_33(Posted 1+ years ago)

 nice


blade007(Posted 1+ years ago)

 ughh im dizzy now


puki(Posted 1+ years ago)

 <div class="quote"> I changed and optimized your system and post the new solution ;)  </div>"DareDevils'" one is slower than a slug dragging its feet.Try again.I want one like the first one, but without the rectangle - I don't like the rectangle.


puki(Posted 1+ years ago)

 Also - and quite frankly, I should not have to point this out.Just what the jolly-badger is going on with the segments?Do I have to do everything myself?How the hell is increasing those optimizing anything?I really won't stand for this.EDIT:I'll edit the resolution and depth myself - might as well do everything.


puki(Posted 1+ years ago)

 Right, the results are as follows:Graphics3D 800,600,16,1Get rid of this:;Local caster1=CreateSphere()      ;<-the object that shall cast a shadow.;PositionEntity caster1,0,1,0;EntityColor caster1,0,0,200;UpdateNormals caster1;Local IDCaster1.Shadow = SW_AddObject(caster1)and its Satan offspring:;shadow_test1shadowcam,camera,light,IDCaster1,IDScene) ;<- our function.;shadow_test1shadowcam,camera,light,IDCaster ,IDCaster1) ;<- our function.Then, for the Love of Large, remove:;EntityColor vis_light,0,200,0


DareDevil(Posted 1+ years ago)

 I thought that rendering it easier it would have been useful to all


Naughty Alien(Posted 1+ years ago)

 .actually I have now same rectangle and some weird lines over plane surface and whole thing is slower..I dont know what is your optimization about...


DareDevil(Posted 1+ years ago)

 The my optimization is multi shadow for object and organization for use in application game, the slow speed is the generate for dettail texture shadow.bye


puki(Posted 1+ years ago)

 But your optimisation honked up the resolution and screen depth (potentially) and then honked up the segments, then added another chuffing caster.You also made the same shocking error to add a green - I repeat, green - vis light.The first thing I did with the original one was sort that shocker out.


Gillissie(Posted 1+ years ago)

 Puki, just what are you talking about? What do you mean "segments"? And who cares if the entity for the light source is green?


puki(Posted 1+ years ago)

 He increased the segments on the primitives.How many people are seriously going to leave in a green caster when the light is not green?  Might just be me, but I always make the caster and the light the same colour.


Yue(Posted 1+ years ago)

 is spectacular, especially to learn things ... thanks man. [/i]