Jump to content


Desktop fadeout


14 replies to this topic

#1 Reedbeta

    DevMaster Staff

  • Administrators
  • 5311 posts
  • LocationSanta Clara, CA

Posted 05 April 2006 - 02:00 PM

Many games take up the entire screen, and when they start up there is often an unsightly few seconds in which the window creation, video mode changes and so forth cause the screen to flicker, the desktop to wink in and out of existence, and so forth. This code sample shows how to make the desktop smoothly fade to black when an application starts, allowing the messy details of graphics initialization to be hidden.

The demo operates by creating a borderless, captionless popup window covering the entire screen. Initially, this window is transparent because it does not paint itself. Then an OpenGL context is created that has no back buffer, so all draw calls operate directly on the displayed image. Each frame, a full-screen alpha-blended rectangle is drawn, fading the image gradually toward black. Any color (or texture) could be chosen, but black is probably the best in most cases. After the fadeout is complete, the application can switch video modes and create its main window, and then destroy the fadeout window. The demo program creates a new OpenGL context and renders a spinning cube until you press Escape.

The core of the effect is in this message handler for the fadeout window:
LRESULT CALLBACK FadeoutWndProc (HWND hWnd, UINT message,
	WPARAM wParam, LPARAM lParam)
{
	static int frames = 0;
	static DWORD nextFrameTime;

	switch (message)
	{
		case WM_CREATE:
		{
			// Set up a basic OpenGL environment for the fadeout, with no
			// backbuffer, zbuffer, stencil, or destination-alpha
			g_pRenderEnvironment = CreateOpenGLEnvironment(hWnd, false, false,
				false, false);
			if (!g_pRenderEnvironment)
			{
				MessageBox(hWnd, L"Could not set up OpenGL!",
					L"Error", MB_ICONEXCLAMATION);
				DestroyWindow(hWnd);
				PostQuitMessage(1);
				return 0;
			}

			ShowCursor(false);

			// Setup OpenGL state
			glEnable(GL_BLEND);
			glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
			glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
			glOrtho(0, 1, 0, 1, -1, 1);

			nextFrameTime = GetTickCount() + FADEOUT_TIME / 256;

			return 0;
		}

		case WM_PAINT:
		{
			if (GetTickCount() > nextFrameTime)
			{
				++frames;
				nextFrameTime += FADEOUT_TIME / 256;
				// Fade out the screen one more step
				glColor4f(0, 0, 0, (float)(255 - frames) / (256 - frames));
				glRectf(0, 0, 1, 1);
				glFinish();
				if (frames == 256)
				{
					// Finished fading out, so validate the window rectangle
					// (so Windows stops sending us paint messages)
					ValidateRect(hWnd, NULL);

					// Get rid of the existing render environment, as we will
					// be creating a new one for the main window
					delete g_pRenderEnvironment;

					// Create the main window before destroying the fadeout
					// window, so as not to allow the desktop to visibly
					// flicker between them
					CreateMainWindow();
					DestroyWindow(hWnd);
				}
			}

			return 0;
		}
	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}

I have tried the program on an nVIDIA GeForce 6800 and on an ATI Radeon 9600, but I would love to hear if it works (or fails) on other cards. :)

The full source code and binary are available here, with the source distributed under the BSD license. The source also demonstrates some parts of a lightweight, extensible framework for graphics applications that I've been developing for an engine I'm working on.

Some improvements that could be made to the code:
* Sometimes on ATI cards the taskbar isn't affected by the fadeout, though it disappears a few seconds after the main window is created. You might be able to fix this by making the fadeout window "topmost," though I haven't gotten around to trying it.
* Some useful work, like loading resources, could be done in the background while the fadeout is occurring. Currently the program just enters a busy wait between frames: since the window is not validated, Windows spams us with WM_PAINT messages, which are ignored until it's time for the next fadeout frame. This could be done with a timer instead.

#2 bladder

    DevMaster Staff

  • Members
  • PipPipPipPip
  • 1057 posts

Posted 05 April 2006 - 02:29 PM

I like it, I like it a lot. Thanks for sharing this.

Works perfectly on a gf4 ti 4200.

#3 monjardin

    Senior Member

  • Members
  • PipPipPipPip
  • 1033 posts

Posted 05 April 2006 - 05:28 PM

Works great with a Mobile Intel 915GM Express on this laptop. Looks sexy, I like it! :yes:

Were transparent windows supported prior to Windows 2000/XP? I'm just wondering if this would fail on Windows 98, but that may not matter much anymore... :closedeye
monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*

#4 Reedbeta

    DevMaster Staff

  • Administrators
  • 5311 posts
  • LocationSanta Clara, CA

Posted 05 April 2006 - 05:36 PM

monjardin said:

Were transparent windows supported prior to Windows 2000/XP? I'm just wondering if this would fail on Windows 98, but that may not matter much anymore... :closedeye

It's only transparent in the sense that it fails to paint itself or establish a background brush, so I think it should still work on Win98. I know XP has some fancy features for alpha-blended windows and stuff, but I'm not using that :)
reedbeta.com - developer blog, OpenGL demos, and other projects

#5 geon

    Senior Member

  • Members
  • PipPipPipPip
  • 939 posts

Posted 06 April 2006 - 03:29 PM

Great idea, works fine here too.

Still, there is a really akward color artifact visible. The colors don't fade to black linearly. It looks more like when you move your head in front of an old, low quality LCD screen.

I think this might look better if the number of fading frames was lower, so the integer math would get some more precission to play with.

#6 roel

    Senior Member

  • Members
  • PipPipPipPip
  • 698 posts

Posted 06 April 2006 - 04:14 PM

very sexy. on my ati 9600 the taskbar remains visible indeed.

#7 Blaxill

    Member

  • Members
  • PipPip
  • 66 posts

Posted 06 April 2006 - 08:07 PM

I really like this, nice work!

#8 davepermen

    Senior Member

  • Members
  • PipPipPipPip
  • 1306 posts

Posted 09 April 2006 - 08:13 PM

works great. only the always-on-top friend-icons from msgplus have some issue while blending..


haw about fading back once you quit your app? :D
davepermen.net
-Loving a Person is having the wish to see this Person happy, no matter what that means to yourself.
-No matter what it means to myself....

#9 MLeoDaalder

    New Member

  • Members
  • Pip
  • 4 posts

Posted 10 April 2006 - 10:16 AM

Very nice!

I might use this in my programs in the future.

It works on my ATI Radeon 9200SE. Though I think I might have to reset my refresh rate now, I'm getting headaches now just looking at my screen (started the moment I pressed Escape).

But I don't think it's something to do with your program.
Well, it might, since this only happens to some fullscreen programs.

#10 Francois Hamel

    Valued Member

  • Members
  • PipPip
  • 86 posts

Posted 15 April 2006 - 11:12 PM

awesome!
I really like it, makes your spinning cube application look real polished :)

thanks for the tip
I post with style, do you?

http://fhamel.blogspot.com/

#11 JeGX

    New Member

  • Members
  • Pip
  • 5 posts

Posted 16 April 2006 - 06:44 PM

Really cool Reedbeta :yes:

Works fine on my gf7800gt (winxp sp2 - forceware 84.21) and on my X700pro (winxp sp2 - catalyst 6.3).

#12 angel_prks

    New Member

  • Members
  • Pip
  • 2 posts

Posted 25 June 2010 - 03:53 AM

Hello Everyone,

Can I have a copy of the source code of this? I want to try it too. Please

#13 Reedbeta

    DevMaster Staff

  • Administrators
  • 5311 posts
  • LocationSanta Clara, CA

Posted 25 June 2010 - 04:11 AM

The full source and binary for this are here. But it should be noted this doesn't work anymore on Vista/Win7, only in XP.
reedbeta.com - developer blog, OpenGL demos, and other projects

#14 angel_prks

    New Member

  • Members
  • Pip
  • 2 posts

Posted 25 June 2010 - 04:59 AM

Ahhh.... Ok. Thank you for this. Ill just try it anyway...:)

#15 imerso

    Senior Member

  • Members
  • PipPipPipPip
  • 431 posts
  • LocationBrasil

Posted 25 June 2010 - 01:17 PM

That is a neat feature. I used to do that in the DOS days, fading out the text-mode palette before switching to ModeX! =)

Oh, but now I *need* to do that again, heheh. Thanks for bringing this again!





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users