Screen Fade

BlitzMax Forums/BlitzMax Programming/Screen Fade

Grey Alien(Posted 2006) [#1]
I'm aware I could do a screen fade by setting a timer and continuing to draw the screen with SetBlend AlphaBlend and progressively reducing the alpha with SetAlpha until the timer runs out.

But I'd prefer to grab the back buffer to an image (or draw a single frame to an image, but this doesn't seem possible like in BlitzPlus) and then draw that fading in a generic loop.

Does anyone have any info about how slow grabbing the backbuffer is? On my BlitzGames it could easily take 200/300ms which is a noticeable delay which I why I made a Dirty Rects system that kept a copy of the screen in RAM for ultra fast grabbing. The reason it was so slow was grabbing the backbuffer to RAM meant sending data backwards down the video pipeline = slow. If I grab an image in BMax (and the card has enough free RAM) will it grab onto the card i.e. fast, or back to RAM = slow? Also I heard that BMax keeps a copy of images in RAM anyway, so it might always be slow if this is true?

Any ideas?

Thanks in advance...


TartanTangerine (was Indiepath)(Posted 2006) [#2]
You heard of render to texture? Render the entire screen to an image (texture) and then fade that texture.

OR you could cheat and draw a Black Rectangle (ALPHA 0) over the entire screen and slowly make it opaque?


(tu) ENAY(Posted 2006) [#3]
> OR you could cheat and draw a Black Rectangle
> (ALPHA 0) over the entire screen and slowly make
> it opaque?

Heheh, that's what I do :) I mean why bother copying the contents somewhere else when you fade with a rectangle, if only you could do that in old skool Blitz.


Grey Alien(Posted 2006) [#4]
You heard of render to texture?
No never, not once ;-D So I need you module to do this right? Or is an old code snippet hiding in these forums somewhere?

Black thing is a good idea. Only thing is I would still need to keep drawing the screen each frame and then the black over the top, otherwise the backbuffer can become corrupted, for example when dragging the window around. So if I was to draw the screen each time, I needn't bother with a black rect, I could just draw everything with setblend as I mentioned in the first post.

Also i was trying to make a function this is independent of the screen drawing code so I can effectively pass it an image and it will do the fading all on it's own.


TartanTangerine (was Indiepath)(Posted 2006) [#5]
Oh you mean like this (this is old code but I think it still works on the latest version of BMAX):



Grey Alien(Posted 2006) [#6]
well I've made something like that already for my splash screens, but only for a single image. so with that I could pass in everything I'm drawing on screen (add to the list), then it would draw them all fading away. Good idea. Only thing is, passing them all into could be a pain with tons of objects on screen, some sprites, some buttons some blah blah. Guess I need a common type as a base, well I do have TSprite ... (So it says not public domain ... can I use it royalty free?)

Really if I can just change a flag so that the screen draws to an image instead of the backbuffer (like in BlitzPlus) I could just use that image in my own fade routine very easily. OR if I can grab the backbuffer into an image, I can use that. I'm just not sure how fast either of these will be based on previous experience.


ImaginaryHuman(Posted 2006) [#7]
In your screen fade are you trying to CROSSFADE, or just to fade to black or white?

On my iMac the glCopyTexSubImage2D() which copies part of the backbuffer into an existing texture, seems to work at full speed, suggesting it is hardware accelerated, otherwise if it went out to main memory it would be much slower framerate. I use it for a full-screen de-res effect for which I have to copy the whole frame to a texture and then draw the texture.

That said I don't know that all systems have this hardware accelerated, some may be software which is much slower.


Grey Alien(Posted 2006) [#8]
fade to black :-)

Thing is I'm not using openGL, but thanks for the idea anyway :-)


Grey Alien(Posted 2006) [#9]
as I suspected, this takes around 200ms in windowed mode and longer in full-screen mode. Weird thing is if I do it when my game framework has been running it only takes 50-70ms, can't explain that! Maybe the system is still doing stuff when this demo first runs... I'll try it waiting for a keypress first.

Strict
Graphics 800,600,0

Cls
DrawRect(100,100,100,100)
Flip

Local start = MilliSecs()
Local temp: TImage = CreateImage(800, 600)
GrabImage(temp,0,0)
SetImageHandle(temp,0,0) 'in case AutoMidHandle is true
DebugLog MilliSecs() - start



[edit] OK, with this after the flip it brings the full-screen back in line with the windowed mode time of 200ms. Bear this in mind when writing benchmark apps that the systems needs to be "ready" before you start testing.

While Not KeyHit(KEY_SPACE) Wend



ImaginaryHuman(Posted 2006) [#10]
I guess it depends what kind of a screen you are fading. Are you in the middle of live action with things moving around etc, and you want it to fade out to black?

If so. ... use:

SetBlend AlphaBlend
SetAlpha whateverleveloffade
SetColor 0,0,0
DrawRect 0,0,screenwidth,screenheight

at the same time as continuing to draw/update your game screen as normal.

You don't need to grab the backbuffer to do a fade to black.


Grey Alien(Posted 2006) [#11]
AngelDaniel: just did that and got back here to read your post :-) In fact actually, my game logic is not run but the drawing is so that everything stops moving but is still drawn. Also all my window controls and debug keys still work during the fade - that means if you click out the window or press P, the fade will be paused! However, instead of using your method, I am drawing a black rect over everything and fading that in or out. Why? Well what if some of my game objects need to have a SetAlpha level which is not 1! e.g translucent ones ;-) This new method rocks as there is no speed problem and it integrates with the Game Framework better.


ImaginaryHuman(Posted 2006) [#12]
Cool.