Problems trying to fade in windowed mode

Member
Posts: 67
Joined: 2006.07
Post: #1
A while back I asked about how to fade an OpenGL context when in windowed mode. I was told to adjust the alpha of a quad drawn over everything else. I assume this is similar to the method described here, which I found via a quick Google search. However, for some reason it doesn't seem to be working for me. It just draws a black quad at full opacity and then it just sticks there -- the sounds and music keep playing with no graphics being drawn.

Right now, when I want to fade, I call a function that fades the display, draw the next frame, swap buffers (although nothing appears because the screen is completely blacked out), and then call a function that fades the display back in. In order to do that in the same way for windowed mode, I thought it would be necessary to take a snapshot of the buffer using glReadPixels() and then draw the quad over that repeatedly. But I got crashes and such. I was also wondering if there was a way to read the back buffer (so I can fade out, draw to the screen, and fade back in by overlaying the quad over the contents of the back buffer) in OpenGL.

Am I going about this all wrong, or is there something I am missing?
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #2
The quad thing should work just fine. It sounds like you're doing it wrong somehow. The only time you should swap buffers is by calling something like [[NSOpenGLContext currentContext] flushBuffer]; (or equivalent) at the end of every frame, only once per frame. That link that you put up does a for loop right in place, but that's not how it should be done on the Mac. You should be calling drawRect (or equivalent) every frame via a timer or through a loop callback in GLUT or whatever -- don't try to hold the machine up and swap buffers like that. Instead, keep track of the opacity value of your covering quad across frames, like fade = opacity * deltaTime, or something like that. It might be easier to offer more specific advice, if you need it, if you showed some code.
Quote this message in a reply
Member
Posts: 67
Joined: 2006.07
Post: #3
Right now, I call my fading functions in the middle of a block of code, like this, for example (in my menu controlling class):

Code:
// Fade out
gGameController->GetScreenController()->FadeOut();

// Draw the first frame of the menu
DrawMenu();

// Update the back buffer
gGameController->GetScreenController()->Update();

// Fade in again
gGameController->GetScreenController()->FadeIn();

I do this because the fading functions set the display alpha in a while loop. Would the quad method work if I made the fade update in the main game loop instead of in a function like I am doing now? Actually, how come the way the link suggested doesn't work? I am using Carbon with AGL, if that makes a difference.

Also, if it helps, here is my current fading code, ripped from Apple's documentation. If possible, I would like to add an else block to the two functions so I don't have to modify the rest of my code.

Code:
// Fading functions

void ScreenController::FadeOut(void)
{
    if (fullScreen)
    {
        double fadeValue = 1.0;
        double startTime = CurrentTimeInMicroseconds();
        double currentTime = startTime;
        
        while (fadeValue >= 0.0)
        {
            double elapsedTime = CurrentTimeInMicroseconds() - currentTime;
            currentTime += elapsedTime;
            
            if (elapsedTime > kFadeDelay)
            {
                startTime = CurrentTimeInMicroseconds();
                
                CGSetDisplayTransferByFormula(kCGDirectMainDisplay,
                    redMin, fadeValue * redMax, redGamma, greenMin,
                    fadeValue * greenMax, greenGamma, blueMin,
                    fadeValue * blueMax, blueGamma);
                
                fadeValue -= kFadeIncrement * elapsedTime;
            }
        }
        
        // Make sure the screen is completely faded out
        CGSetDisplayTransferByFormula(kCGDirectMainDisplay, redMin,
            0.0, redGamma, greenMin, 0.0, greenGamma, blueMin, 0.0,
            blueGamma);
    }
}

void ScreenController::FadeIn(void)
{
    if (fullScreen)
    {
        double fadeValue = 0.0;
        double startTime = CurrentTimeInMicroseconds();
        double currentTime = startTime;
        
        while (fadeValue <= 1.0)
        {
            double elapsedTime = CurrentTimeInMicroseconds() - currentTime;
            currentTime += elapsedTime;
            
            if (elapsedTime > kFadeDelay)
            {
                startTime = CurrentTimeInMicroseconds();
                
                CGSetDisplayTransferByFormula(kCGDirectMainDisplay,
                    redMin, fadeValue * redMax, redGamma, greenMin,
                    fadeValue * greenMax, greenGamma,   blueMin,
                    fadeValue * blueMax, blueGamma);
                
                fadeValue += kFadeIncrement * elapsedTime;
            }
        }
        
        // Make sure the screen is completely faded in
        CGSetDisplayTransferByFormula(kCGDirectMainDisplay, redMin,
            redMax, redGamma, greenMin, greenMax, greenGamma, blueMin,
            blueMax, blueGamma);
    }
}

Thanks for any help you can give.
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #4
Sorry, I'm a little brain-fried at the moment, but two thoughts come to mind:

1) I'm confused as to whether you are trying to fade the display or fade the scene. Fading the scene should be done with a covering quad so that it works in windowed mode as well. Fading the display for fading into and out of full screen should be done with the CG routines.

2) In my experience, CGSetDisplayTransferByFormula isn't ideal because you have to loop through all displays if you are capturing all displays. And worse, the formula doesn't go through the gamma tables so the fading can be slightly off from what the users display calibration might be, possibly causing a slight shade flicker at the start and end of the fades. I use CGDisplayFade instead.
Quote this message in a reply
Member
Posts: 67
Joined: 2006.07
Post: #5
I'm trying to fade the whole display when in full screen mode, but fade only the scene when in windowed mode (fading the whole display while the game is running in windowed mode seems like overkill). If possible, I would like to do this by modifying the two functions I already have (the FadeOut()/FadeIn() routines). Although I'm thinking that to do this with the covered quad, I'd have to re-engineer the fading system.

Actually, would it be better to just use a covered quad for fading in both full screen and windowed mode and save the CGDisplayFade() for just the resolution switching?
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Mac OS X. Switching between fullscreen and windowed mode. e40pud 2 4,275 Jan 25, 2010 12:01 PM
Last Post: OneSadCookie
  Fade Particle to black bonanza 8 5,538 Apr 3, 2008 05:24 AM
Last Post: bonanza
  how to make a RGBA image fade away? WhatMeWorry 7 4,525 Nov 13, 2006 07:58 PM
Last Post: akb825
  Weird Windowed Mode GFX Tearing nabobnick 2 2,867 Jul 25, 2005 06:45 PM
Last Post: nabobnick
  Fullscreen windowed OpenGL mode maaaaark 8 5,180 Mar 11, 2005 12:34 PM
Last Post: maaaaark