Fading to black

Hello,

Here you’ll find two routines for fading to black, an incorrect and a correct
one, separated by conditional compiles. The one that is currently enabled is
incorrect–and I can’t figure out why. The correct version is very slow with
those 3 divides per pixel. The basic idea with the incorrect version is to
just setup a delta buffer and apply it iteratively… but for some reason the
colors are screwy and it doesn’t fade enough. Any ideas?

The delta buffer is called originals because that’s what it stores in the
correct version–the original pixel values.

void ZVideo::fadeToBlack( Uint8 numSteps )
{
Uint32 numCells = screenWidth * screenHeight;
Uint16* pixels = 0;
Uint16 color = 0;
Uint32 redMask = screen->format->Rmask;
Uint32 greenMask = screen->format->Gmask;
Uint32 blueMask = screen->format->Bmask;
Uint16* originals = 0;

if( SDL_MUSTLOCK( screen ) && ( SDL_LockSurface( screen ) < 0 ) )
{
cerr << “zelda: could not lock surface for buffer copy in
ZVideo::fadeToBlack()\n”;
return;
}
else
{
// Allow for the fact that a lock might shuffle addresses in screen.
pixels = (Uint16*) screen->pixels;
originals = new Uint16[ screenWidth * screenHeight ];

if( originals == 0 )
{
  cerr << "zelda: could not allocate color buffer in

ZVideo::fadeToBlack()\n";
return;
}

#if 1
for( unsigned int i = 0; i < numCells; i++ )
{

  if( pixels[i] > 0 )
  {
color = pixels[i] & redMask;
originals[i] &= ~redMask;
originals[i] |= color / numSteps;

color = pixels[i] & greenMask;
originals[i] &= ~greenMask;
originals[i] |= color / numSteps;

color = pixels[i] & blueMask;
originals[i] &= ~blueMask;
originals[i] |= color / numSteps;
  }
  else
  {
originals[i] = 0;
  }

}

#else
memcpy( originals, pixels, numCells * 2 );
#endif
SDL_UnlockSurface( screen );
}

for( int i = numSteps - 1; i >= 0; --i )
{

if( SDL_MUSTLOCK( screen ) && ( SDL_LockSurface( screen ) < 0 ) )
{
  cerr << "zelda: failed to lock surface in ZVideo::ditherToBlack()\n";
  delete[] originals;
  return;
}

pixels = (Uint16*) screen->pixels;

for( unsigned int j = 0; j < numCells; j++ )
{

#if 1
if( pixels[j] < originals[j] )
{
pixels[j] = 0;
}
else if( pixels[j] > 0 )
{
pixels[j] -= originals[j];
}
#else
if( pixels[j] > 0 )
{
color = originals[j] & redMask;
pixels[j] &= ~redMask;
pixels[j] |= ( color * i ) / numSteps;

color = originals[j] & greenMask;
pixels[j] &= ~greenMask;
pixels[j] |= ( color * i ) / numSteps;

color = originals[j] & blueMask;
pixels[j] &= ~blueMask;
pixels[j] |= ( color * i ) / numSteps;
  }

#endif

}

if( SDL_MUSTLOCK( screen ) )
{
  SDL_UnlockSurface( screen );
}

flip( );

}

delete[] originals;
}

m.–
“Plausibility is just what it does have, Crito, rather than truth.”
– Socrates, Euthydemus

i’ve always thought it looks cool when menus, etc fade to black and then
back in when changing and stuff. is this done with alpha blending or
something else? i know you could use pallete tricks, but i’m doing 16bit and
dont want to get away from that. alpha blending seems to be really slow on
my computer in 2d. in 3d it seems to be really fast, but apparently its not
done in hardware in 2d. btw, my system is AMD XP 1700+, gf3ti200, so its not
a problem with my hardware. is there some cool, fast way to do fading that i
dont know about, or is alpha blending how its done?_________________________________________________________________
Add photos to your messages with MSN 8. Get 2 months FREE*.
http://join.msn.com/?page=features/featuredemail

Hi,

you’re right, alphablending is easiest, but very slow in hardware. I wrote a
util for it, I only have still to modify it that it creates a software
surface and then do a regular blit to the hardware surface.

This is the trick in case of hardware surface:

  1. Create temporary surface in SOFTware
  2. Copy the hardware surface to it with a regular blit
  3. Blend the black surface (also surface) over it
  4. Blit the temporary surface back to the hardware surface

My utility is synchronous, which means in this case that entire fade is
done, before exiting the function. Therefore, the overhead of only once
creating and destroying the temporary surface is very low.

You can read it here:

http://www.2dgame-tutorial.com/sdl/fading.htm

Patrick.

On Wed, 20 Nov 2002 04:18:02 0000 “Matt Monson”
wrote.
i’ve always thought it looks cool when menus, etc fade to black and then
back in when changing and stuff. is this done with alpha blending or
something else? i know you could use pallete tricks, but i’m doing 16bit
and
dont want to get away from that. alpha blending seems to be really slow on
my computer in 2d. in 3d it seems to be really fast, but apparently its not

done in hardware in 2d. btw, my system is AMD XP 1700 , gf3ti200, so its
not
a problem with my hardware. is there some cool, fast way to do fading that
i>dont know about, or is alpha blending how its done?


Add photos to your messages with MSN 8. Get 2 months FREE*.
http://join.msn.com/?page=features/featuredemail


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

You probably mean in software; it’s very fast in hardware, at least with
OpenGL.On Tue, Nov 19, 2002 at 11:18:22PM -0800, patrick wrote:

you’re right, alphablending is easiest, but very slow in hardware. I wrote a


Glenn Maynard

SDL,

whats wrong with this code:

SDL_Event event;
while(true)
{
while(SDL_PollEvent(&event))
{
switch(event.key.keysym.sym)
{
case SDLK_a:
/* do some stuf */
break;
case SDLK_ESCAPE:
quit(0);
break;
case SDL_QUIT:
quit(0);
break;
default:
break;
}
}
}

When I am making fast mouse moving east<->west I get SDL_QUIT event, when I
commented it out, I get SDLK_ESCAPE event, but I am not hitting any kay on
keyboard!

Do I have to use while(SDL_WaitEvent(&event) >= 0) insted of while(true)while
(SDL_PollEvent(&event)) or I have to make some event filtering? is it possible,
that some mouse etc. events has the same code as SDL_QUIT or SDLK_ESCAPE?

marex

whats wrong with this code:

A lot. You appear to be confused about event handling. The SDL_Event
is a union of many different event types, but your code always
assumes the event is from the keyboard. You should check event.type
first to see what kind of event it is. Second, SDL_QUIT is not a
valid key code. The loop should look something like this:

SDL_Event event;
while(true)
{
while(SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_a:
/* do some stuf */
break;
case SDLK_ESCAPE:
quit(0);
break;
}
break;

        case SDL_QUIT:
            quit(0);
            break;
    }
}

}

Hope that makes it a little clearer,–
Matthijs Hollemans
All Your Software
www.allyoursoftware.com

You have to check the event type before interpreting it as a keyboard event.

From one of the test applications in the distribution:

while(true)
{
while(SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_KEYDOWN:
… etc

Huib-Jan> ----- Original Message -----

From: marex@jelgava.lv (Mareks Rampans)
To:
Sent: Wednesday, November 20, 2002 10:30 AM
Subject: [SDL] SDL_Event

SDL,

whats wrong with this code:

SDL_Event event;
while(true)
{
while(SDL_PollEvent(&event))
{
switch(event.key.keysym.sym)
{
case SDLK_a:
/* do some stuf */
break;
case SDLK_ESCAPE:
quit(0);
break;
case SDL_QUIT:
quit(0);
break;
default:
break;
}
}
}

When I am making fast mouse moving east<->west I get SDL_QUIT event, when
I
commented it out, I get SDLK_ESCAPE event, but I am not hitting any kay on
keyboard!

Do I have to use while(SDL_WaitEvent(&event) >= 0) insted of
while(true)while
(SDL_PollEvent(&event)) or I have to make some event filtering? is it
possible,
that some mouse etc. events has the same code as SDL_QUIT or SDLK_ESCAPE?

marex


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

You forget to check the type of the event. Not all events are from keyboard.
so if(event.type==SDL_KEYBOARDEVENT) or something can’t remember the
constants name.On Wednesday 20 November 2002 11:30, you wrote:

SDL,

whats wrong with this code:

SDL_Event event;
while(true)
{
while(SDL_PollEvent(&event))
{
switch(event.key.keysym.sym)
{
case SDLK_a:
/* do some stuf */
break;
case SDLK_ESCAPE:
quit(0);
break;
case SDL_QUIT:
quit(0);
break;
default:
break;
}
}
}

When I am making fast mouse moving east<->west I get SDL_QUIT event, when I
commented it out, I get SDLK_ESCAPE event, but I am not hitting any kay on
keyboard!

Do I have to use while(SDL_WaitEvent(&event) >= 0) insted of
while(true)while (SDL_PollEvent(&event)) or I have to make some event
filtering? is it possible, that some mouse etc. events has the same code as
SDL_QUIT or SDLK_ESCAPE?

Judging from some of the posts, there seems to be some confusion. The
original poster wrote:

in 3d it seems to be really fast, but apparently its not done in
hardware in 2d. btw, my system is >AMD XP 1700+, gf3ti200, so its not a
problem with my hardware. is there some cool, fast way > to do fading
that i dont know about, or is alpha blending how its done?

Alpha-blending is never done in hardware in 2D. If there are any cards
which support it, I don’t know of them. Most apps use some sort of MMX
or other assembly algortihms to perform software alpha-blending. I
remember reading that in Commandos all the sprites had their edges
blended with the background, in software. Alpha-blending using D3D or
OpenGL is fast because the drivers support it. If you need lots of
alpha-blending in a 2D game, using a 3D API to reder is not such a bad idea.>On Tue, Nov 19, 2002 at 11:18:22PM -0800, patrick wrote:

you’re right, alphablending is easiest, but very slow in hardware. I wrote a

You probably mean in software; it’s very fast in hardware, at least with
OpenGL.

I think what he meant is that it is slow in ‘hardware memory’, aka video
memory. When using your own alpha-blending routine, it is best to work
with data that is stored in system memory, since accessing video memory
will really slow you down. Haven’t used SDL’s alpha-blending in a while
but as I recall it only works on software surfaces - for precisely this
reason.

When you want fade-to-black 3D scene - best way is to modify light value.On Wed, Nov 20, 2002 at 02:26:16AM -0500, Glenn Maynard wrote:

you’re right, alphablending is easiest, but very slow in hardware. I wrote a

You probably mean in software; it’s very fast in hardware, at least with
OpenGL.


http://decopter.sf.net - free unrealistic helicopter simulator

An embedded and charset-unspecified text was scrubbed…
Name: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20021120/1f04f78c/attachment.asc

No, I just mean that this is very fast:

(render scene)
glBindTexture(GL_TEXTURE_2D, 0); /* no texture /
glColor4f(0,0,0, dim); /
partially transparent black */
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(right,0);
glVertex2f(right,bottom);
glVertex2f(0,bottom);
glEnd();

as it’ll use 3d hardware to blend the scene toward black. Since he’s
apparently not using OpenGL, this method won’t work for him.On Wed, Nov 20, 2002 at 02:50:48AM -0500, patrick at 2dgame-tutorial.com wrote:

Yes, maybe it can be done in hardware, but SDL doesn’t make the explicit call to it or
something. It can also be the OpenGL does has a very optimized funtion for it and performs a
blend in software…


Glenn Maynard