Page 1 of 1

StartSpecialFX() Enhancement

Posted: Sat May 31, 2003 3:58 am
by Revolver
I was messing around with the special effects commands today, and noticed something. The documentation for StartSpecialFX() states that any normal sprite drawing commands(such as DisplaySprite()) should be used after StopSpecialEffects(). I figured it meant that you should use them outside the special effects environment, which meant you could also do it before StartSpecialFX(). I was wrong! Upon looking closer to the documentation, it states that StartSpecialFX() creates a new memory buffer in the main system ram to perform the special effects operations with. Well this is fine, but it also means that any normal sprite commands you used to draw to the buffer in the video memory are now wiped away! Take for example, the following code:

Code: Select all

InitSprite()
InitMouse()
InitKeyboard()
OpenScreen(640, 480, 32, "Sprite Test")
LoadSprite(0, "Data\Background.bmp", 0)
LoadSprite(1, "Data\PureBasic.bmp", #PB_Sprite_Memory)

Repeat
  
  FlipBuffers()
  ExamineMouse()
  
  DisplaySprite(0, 0, 0)
  
  StartSpecialFX()
    DisplayTranslucideSprite(1, MouseX(), MouseY(), 128)
  StopSpecialFX()
  
  StartDrawing(ScreenOutput())
    DrawingMode(1)
    Locate(10,10) : DrawText("Testing text")
  StopDrawing()
  
  ExamineKeyboard()

Until KeyboardPushed(#PB_Key_Escape)

End
You'd think this would display the background, then an alpha blended pb logo wherever the mouse is, and then some plain text on it, right? Wrong! That first DisplaySprite(0, 0, 0) command is nullified, because when you call StartSpecialFX(), it uses a new, blank buffer in the system ram to draw on, not the one you drew the background sprite on in video memory. Now, check out this following code, that actually works(this is how it is done in the examples):

Code: Select all

InitSprite()
InitMouse()
InitKeyboard()
OpenScreen(640, 480, 32, "Sprite Test")
LoadSprite(0, "Data\Background.bmp", #PB_Sprite_Memory)
LoadSprite(1, "Data\PureBasic.bmp", #PB_Sprite_Memory)

Repeat
  
  FlipBuffers()
  ExamineMouse()
  
  StartSpecialFX()
    DisplaySprite(0, 0, 0)
    DisplayTranslucideSprite(1, MouseX(), MouseY(), 128)
  StopSpecialFX()
  
  StartDrawing(ScreenOutput())
    DrawingMode(1)
    Locate(10,10) : DrawText("Testing text")
  StopDrawing()
  
  ExamineKeyboard()

Until KeyboardPushed(#PB_Key_Escape)

End
This works because I loaded the background sprite into the system ram, and displayed it after StartSpecialFX(), onto the buffer that was being used for the special effects. Why am I complaining? This is slow! The PB docs say specifically that commands used in the special effects mode are slower than they are outside it, and that all normal sprite commands should be used outside the special effects mode when possible. Well, if you're going to be using the special effects mode at all, then you can forget using any normal sprite commands before you use the special effects commands, unless you want them to all be done inside the special effects mode, which is slower than the video card's memory and processing. This is a bad thing, because you're always going to have something under the graphics you're displaying with special effects, be it just a background, or your entire 2D world(if only your HUD was using alpha effects, you'd draw the entire world in normal commands first, then draw the HUD with special effects commands). The way things are set up now, you'd have to render the entire 2D world inside the special effects mode, and have all of the sprites for the world loaded into system ram! This would be horrible for a game developer!

Enough of this complaining, what would I recommend be done about this? Well, the documentation states that StopSpecialFX() copies the graphics buffer that was used for special effects mode from the system ram to the video card's ram. This is why you can use normal sprite commands after you're done using the special effects mode. Why not do something similar for StartSpecialFX()? When this command is called, it should copy the current drawing buffer from video card ram to the system ram, so that any normal sprite commands used before the special effects mode was needed will be retained in the current drawing buffer. That way, I could load my background sprite into the normal video memory, use the video card to draw it to the buffer very quickly, then draw the alpha logo on top of it with the system processor and memory.

Please correct me if I have gotten something wrong, or if you would like me to explain something more, but I believe I am correct in what is happening with these commands. Thanks for your time!

Posted: Sat May 31, 2003 5:15 am
by Paul
Why am I complaining? This is slow! The PB docs say specifically that commands used in the special effects mode are slower than they are outside it
If you want speed (much faster than SpecialFX) then use commands from the Sprite3D Library.

Posted: Sat May 31, 2003 6:33 am
by Revolver
I'd rather not have all of my sprites be one of the following dimensions: 16x16, 32x32, 64x64, 128x128 or 256x256... Plus look at how robust the sprite command set is compared to the relatively sparse 3d sprite command set.

Posted: Sat May 31, 2003 10:50 am
by Fred
Ok, let's clarify a bit. We will try to do these operations with the StartFX():

1) Have a nice background
2) Blend some sprites on the background

If you use the regular DisplaySprite() command, the sprite is copied directly by the video card chipset to the VideoRam. Ok, so we have our background in the video ram, keep this in mind. So if I want to blend it at fast speed, I need to copy the whole videoram content into the system memory and then do all the blends ops. This is the bottleneck, and doing this is awfully slow. And you still have to copy back the whole buffer to the videoram once the blending is done.

So the SpecialFX() mode skip the first Video->System copy as it is much faster to copy a sprite from SystemMem->System than Video->System (you can easily understand why, the processor has to go trough the PCI/AGP bus).

The second way you used is of course the right one.

Note: you can use all the special fx command directly on the video screen (without Start/StopFX). For small op it will be faster I guess but it will slower very quickly if you do a lot of blending ops.

What can we do ? I can add a flag to StartFX() to copy the current video buffer. Please be careful about performance as I stated above. And I think it could have a clever way with this stuff: doing a clipping area:

StartFX(x,y,Width,Height) to only work on a small part of the screen instead of the whole screen.

Any comments are welcome.

Posted: Sat May 31, 2003 5:51 pm
by Revolver
Fred wrote:StartFX(x,y,Width,Height)
I like this idea a lot! Let's say I drew my game world with normal sprite commands, and then wanted to use some alpha effects for the HUD. Well, the HUD doesn't take up the entire screen, just little portions of some corners and maybe sides. It would not make any sense at all to transfer the entire screen buffer to system memory to only do effects on one small piece of the screen. However, if you had, let's say, 1 icon in each corner of the screen, if you wanted to do them all in the same SpecialFX() mode, you'd have to copy nearly the whole screen buffer to system memory. Or, you could call the StartSpecialFX() and StopSpecialFX() four times, 1 for each small part of the screen you wanted to do alpha effects on. Do these 2 commands have any additional overhead that would slow them down if you called them 4 times per game loop? Or is the only really slow thing thats happening being the screen buffers being copied? If that's true, then copying 32x32 pixels (the icons in the corners) 2 times per SpecialFX() mode(from video memory to system memory first, then system memory back to video memory when done), 4 times per game loop(8,192 total pixels) would still be faster than 2 copies of 640x480 (or whatever resolution you're using), 1 time per game loop(614,400 total pixels).

Posted: Sat May 31, 2003 6:23 pm
by Revolver
Just to clarify you'd have to make sure that StopSpecialFX() only copied back the same clipped dimensions specified in StartSpecialFX(), not the entire screen. I guess this would seem obvious, but I just wanted to get my point across better

Posted: Sun Jun 01, 2003 11:10 am
by Fred
Yes, that's exaclty the way I would like for StopSpecialFX(). So, I will implement this soon.

Posted: Fri May 13, 2005 11:46 am
by THCM
Did I miss something here? Fred do you still plan to implement this?

Posted: Sun May 15, 2005 7:32 pm
by S.M.
Hi Revolver
Why you don't use simply system memory Sprites ? :?
regards
Stefan

Posted: Sun May 15, 2005 7:52 pm
by freedimension
S.M. wrote:Hi Revolver
Why you don't use simply system memory Sprites ? :?
regards
Stefan
Don't expect an answer. His posting is from may 2003, his post count ist 22 ;)

Posted: Sun May 15, 2005 8:06 pm
by S.M.
freedimension wrote: Don't expect an answer. His posting is from may 2003, his post count ist 22
Oops :oops:

:lol:

Posted: Mon May 16, 2005 12:30 am
by blueznl

Posted: Mon May 16, 2005 12:32 am
by blueznl
iirc fred was going to do something with a copy option... i think...

Posted: Mon May 16, 2005 12:48 pm
by THCM
Very nice Guide blueznl! Any chance to get your tutorial for offline browsing?