Main Menu

Sprite (alpha) Particles

Started by kevin, January 07, 2006, 07:12:15 PM

Previous topic - Next topic

kevin

This  example uses sprites Alpha+ Circle Alpha Addition effects.    


 


 Updated Jan 2024, corrected a few small differences for modern PlayBASIC
PlayBASIC Code: [Select]
  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
Login required to view complete source code



Original Code:

PlayBASIC Code: [Select]
; 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


Login required to view complete source code



stef

#1
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

medwayman

Wow that's very nice!

I didn't realise you'd already released PlaybasicFX ;)

kevin

#3
Stef,

 Here ya go
 Blit Fx Library

Ian Price

I came. I saw. I played some Nintendo.

kevin

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 :)

stef


thaaks

Pretty cool! Not very fast on my machine but looks great. Will fiddle around with it  ;)

Thanks for the sample code,
Tommy

kevin

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.

kevin

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.

kevin

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.