Using DirectDraw's Gamma Controls to Perform a Fade
by Joseph Fernald

So why would you want to use the Gamma Control function which is included in Direct Draw to do a fade? Well there are two main reasons the first of which is Simplicity, and the second is the fact that by using a Gamma fade you don't lose any information which is stored on your primary surface.

Now that that's out of the way there are a few things we must take into consideration before implementing this technique. First your primary surface has to be at least 16 bit or greater. Second this fade can only be preformed on your primary surface due to the fact that what your doing here is manipulating your video cards gamma settings.

Let's get down to business. Included in the Direct Draw library is a structure called DDGAMMARAMP. This structure consists of 3 arrays of 256 WORDs. It the three arrays are called Red, Green, and Blue. It looks like the following:

typedef struct DDGAMMARAMP {

  WORD red[256];
  WORD green[256];
  WORD blue[256];
} DDGAMMARAMP, FAR * LPDDGAMMARAMP;

This structure will hold all the current values of our video cards current gamma settings. So lets declare a few variables that we can use in our program shall we?

//initialize the gamma control so that we can use it.
LPDIRECTDRAWGAMMACONTROL lpDDGammaControl = NULL;

//this structure will be the ramp value that we modify
DDGAMMARAMP DDGammaRamp;

//this structure will hold the old gamma values so that we can reset our video card after our fade is complete.
DDGAMMARAMP DDGammaOld;

Now that that's all done we need to find out of your video card supports gamma control (although direct X will simulate the fade even if your video card doesn't support gamma control.) So let's query the primary surface:

lpddsprimary->QueryInterface(IID_IDirectDrawGammaControl,(void **)&lpDDGammaControl);

Next we need to find out what the current gamma settings are on your video card right now and store it in our DDGAMMAOLD structure:

lpDDGammaControl->GetGammaRamp(0, &DDGammaOld);

Let's perform that task one more time and save the values to our DDGAMMARAMP structure so that we can modify the values:

lpDDGammaControl->GetGammaRamp(0, &DDGammaRamp);

Now unless a user changes the values of the gamma on their computer the values should go up as you reach the 256th value in your DDGammaRamp structure. Now because each value of Red, Blue and Green can be anywhere from 0 to 65535 we wouldn't want to decrement our values by 1. Instead I decided to make the code as fast as possible so I set all 256 values to 0 and update the screen after each. Here is how the code looks:

for(int blackloop=0;blackloop<256;blackloop++)
{

  //we wouldn't want to decrement a value unless it's greater than 0
  if(DDGammaRamp.red[blackloop] > 0)
    {
        //set the current value of DDGammaRamp.Red to 0.
        DDGammaRamp.red[blackloop]=0;
        //now let's update our primary
        lpDDGammaControl->SetGammaRamp(0, &DDGammaRamp);
        surface with the new gamma setting

    } //end if

//the routine was a little too fast so this slows it down a bit….
Sleep(1);

//we wouldn't want to decrement a value unless it's greater than 0
if(DDGammaRamp.green[blackloop] > 0)
  {
    //set the current value of DDGammaRamp.yellow to 0.
    DDGammaRamp.green[blackloop]=0;
    lpDDGammaControl->SetGammaRamp(DDSGR_CALIBRATE, &DDGammaRamp);
  } //end if

//the routine was a little too fast so this slows it down a bit….
Sleep(1);

//we wouldn't want to decrement a value unless it's greater than 0
if(DDGammaRamp.blue[blackloop] > 0)
  {
    //set the current value of DDGammaRamp.Blue to 0.
    DDGammaRamp. blue [blackloop]=0;
    lpDDGammaControl->SetGammaRamp(DDSGR_CALIBRATE, &DDGammaRamp);

} //end if

//the routine was a little too fast so this slows it down a bit….
Sleep(1);

} //end for

Now that the fade is complete, we need to restore all the old gamma values or our screen will stay black as the rest of your game continues.

lpDDGammaControl->SetGammaRamp(0, &DDGammaOld);

Well that wraps it up. There are a few other things you can do with the code. You can modify the code to Flash the screen Red when your player gets hit by something, Green when your swimming in toxic waste, blue if your drowning. And you can even modify the code to fade in, but I'm leaving that to everyone else to figure out.

Discuss this article in the forums


Date this article was posted to GameDev.net: 5/17/2000
(Note that this date does not necessarily correspond to the date the article was written)

See Also:
DirectDraw

© 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
Comments? Questions? Feedback? Click here!