SMS Library ( projectional shadow system )
Blitz3D Forums/Blitz3D Userlibs/SMS Library ( projectional shadow system )
| ||
Here is a "simple" library I made, that may be usefull for simple 'flat' games . I notify Flat, cause it's a projectional system that set the height constant for the projected shadows . ( we could go farvest in the development, but it's not my way. ) An other limit is that shadows do not support alpha, as it simply flat coordinates from original mesh, and tris are superimposed, so the ground should have a uniform texture or color. And the last limit for the moment, is that it does not support animation ( we can't get the vertexCoord for animated surfaces ... ) advice : it's better to use simplified LPM of the mesh you want to project shadows. ;*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* ; SMS LIB ; Par Bobysait => Bobysait@... ; Pour tous renseignements consultez moi sur http://www.BlitzFr.com ; ; ; Faites vous plaisir, et utilisez le à volonté ! ; ;*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* ;====================================================================================================== ;====================================================================================================== ;|| || ----------- ;|| || -Fonctions- ;|| || ----------- ;====================================================================================================== ;====================================================================================================== ;========================================================= ; =========== Constantes SMS =========== Const C_SMS_MaxMesh%=1000 Const C_SMS_MaxSurf%=20 ;============================================== ;========================================================= ; ========== Types SMS ========== Type ENV_SMS_Layer Field SMS_Mesh% Field SMS_Surf% Field NbMesh% Field HandleMesh%[C_SMS_MaxMesh] Field Statik%[C_SMS_MaxMesh] Field Anim%[C_SMS_MaxMesh] Field SMS_Rate% ; Contrôle du rafraichissement. Field MajTime% Field st% Field lt% Field dt% Field GroundR% Field GroundG% Field GroundB% Field Vrt_X#[3] Field Vrt_Y#[3] Field Vrt_Z#[3] Field Vrt_dX#[3] Field Vrt_dY#[3] Field Vrt_dZ#[3] Field Actif% ; variable pour l'affichage des ombres simples ; ( pour ne pas refaire le maillage à chaque boucle) ; comme il s'agit d'ombre statique, inutile de les recréer sans cesse ! End Type Type ENV_SMS_Mesh Field Mesh% Field NbSurf% Field IdSurf%[C_SMS_MaxSurf] Field HandleSurf%[C_SMS_MaxSurf] Field NbTris% Field ColR,ColG,ColB End Type Type ENV_SMS_Surf Field Surf% Field CountTris% Field Vrt1%[65536] Field Vrt2%[65536] Field Vrt3%[65536] End Type Type ENV_SMS_BoxMesh Field Mesh Field Pointx#[4] Field Pointy#[4] Field Pointz#[4] End Type ;============================================== ;========================================================= ; =========== Initialisation SMS ============ ;========================================================= Function SMS_Init(World%) f.ENV_SMS_Layer=New ENV_SMS_Layer If world = 0 f\SMS_Mesh=CreateMesh() Else f\SMS_Mesh=CreateMesh(World) EndIf f\SMS_surf=CreateSurface(f\SMS_Mesh) EntityFX f\SMS_Mesh,1+2+8 f\st%=MilliSecs() f\SMS_Rate%=16 ; 60 Hetz ( 1000 / 60 ) => 16 milliSecondes ImgX=32 tex=CreateTexture(ImgX,1,3) currentbuffer=GraphicsBuffer() SetBuffer TextureBuffer(tex) For i = 0 To ImgX Color 255-i*255/ImgX,255-i*255/ImgX,255-i*255/ImgX Rect i,0,1,1 Next SetBuffer currentbuffer EntityTexture f\SMS_Mesh,tex End Function ;========================================================= ; =========== Ajout d'un mesh dans le SMS ============ ;========================================================= Function SMS_Add_Emetteur(Mesh,World%=0,ColR%=128,ColG%=128,ColB%=128) ; avant tout on verifie que le mesh existe, et qu'il a de quoi projeté des ombres. ; <!> ============== mesh inexistant... If mesh=0 Return False NbSurf=CountSurfaces(mesh) ; ========== <!> ; <!> ============== pas de surface ... If nbsurf=0 Return False For ns= 1 To NbSurf srf=GetSurface(mesh,ns) CountTris=CountTriangles (srf) CntTri=CntTri+CountTris If CountTris>0 CountSurfForMesh=CountSurfForMesh+1 Next ; ========== <!> ; <!> ============== surfaces vides ... If CntTri=0 Return False ; ========== <!> ; le mesh est correct, on l'enregistre ! f.ENV_SMS_Layer=Last ENV_SMS_Layer ; <!> ============== SMS non initialisé ? alors faisons le ! If f=Null SMS_Init(World) f.ENV_SMS_Layer=Last ENV_SMS_Layer EndIf ; ========== <!> ; c'est parti ! f\NbMesh=f\NbMesh+1 m.ENV_SMS_Mesh=New ENV_SMS_Mesh m\ColR%=ColR m\ColG%=ColG m\ColB%=ColB f\HandleMesh[f\NbMesh]=Handle(m) m\Mesh=Mesh m\NBSurf=CountSurfForMesh For ns= 1 To nbsurf srf=GetSurface(mesh,ns) CountTris=CountTriangles(srf) If countTris<>0 CurIdSurf=CurIdSurf+1 s.ENV_SMS_Surf=New ENV_SMS_Surf m\HandleSurf[CurIdSurf]=Handle(s) s\Surf=srf s\CountTris=CountTris For Nt= 0 To CountTris-1 s\Vrt1[Nt]=TriangleVertex(srf,Nt,0) s\Vrt2[Nt]=TriangleVertex(srf,Nt,1) s\Vrt3[Nt]=TriangleVertex(srf,Nt,2) Next EndIf Next End Function Function SMS_Free_Emetteur(Mesh) For m.ENV_SMS_Mesh=Each ENV_SMS_Mesh If m\Mesh = mesh Delete m Exit EndIf Next End Function ;========================================================= ; =========== Ajout d'un mesh Recepteur ============ ; à finir !!! ;========================================================= Function SMS_Define_GroundColor(R%,G%,B%) f.ENV_SMS_Layer=Last ENV_SMS_Layer F\GroundR%=R F\GroundG%=G F\GroundB%=B End Function Function SMS_RateTime%(f.ENV_SMS_Layer) Local l_mt=MilliSecs() l_dmt=f\lt+f\st f\dt%=l_mt-l_dmt If f\dt<2 f\dt=1 f\MajTime=f\MajTime+f\Dt If f\MajTime>f\SMS_Rate f\MajTime=0 f\st=MilliSecs() f\lt=0 Return True EndIf f\lt#=f\lt+f\dt Return False End Function Function SMS_SetMajRate(Rate%) f.ENV_SMS_Layer = Last ENV_SMS_Layer f\SMS_Rate%=Rate End Function ;========================================================= ; =========== Mise à Jour du SMS ============ ;========================================================= Function SMS_Update(Light%,Camera,Methode,Range%=1000) f.ENV_SMS_Layer = Last ENV_SMS_Layer If SMS_RateTime(f)=True Select methode Case 0 SMS_NoUpdate():f\Actif=0 Case 1 If f\Actif=0 SMS_Simple_Shader(Light%,Camera):f\Actif=1 Case 2 SMS_Projection_Shader(Light%,Camera,Range):f\Actif=0 End Select EndIf End Function Function SMS_Simple_Shader(Light%,Camera) f.ENV_SMS_Layer = Last ENV_SMS_Layer l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) If l=Null Return False If f\NbMesh>0 ClearSurface f\SMS_surf,1,1 For nm = 1 To f\NbMesh m.ENV_SMS_Mesh=Object.ENV_SMS_Mesh(f\HandleMesh[nm]) EntityColor f\SMS_Mesh,f\GroundR-m\ColR,f\GroundG-m\ColG,f\GroundB-m\ColB EntityFX f\SMS_Mesh,1+2 If m<>Null mx#=EntityX(m\mesh,1) my#=EntityY(m\mesh,1) mz#=EntityZ(m\mesh,1) TFormPoint mx,my,mz,0,camera If TFormedZ()>0 For ns = 1 To m\NbSurf s.ENV_SMS_Surf=Object.ENV_SMS_Surf(m\handleSurf[ns]) surf=s\Surf NbTris=s\CountTris For Nt=0 To NbTris-1 enableTri=True For nv=0 To 2 Vrt%= TriangleVertex(surf,Nt,nv) y# = VertexY(surf,Vrt) x# = VertexX(surf,Vrt) z# = VertexZ(surf,Vrt) TFormPoint x#,y#,z#,m\mesh,0 y# = TFormedY()/Vy# If y#>=0 x# = TFormedX() z# = TFormedZ() Vrt = AddVertex (f\SMS_surf,x#,0.01,z#) VertexNormal f\SMS_surf,Vrt,0,1,0 Else enableTri=False EndIf Next If enableTri=True AddTriangle f\SMS_surf,Vrt-2,Vrt-1,Vrt Next Next EndIf EndIf Next EndIf End Function Function SMS_Projection_Shader(Light%,Camera,Range%=1000) f.ENV_SMS_Layer = Last ENV_SMS_Layer l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) If l=Null Return False L_Lx# = EntityX(l\light,1) L_Ly# = EntityY(l\light,1) L_Lz# = EntityZ(l\light,1) l_FColR = f\GroundR l_FColG = f\GroundG l_FColB = f\GroundB L_Range#= l\Range EntityFX f\SMS_Mesh,1+2 If f\NbMesh>0 ClearSurface f\SMS_surf,1,1 For nm = 1 To f\NbMesh m.ENV_SMS_Mesh=Object.ENV_SMS_Mesh(f\HandleMesh[nm]) If m<>Null DistMesh = EntityDistance(m\mesh,camera) If Abs DistMesh>Range Else mx# = EntityX(m\mesh,1) my# = EntityY(m\mesh,1) mz# = EntityZ(m\mesh,1) l_ty# = MeshHeight(m\mesh)*2 l_NColR = m\ColR l_NColG = m\ColG l_NColB = m\ColB TFormPoint mx,my,mz,0,camera If TFormedZ()>0 For ns = 1 To m\NbSurf s.ENV_SMS_Surf=Object.ENV_SMS_Surf(m\handleSurf[ns]) surf=s\Surf NbTris=s\CountTris For Nt=0 To NbTris-1 enableTri=True For nv=0 To 2 Select nv Case 0 Vrt=s\Vrt1[Nt] Case 1 Vrt=s\Vrt2[Nt] Case 2 Vrt=s\Vrt3[Nt] End Select dy# = VertexY(surf,Vrt) dx# = VertexX(surf,Vrt) dz# = VertexZ(surf,Vrt) TFormPoint dx#,dy#,dz#,m\mesh,0 ddy# = TFormedY() Vy# = Abs(l_ly-ddy) dy# = ddy/Vy If Dy#>=0 dx# = TFormedX() dz# = TFormedZ() Vx# = l_lx-dx Vz# = l_lz-dz x# = dx#-Vx*dy z# = dz#-Vz*dy ddY# = (ddy)/l_ty Coef# = SMS_LightCoef#(x,z,l_lx,l_lz,l_Range) Vrt = AddVertex (f\SMS_surf,x,ddy/50,z) ColR=SMS_SmoothColor(l_NColR,l_FColR,ddy,coef) ColG=SMS_SmoothColor(l_NColG,l_FColG,ddy,coef) ColB=SMS_SmoothColor(l_NColB,l_FColB,ddy,coef) VertexColor f\SMS_surf,Vrt,ColR,ColG,ColB Else enableTri=False EndIf Next If enableTri=True AddTriangle f\SMS_surf,Vrt-2,Vrt-1,Vrt Next Next EndIf EndIf EndIf Next EndIf End Function Function SMS_NoUpdate() f.ENV_SMS_Layer = Last ENV_SMS_Layer If f\NbMesh>0 ClearSurface f\SMS_surf,1,1 EndIf End Function Function SMS_Distance#(dd#,Range#) If dd>range Return 1 If dd<0 Return 0 coef#=Float(dd)/Float(Range) Return coef# End Function Global G_Coef# Function SMS_LightCoef#(X1#,Y1#,X2#,Y2#,Range#) Local ddx#=(x1-x2)*(x1-x2) Local ddz#=(z1-z2)*(z1-z2) Local dd#=ddx+ddz dd=Sqr(dd) Local Coef#=SMS_Distance#(dd#,Range);*Range) G_Coef#=Coef Return Coef# End Function Function SMS_SmoothColor%(NCol,FCol,CoefN#,CoefF#) Col%=NCol*(CoefN)*(1-coefF)+FCol*(coefF) Return Col End Function Function SMS_BoxMesh() End Function Type ENV_SMS_Light Field Light%,Mesh% Field X#,Y#,Z# Field RX%,RY%,RZ% Field ColR%,ColG%,ColB% Field Range# End Type ; Light Create ====================================== Function SMS_Createlight(Typ%=1,Parent%=0,ColR%=255,ColG%=255,ColB%=255,Range#=100) l.ENV_SMS_Light=New ENV_SMS_Light If parent<>0 l\Light=CreateLight(Typ,Parent) Else l\Light=CreateLight(Typ) EndIf l\Mesh=CreateSphere(4,l\light) HideEntity l\mesh NameEntity l\light,Handle(l) l\ColR=ColR l\ColG=ColG l\ColB=ColB l\Range=range LightColor l\light,l\ColR,l\ColG,l\ColB EntityColor l\mesh,l\ColR,l\ColG,l\ColB EntityFX l\mesh,9 LightRange l\Light,l\Range Return l\Light End Function ; Hide/Show Repere ===================================== Function SMS_MeshVisible(Light,Alpha#) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) If alpha#=0 HideEntity l\mesh Else ShowEntity l\mesh EntityAlpha l\mesh,alpha EndIf End Function Function SMS_SetParent(Light,Parent) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) EntityParent l\light,Parent End Function ; Light positions ====================================== ; Set Function SMS_SetLightPosition(Light,X#,Y#,Z#,Globale%=0) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) l\x#=x l\y#=y l\z#=z PositionEntity l\light,x,y,z,Globale End Function Function SMS_SetLightTranslate(Light,vX#,vY#,vZ#,Globale%=0) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) TranslateEntity l\light,vx,vy,vz,globale l\X#=EntityX(l\light,1) l\Y#=EntityY(l\light,1) l\Z#=EntityZ(l\light,1) End Function Function SMS_SetLightMove(Light,vX#,vY#,vZ#) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) MoveEntity l\light,vx,vy,vz l\X#=EntityX(l\light,1) l\Y#=EntityY(l\light,1) l\Z#=EntityZ(l\light,1) End Function ; get Function SMS_GetLightPosX#(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\x# End Function Function SMS_GetLightPosY#(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\y# End Function Function SMS_GetLightPosZ#(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\z# End Function ; Light Rotations ====================================== ; Set Function SMS_SetLightRotate(Light,RX%,RY%,RZ%,Globale%=0) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) l\Rx%=rx l\Ry%=ry l\Rz%=rz RotateEntity l\light,Rx,Ry,Rz,Globale End Function Function SMS_SetLightTurn(Light,vRX%,vRY%,vRZ%,Globale%=0) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) TurnEntity l\light,vRx,vRy,vRz,Globale l\Rx%=EntityPitch(l\light,1) l\Ry%=EntityYaw (l\light,1) l\Rz%=EntityRoll (l\light,1) End Function ; get Function SMS_GetLightRotX#(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\rx# End Function Function SMS_GetLightRotY#(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\ry# End Function Function SMS_GetLightRotZ#(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\rz# End Function ; Light Color ====================================== ; Set Function SMS_SetLightColor(Light,ColR%,ColG%,ColB%) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) l\ColR%=Colr l\ColG%=Colg l\ColB%=Colb LightColor l\light,colr,colg,colb EntityColor l\mesh,colr,colg,colb End Function Function SMS_SetLightColorRed(Light,ColR%) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) l\ColR%=Colr LightColor l\light,l\colr,l\colg,l\colb EntityColor l\mesh,l\colr,l\colg,l\colb End Function Function SMS_SetLightColorGreen(Light,ColG%) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) l\ColG%=Colg LightColor l\light,l\colr,l\colg,l\colb EntityColor l\mesh,l\colr,l\colg,l\colb End Function Function SMS_SetLightColorBlue(Light,ColB%) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) l\ColB%=Colb LightColor l\light,l\colr,l\colg,l\colb EntityColor l\mesh,l\colr,l\colg,l\colb End Function ; Get Function SMS_GetColorR%(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\ColR End Function Function SMS_GetColorG%(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\ColG End Function Function SMS_GetColorB%(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\ColB End Function ; Light Range ====================================== ; Set Function SMS_SetLightRange(Light,Range#) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) l\Range#=Range LightRange l\Light,l\Range End Function ; get Function SMS_GetRange#(light) l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) Return l\Range# End Function and here is a demo Graphics3D 1024,768,0,2 SetBuffer BackBuffer() AmbientLight 125,125,125 SeedRnd MilliSecs() Include "SMS_Lib_V1.bb" world = CreatePivot() pivcam1 = CreatePivot (world) pivcam2 = CreatePivot (pivcam1) MoveEntity pivcam2,0,2,0 camera = CreateCamera (pivcam2) CameraClsColor camera,120,150,255 MoveEntity camera,0,2,-10 PointEntity camera,pivcam2 CameraRange camera,.1,200 ; initialise variables for the hadow system ( SMS Library ) SMS_Init(World) LightR% = 255 LightG% = 120 LightB% = 20 groundR% = 50 groundG% = 120 groundB% = 20 Shade_R% = 20 Shade_G% = 50 Shade_B% = 0 SMS_Refreshrate%= 20 ; add the light for the shadows ( remember it adds a real light ! ) light = SMS_Createlight (1,0,LightR,LightG,LightB,2) SMS_SetLightPosition (light,0,30,0) SMS_SetMajRate (Refreshrate) SMS_Define_GroundColor (groundR,groundG,groundB) Repere = CreateSphere (4,light) EntityColor repere,LightR,LightG,LightB EntityFX repere,9 ; Cubes...=========================== !> Type cube Field mesh End Type For i=0 To 20 cube.cube = New cube cube\mesh = CreateCube() ScaleEntity cube\mesh,Rnd(.5,2),Rnd(.5,2),Rnd(.5,2) TurnEntity cube\mesh,Rnd(0,360),Rnd(0,360),Rnd(0,360) PositionEntity cube\mesh,Rnd(-50,50),Rnd(1.5,5),Rnd(-50,50) EntityShininess cube\mesh,1 SMS_Add_Emetteur (cube\mesh,World,Shade_R,Shade_G,Shade_B) Next ;====================================/!> ; a simple plane ==================== !> p = CreatePlane () MoveEntity p,0,0,0 EntityColor p,groundR,groundG,groundB EntityFX p,9 ;====================================/!> fnt=LoadFont("Comic Sans Ms",18,1) SetFont fnt st=MilliSecs() lt# = 0 zoom# = 1 methode% = 2 Repeat ; time based .... <================= !> mt%=MilliSecs() realDt=mt-(st+lt) If realDt>60 dt#=60.00 ElseIf realDt<2 dt#=2.00 Else dt#=Float(realDt) EndIf lt=lt+dt ;====================================/!> ; Set the light ===================== !> poslightX#=20*Cos(lt/20) poslighty#=10+5*Cos(lt/50) poslightZ#=10*Sin(lt/20) SMS_SetLightPosition(light,poslightX,poslightY,poslightZ) PointEntity light,world ;====================================/!> ; Camera ============================ !> TurnEntity pivcam1 ,0,-MouseXSpeed(),0 TurnEntity PivCam2 ,MouseYSpeed(),0,0 zoom# =MouseZSpeed() MoveEntity camera ,0,0,zoom ;====================================/!> l.ENV_SMS_Light=Object.ENV_SMS_Light(EntityName(light)) If MouseHit(2) methode=(methode+1) Mod(4) ColR# = (ColR+dt#/120) Mod(255) ColG# = (ColG+dt#/150) Mod(255) ColB# = (ColB+dt#/180) Mod(255) SMS_SetLightColor (Light,ColR,ColG,ColB) SMS_Update (light,camera,methode,100) ; maj ombres RenderWorld If lt>ltfps:ltfps=lt+1000:fpsC=fpscur:fpscur=0:ddt=dt:Else fpscur=fpscur+1:EndIf Color 180,200,150 Rect 2,10,354,64,1 Color 50,50,50 Rect 5,13,348,58,1 Color 0,255,0 Text 10,20,"Use MouseHit 2 to toggle Shadow rendering" Text 10,35," fps :"+fpsC Text 10,50," tris :"+TrisRendered() Color 180,120,50 Rect 500,12,200,30,1 Color 50,50,55 Rect 503,15,194,24,1 Color 0,120,250 Select Methode Case 0 TextMethode$=" Off " Case 1 TextMethode$=" One Time render Case 2 TextMethode$=" RealTime" Case 3 TextMethode$=" no Update" End Select Text 510,20,"Methode :"+TextMethode ; replace the mouse on the screen ! If MouseX()>GraphicsWidth()-20 MoveMouse 30,MouseY() If MouseX()<20 MoveMouse GraphicsWidth()-30,MouseY() If MouseY()>GraphicsHeight()-20 MoveMouse MouseX(),30 If MouseY()<20 MoveMouse MouseX(),GraphicsHeight()-30 Flip 0 Until KeyDown(1) End Feel free to post your comments ;) |
| ||
I just realised it's maybe not in the good section of the forum... As anyone could replace it where it should find its right place ;) |
| ||
i put the code here => http://www.blitzbasic.com/codearcs/codearcs.php?code=1791 If anyone could delete this topic :) |
| ||
An other limit is that shadows do not support alpha, as it simply flat coordinates from original mesh, and tris are superimposed, so the ground should have a uniform texture or color. I haven't really looked at your code, but from the description I believe there is a way round this. In similar circumstances, what I have done is to make the ground semi-transparent and position the opaque shadow just below it. If done correctly, this gives the exact appearance of an alpha-blended shadow. |