UnderwareDESIGN

PlayBASIC => Show Case => Topic started by: kevin on January 07, 2006, 07:12:15 PM

Title: Sprite (alpha) Particles
Post by: kevin on January 07, 2006, 07:12:15 PM
This  example uses sprites Alpha+ Circle Alpha Addition effects.    


 


 Updated Jan 2024, corrected a few small differences for modern PlayBASIC
[pbcode]

 OpenSCreen 640,480,32,1


; CReate an FX copy of the display
  FXScreen=NewFXImage(GetScreenWidth(),GetScreenHeight())

; Projection constants
  constant   ProjectionX#=400
  constant ProjectionY#=400

; View Z depth
  Zdepth#=1000



; Size of Alpha Texture
  Size=32

  MaxImages=64
  Dim ParticleIMage(MaxImages)

  Col=$ffffff
  For lp=0 to MaxImages
 ParticleIMage(lp)=Newimage(Size,Size)  
 rendertoimage ParticleIMage(lp)
 Preparefximage ParticleIMage(lp)
 RenderPhongImage  ParticleIMage(lp),Size/2,Size/2,col,255,260/(size/2)
 Col=rndrgb()
  next
  rendertoscreen
  ParticleSize=GetImageWidth(ParticleIMage(0))
 
 
  NumberOfParticles=400

  acset =1
  Constant Particle_Xpos=ac(1)  
  Constant Particle_Ypos=ac(1)  
  Constant Particle_Zpos=ac(1)  
  Constant Particle_Size=ac(1)  
  Constant Particle_Sprite=ac(1)  
  Constant Particle_StructSize=ac(1)  
 
  Dim VertexList#(NumberOfParticles,Particle_StructSize)
  Dim RotatedVertexList#(NumberOfParticles,Particle_StructSize)

  Size=300
  For lp=0 to NumberOfParticles
 VertexList#(lp,Particle_Xpos)=rndrange(-size,size)    
 VertexList#(lp,Particle_Ypos)=rndrange(-size,size)    
 VertexList#(lp,Particle_Zpos)=rndrange(-size,size)    
 VertexList#(lp,Particle_Size)=rndrange(20,50)

 ThisSprite=NewSprite(0,0,ParticleIMage(rnd(MaxImages)))
 SpriteDRawmode ThisSprite,2+16
 VertexList#(lp,Particle_Sprite)=ThisSprite
  next


  RenderMode=1


  rendertoimage fxscreen  
  Createcamera 1
  cameracls 1,off
 
  RenderToSCreen

 Do

 rendertoimage fxscreen


 RotateVerts(VertexList#(),RotatedVertexList#(),NumberOFParticles,Tilt#,turn#,roll#,Zdepth#)


 if RenderMode=0
    CaptureToscene
    ClsScene

   inkmode 1+64

   For lp=0 to NumberOFParticles
      z#=RotatedVertexList#(lp,Particle_Zpos)
     if z#>1
        capturedepth z#
        Size#=(VertexList#(lp,Particle_Size)*ProjectionX#)/z#
        Circlec RotatedVertexList#(lp,Particle_Xpos),RotatedVertexList#(lp,Particle_Ypos),Size#,1,$80808
      endif
   next
    DrawCamera 1

 endif
 

 if RenderMode=1


    For lp=0 to NumberOFParticles
   z#=RotatedVertexList#(lp,Particle_Zpos)
   if z#>1
      ThisSprite=VertexList#(lp,Particle_Sprite)
      SizeX#=VertexList#(lp,Particle_Size)
      POsitionSpritexyz  ThisSprite,RotatedVertexList#(lp,Particle_Xpos),RotatedVertexList#(lp,Particle_Ypos),z#
      ScaleSprite ThisSprite,(SizeX#*ProjectionX#)/z#/ParticleSize  
   else
     POsitionSpritex  ThisSprite,-100
     
   endif
    next
    drawAllsprites

 endif


 
 inkmode 1
 rendertoscreen

 if RenderMode=1 then   BlitImageClr(FXScreen,0,0,rgb(20,30,40))
 if RenderMode=0 then BlitImageALphaSub(FXScreen,X#,y#,Rgb(23,34,22))

;   BlitImageALphaAdd(FXScreen,X#,y#,Rgb(11,11,11))
;   BlitImageALphaSub(FXScreen,X#,y#,Rgb(13,14,12))

;  drawimage FXScreen,0,0,0
 

 Rem animate the tilt, turn And roll values
  tilt# = tilt#+1.31
  turn# = turn#+0.42  
  roll# = roll#+0.53



  ShowSubDivides   = enterkey()
   
 if upkey() and zdepth#>400 then Zdepth#=Zdepth#-20
 if downkey() then Zdepth#=Zdepth#+20

 
 If SpaceKey() and Released=false
    RenderMode=1-rendermode  
    released=true
 endif

 if Scancode()=0
    released=false
 endif

 if RenderMode=0 then ModeName$="Alpha Circles"  
 if RenderMode=1 then ModeName$="Alpha Sprites"  

 setcursor 0,0  
 print "Effect Mode: "+Modename$
 print fps()
 
  Sync
loop





Function RotateVerts(Pts#(),RotatedPts#(),NumbOfVerts,Tilt#,turn#,roll#,ObjectDistance#)


 cx=getscreenwidth()/2
 cy=getscreenheight()/2
 

  Rem prepare the rotation matrix
  A#=Cos(tilt#) : B#=Sin(tilt#)
  C#=Cos(turn#) : D#=Sin(turn#)
  E#=Cos(roll#) : F#=Sin(roll#)
  AD#=A#*D#
  BD#=B#*D#

; Calc Rotation Matrix  
   m11#=C#*E#
  m21#=-1*C#*F#
  m31#=D#
  m12#=BD#*E#+A#*F#
  m22#=-1*BD#*F#+A#*E#
  m32#=-1*B#*C#
  m13#=-1*AD#*E#+B#*F#
  m23#=AD#*F#+B#*E#
  m33#=A#*C#

  Rem rotate all the points using the matrix
  For p=0 To NumbOfVerts

    pointx#=pts#(p,1)
    pointy#=pts#(p,2)
    pointz#=pts#(p,3)

     rotatedPts#(p,1) = (m11# * pointx#) + (m12# * pointy#) + (m13# * pointz#)
     rotatedPts#(p,2) = (m21# * pointx#) + (m22# * pointy#) + (m23# * pointz#)
     rotatedPts#(p,3) = (m31# * pointx#) + (m32# * pointy#) + (m33# * pointz#)
     
     Rem Now Do the perspective calculation
     z# = rotatedPts#(p,3) + ObjectDistance#
       rotatedPts#(p,1) = cx+ ((rotatedPts#(p,1)*ProjectionX# )/ z#)
     rotatedPts#(p,2) = cy+ ((rotatedpts#(p,2)*ProjectionY# )/ z#)
    RotatedPts#(p,3)=z#
  Next p

 
Endfunction
 


Function SizeVerts(Pts#(),x_scale#,y_scale#,z_scale#)
  Rem rotate all the points using the matrix
  For p=1 To getArrayelements(pts#(),1)
    pts#(p,1)=pts#(p,1)* x_scale#
    pts#(p,2)=pts#(p,2)* Y_scale#
    pts#(p,3)=pts#(p,3)* Z_scale#
  Next p
Endfunction
 






Function BlitImageClr(ThisImage,X#,y#,ClrRGB)
 BlitMode=1
 blitimage ThisIMage,x#,y#,transparentflag,Blitmode,ClrRGB,0,0  
EndFunction

Function BlitImageALphaAdd(ThisImage,X#,y#,AddRGB)
  select GetSCreenDepth()
 case 32
    BlitMode=64
    blitimage ThisImage,x#,y#,transparentflag,Blitmode,AddRGB,0,0  
 default
 ; Create an Equivalent Alpha effect using a box alpha masked over the src image
    OldSurface=getsurface()
    w=getimagewidth(Thisimage)
    h=getimageHeight(Thisimage)
    oldinkmode=getinkmode()
    rendertoimage thisimage
    inkmode 1+64
    boxc 0,0,w,h,1,AddRgb
    inkmode oldinkmode  
    rendertoimage OldSurface
    drawimage Thisimage,X#,y#,0
  endselect
 
EndFunction


Function BlitImageALphaSub(ThisImage,X#,y#,SubRGB)
  select GetSCreenDepth()
  ; BlitImage only supports 32bit in PBV1.089 and bellow
 case 32
    BlitMode=128
    blitimage ThisImage,x#,y#,transparentflag,Blitmode,SubRGB,0,0  
 default
 ; Create an Equivalent Alpha effect using a box alpha masked over the src image
    OldSurface=getsurface()
    w=getimagewidth(Thisimage)
    h=getimageHeight(Thisimage)
    oldinkmode=getinkmode()
    rendertoimage thisimage
    inkmode 1+128
    boxc 0,0,w,h,1,SubRgb
    inkmode oldinkmode  
    rendertoimage OldSurface
    drawimage Thisimage,X#,y#,0
  endselect
 

EndFunction



[/pbcode]


Original Code:

[pbcode]

; PROJECT : AlphaParticles
; AUTHOR  : Kevin Picone (c) Underware Design 2005
; CREATED : 13/08/2004
; EDITED  : 8/01/2006


 OpenSCreen 640,480,16,2


; CReate an FX copy of the display
   FXScreen=NewImage(GetScreenWidth(),GetScreenHeight())
   PrepareFXimage FXscreen

; Projection constants
   constant   ProjectionX#=400
   constant ProjectionY#=400

; View Z depth
   Zdepth#=1000



; Size of Alpha Texture
   Size=32

   MaxImages=64
   Dim ParticleIMage(MaxImages)

   Col=$ffffff
   For lp=0 to MaxImages
 ParticleIMage(lp)=Newimage(Size,Size)  
 rendertoimage ParticleIMage(lp)
 Preparefximage ParticleIMage(lp)
 RenderPhongImage  ParticleIMage(lp),Size/2,Size/2,col,255,260/(size/2)
 Col=rndrgb()
   next
   rendertoscreen
   ParticleSize=GetImageWidth(ParticleIMage(0))
   
   
   NumberOfParticles=400

   acset =1
   Constant Particle_Xpos=ac(1)  
   Constant Particle_Ypos=ac(1)  
   Constant Particle_Zpos=ac(1)  
   Constant Particle_Size=ac(1)  
   Constant Particle_Sprite=ac(1)  
   Constant Particle_StructSize=ac(1)  
 
   Dim VertexList#(NumberOfParticles,Particle_StructSize)
   Dim RotatedVertexList#(NumberOfParticles,Particle_StructSize)

   Size=300
   For lp=0 to NumberOfParticles
 VertexList#(lp,Particle_Xpos)=rndrange(-size,size)    
 VertexList#(lp,Particle_Ypos)=rndrange(-size,size)    
 VertexList#(lp,Particle_Zpos)=rndrange(-size,size)    
 VertexList#(lp,Particle_Size)=rndrange(20,50)

 ThisSprite=NewSprite(0,0,ParticleIMage(rnd(MaxImages)))
 SpriteDRawmode ThisSprite,2+16
 VertexList#(lp,Particle_Sprite)=ThisSprite
   next


   RenderMode=1


   rendertoimage fxscreen   
   Createcamera 1
   cameracls 1,off
   
   RenderToSCreen

 Do

 rendertoimage fxscreen


 RotateVerts(VertexList#(),RotatedVertexList#(),NumberOFParticles,Tilt#,turn#,roll#,Zdepth#)


 if RenderMode=0
    CaptureToscene
    ClsScene

   inkmode 1+64

   For lp=0 to NumberOFParticles
      z#=RotatedVertexList#(lp,Particle_Zpos)
     if z#>1
        capturedepth z#
        Size#=(VertexList#(lp,Particle_Size)*ProjectionX#)/z#
        Circlec RotatedVertexList#(lp,Particle_Xpos),RotatedVertexList#(lp,Particle_Ypos),Size#,1,$80808
      endif
   next
    DrawCamera 1

 endif
 

 if RenderMode=1


    For lp=0 to NumberOFParticles
   z#=RotatedVertexList#(lp,Particle_Zpos)
   if z#>1
      ThisSprite=VertexList#(lp,Particle_Sprite)
      SizeX#=VertexList#(lp,Particle_Size)
      POsitionSpritexyz  ThisSprite,RotatedVertexList#(lp,Particle_Xpos),RotatedVertexList#(lp,Particle_Ypos),z#
      ScaleSprite ThisSprite,(SizeX#*ProjectionX#)/z#/ParticleSize  
   else
     POsitionSpritex  ThisSprite,-100
     
   endif
    next
    drawAllsprites

 endif


 
 inkmode 1
 rendertoscreen

 if RenderMode=1 then   BlitImageClr(FXScreen,0,0,rgb(20,30,40))
 if RenderMode=0 then BlitImageALphaSub(FXScreen,X#,y#,Rgb(23,34,22))

;   BlitImageALphaAdd(FXScreen,X#,y#,Rgb(11,11,11))
;   BlitImageALphaSub(FXScreen,X#,y#,Rgb(13,14,12))

;  drawimage FXScreen,0,0,0
 

 Rem animate the tilt, turn And roll values
  tilt# = tilt#+1.31
  turn# = turn#+0.42   
  roll# = roll#+0.53



  ShowSubDivides   = enterkey()
    
 if upkey() and zdepth#>400 then Zdepth#=Zdepth#-20
 if downkey() then Zdepth#=Zdepth#+20

   
 If SpaceKey() and Released=false
    RenderMode=1-rendermode  
    released=true
 endif

 if Scancode()=0
    released=false
 endif

 if RenderMode=0 then ModeName$="Alpha Circles"  
 if RenderMode=1 then ModeName$="Alpha Sprites"  

 setcursor 0,0   
 print "Effect Mode: "+Modename$
 print fps()
   
   Sync
loop





Function RotateVerts(Pts#(),RotatedPts#(),NumbOfVerts,Tilt#,turn#,roll#,ObjectDistance#)


 cx=getscreenwidth()/2
 cy=getscreenheight()/2
   

   Rem prepare the rotation matrix
  A#=Cos(tilt#) : B#=Sin(tilt#)
  C#=Cos(turn#) : D#=Sin(turn#)
  E#=Cos(roll#) : F#=Sin(roll#)
  AD#=A#*D#
  BD#=B#*D#

; Calc Rotation Matrix  
   m11#=C#*E#
  m21#=-1*C#*F#
  m31#=D#
  m12#=BD#*E#+A#*F#
  m22#=-1*BD#*F#+A#*E#
  m32#=-1*B#*C#
  m13#=-1*AD#*E#+B#*F#
  m23#=AD#*F#+B#*E#
  m33#=A#*C#

   Rem rotate all the points using the matrix
  For p=0 To NumbOfVerts

    pointx#=pts#(p,1)
    pointy#=pts#(p,2)
    pointz#=pts#(p,3)

     rotatedPts#(p,1) = (m11# * pointx#) + (m12# * pointy#) + (m13# * pointz#)
     rotatedPts#(p,2) = (m21# * pointx#) + (m22# * pointy#) + (m23# * pointz#)
     rotatedPts#(p,3) = (m31# * pointx#) + (m32# * pointy#) + (m33# * pointz#)
     
     Rem Now Do the perspective calculation
     z# = rotatedPts#(p,3) + ObjectDistance#
       rotatedPts#(p,1) = cx+ ((rotatedPts#(p,1)*ProjectionX# )/ z#)
     rotatedPts#(p,2) = cy+ ((rotatedpts#(p,2)*ProjectionY# )/ z#)
    RotatedPts#(p,3)=z#
  Next p

   
Endfunction
   


Function SizeVerts(Pts#(),x_scale#,y_scale#,z_scale#)
   Rem rotate all the points using the matrix
  For p=1 To getArrayelements(pts#(),1)
    pts#(p,1)=pts#(p,1)* x_scale#
    pts#(p,2)=pts#(p,2)* Y_scale#
    pts#(p,3)=pts#(p,3)* Z_scale#
  Next p
Endfunction
   






Function BlitImageClr(ThisImage,X#,y#,ClrRGB)
 BlitMode=1
 blitimage ThisIMage,x#,y#,transparentflag,Blitmode,ClrRGB,0,0   
EndFunction

Function BlitImageALphaAdd(ThisImage,X#,y#,AddRGB)
   select GetSCreenDepth()
 case 32
    BlitMode=64
    blitimage ThisImage,x#,y#,transparentflag,Blitmode,AddRGB,0,0   
 default
 ; Create an Equivalent Alpha effect using a box alpha masked over the src image
    OldSurface=getsurface()
    w=getimagewidth(Thisimage)
    h=getimageHeight(Thisimage)
    oldinkmode=getinkmode()
    rendertoimage thisimage
    inkmode 1+64
    boxc 0,0,w,h,1,AddRgb
    inkmode oldinkmode   
    rendertoimage OldSurface
    drawimage Thisimage,X#,y#,0
   endselect
 
EndFunction


Function BlitImageALphaSub(ThisImage,X#,y#,SubRGB)
   select GetSCreenDepth()
   ; BlitImage only supports 32bit in PBV1.089 and bellow
 case 32
    BlitMode=128
    blitimage ThisImage,x#,y#,transparentflag,Blitmode,SubRGB,0,0   
 default
 ; Create an Equivalent Alpha effect using a box alpha masked over the src image
    OldSurface=getsurface()
    w=getimagewidth(Thisimage)
    h=getimageHeight(Thisimage)
    oldinkmode=getinkmode()
    rendertoimage thisimage
    inkmode 1+128
    boxc 0,0,w,h,1,SubRgb
    inkmode oldinkmode   
    rendertoimage OldSurface
    drawimage Thisimage,X#,y#,0
   endselect
 

EndFunction






[/pbcode]

Title: Sprite (alpha) Particles
Post by: stef on January 08, 2006, 04:04:47 AM
Hi!

Looks nice! :)
Edit:
No, it's looking great (must use arrow-keys and space-key!)

Can you tell something about command "blitimage" and how to use it?

Greetings
stef
Title: Sprite (alpha) Particles
Post by: medwayman on January 08, 2006, 07:13:23 AM
Wow that's very nice!

I didn't realise you'd already released PlaybasicFX ;)
Title: Sprite (alpha) Particles
Post by: kevin on January 08, 2006, 09:17:11 AM
Stef,

 Here ya go
 Blit Fx Library (http://www.underwaredesign.com/forums/index.php?topic=998.0)
Title: Sprite (alpha) Particles
Post by: Ian Price on January 08, 2006, 09:22:46 AM
Looks lovely :D
Title: Sprite (alpha) Particles
Post by: kevin on January 08, 2006, 09:37:15 AM
Medway,

 Well, this stuff has always been there, but you just have to careful about how it's used ATM.   That is to say, that performing any blend operation that reads  video memory is a no/no.  But if you do it all in fx buffers, then move it down, there's less of a drama.

 Obviously the biggest benefit of PBFX  will be that all rendering will be performed with hardware...  Fun :)
Title: Sprite (alpha) Particles
Post by: stef on January 08, 2006, 09:48:13 AM
Hi!

Thanks for info!
Title: Sprite (alpha) Particles
Post by: thaaks on January 08, 2006, 10:46:21 AM
Pretty cool! Not very fast on my machine but looks great. Will fiddle around with it  ;)

Thanks for the sample code,
Tommy
Title: Sprite (alpha) Particles
Post by: kevin on January 08, 2006, 11:39:56 AM
Yeah, I can't say i'm terribly surprised, it won't ever be 'fast'.  Whatever that means.  There's a fair slab of rotation overhead on the VM handling 400 points,  and the actual shift it's to video memory, is at the mercy of your video bus.   But none of the polygon renders (which draw sprites) are MMX optimized, which is where most of the time is spent.

  It clocks about 24/25fps in32bit and about 30fps in 16bit on my Duron 800 + GF2 combo.
Title: Sprite (alpha) Particles
Post by: kevin on January 12, 2006, 02:39:47 PM
In between baby sitting yesterday, and fixing the clipping and some render errors in Blit Image, i've been experimenting with a few other modes.   This one takes two source images and performs a 50/50 alpha blend between the two and dumps tot eh output surface.  If both surfaces are FX surfaces this avoid the reading from memory bottleneck

 The blend image is secondary though, so unfortunately you can't offset the two during the merge. And the second image can't be smaller than source. It's not express at full screen (640*480*32) on the Duron 800/gf2 combo, but should be useful when used in smaller doses.

This picture is the above demo modified to merge the sprite image with a shadebox + image on a second image.  The Blit mode doesn't effect either, it just merges them and write to where ever the current surface is.
Title: Sprite (alpha) Particles
Post by: kevin on February 01, 2006, 10:59:49 AM
This image is the product of another BlitImage combination effect.  This mode performs an alpha subtraction between two images during the output.  This means that you can use a second image as sort of light map (well subtraction map).  It's creates a pretty interest effect in the particle demo, the particles turn into these sort of  morphing blobs.  Very odd, but cool :)

 I guess should explain how it works.  

 Image A = Your normal image
 Image B = Subtraction Map

 Outputted pixels are read from Pixel A and then have the corresponding pixel from image B subtracted from it then it's drawn to the ouput surface.

  So white pixels will make an area blacked out,  and Black pixels will have no effect.   Alternatively if you fill Image  with Rgb(0,0,255)  this would screen out Blue in the render image...  You can make a flash light by using gouraud shaded triangles.  Projected from (or around) the viewer.