Выбрать главу

    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left

   glEnd(); // Done Drawing The Quad

  }

Now that we have drawn our mask to the screen it's time to change blending modes again. This time we're going to tell OpenGL to copy any part of our colored texture that is NOT black to the screen. Because the final texture is an exact copy of the mask but with color, the only parts of our texture that get drawn to the screen are parts that land on top of the black portion of the mask. Because the mask is black, nothing from the screen will shine through our texture. This leaves us with a very solid looking texture floating on top of the screen.

Notice that we select the second image after selecting the final blending mode. This selects our colored image (the image that our second mask is based on). Also notice that we draw this image right on top of the mask. Same texture coordinates, same vertices.

If we don't lay down a mask, our image will still be copied to the screen, but it will blend with whatever was on the screen.

  glBlendFunc(GL_ONE, GL_ONE); // Copy Image 2 Color To The Screen

  glBindTexture(GL_TEXTURE_2D, texture[4]); // Select The Second Image Texture

  glBegin(GL_QUADS); // Start Drawing A Textured Quad

   glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f, –1.1f, 0.0f); // Bottom Left

   glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f, –1.1f, 0.0f); // Bottom Right

   glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f); // Top Right

   glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left

  glEnd(); // Done Drawing The Quad

 }

If scene was FALSE, we will draw the first scene (my favorite).

 else // Otherwise

 {

We start off by checking to see if masking is TRUE of FALSE, just like in the code above.

  if (masking) // Is Masking On?

  {

If masking is TRUE we draw our mask 1 to the screen (the mask for scene 1). Notice that the texture is rolling from right to left (roll is added to the horizontal texture coordinate). We want this texture to fill the entire screen that is why we never translated further into the screen.

   glBindTexture(GL_TEXTURE_2D, texture[1]); // Select The First Mask Texture

   glBegin(GL_QUADS); // Start Drawing A Textured Quad

    glTexCoord2f(roll+0.0f, 0.0f); glVertex3f(-1.1f, –1.1f, 0.0f); // Bottom Left

    glTexCoord2f(roll+4.0f, 0.0f); glVertex3f( 1.1f, –1.1f, 0.0f); // Bottom Right

    glTexCoord2f(roll+4.0f, 4.0f); glVertex3f( 1.1f, 1.1f, 0.0f); // Top Right

    glTexCoord2f(roll+0.0f, 4.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left

   glEnd(); // Done Drawing The Quad

  }

Again we enable blending and select our texture for scene 1. We map this texture on top of it's mask. Notice we roll this texture as well, otherwise the mask and final image wouldn't line up.

  glBlendFunc(GL_ONE, GL_ONE); // Copy Image 1 Color To The Screen

  glBindTexture(GL_TEXTURE_2D, texture[2]); // Select The First Image Texture

  glBegin(GL_QUADS); // Start Drawing A Textured Quad

   glTexCoord2f(roll+0.0f, 0.0f); glVertex3f(-1.1f, –1.1f, 0.0f); // Bottom Left

   glTexCoord2f(roll+4.0f, 0.0f); glVertex3f( 1.1f, –1.1f, 0.0f); // Bottom Right

   glTexCoord2f(roll+4.0f, 4.0f); glVertex3f( 1.1f, 1.1f, 0.0f); // Top Right

   glTexCoord2f(roll+0.0f, 4.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left

  glEnd(); // Done Drawing The Quad

 }

Next we enable depth testing, and disable blending. This prevents strange things from happening in the rest of our program :)

 glEnable(GL_DEPTH_TEST); // Enable Depth Testing

 glDisable(GL_BLEND); // Disable Blending

Finally all we have left to do is increase the value of roll. If roll is greater than 1.0 we subtract 1.0. This prevents the value of roll from getting to high.

 roll+=0.002f; // Increase Our Texture Roll Variable

 if (roll>1.0f) // Is Roll Greater Than One

 {

  roll-=1.0f; // Subtract 1 From Roll

 }

 return TRUE; // Everything Went OK

}

The KillGLWindow(), CreateGLWindow() and WndProc() code hasn't changed so we'll skip over it.

The first thing you will notice different in the WinMain() code is the Window title. It's now titled "NeHe's Masking Tutorial". Change it to whatever you want :)

int WINAPI WinMain(HINSTANCE hInstance, // Instance

 HINSTANCE hPrevInstance, // Previous Instance

 LPSTR lpCmdLine, // Command Line Parameters

 int nCmdShow) // Window Show State

{

 MSG msg; // Windows Message Structure

 BOOL done=FALSE; // Bool Variable To Exit Loop

 // Ask The User Which Screen Mode They Prefer

 if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start FullScreen?", MB_YESNO|MB_ICONQUESTION) == IDNO) {

  fullscreen=FALSE; // Windowed Mode

 }

 // Create Our OpenGL Window

 if (!CreateGLWindow("NeHe's Masking Tutorial", 640, 480, 16, fullscreen)) {

  return 0; // Quit If Window Was Not Created

 }

 while(!done) // Loop That Runs While done=FALSE

 {

  if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // Is There A Message Waiting?

  {

   if (msg.message == WM_QUIT) // Have We Received A Quit Message?

   {

    done=TRUE; // If So done=TRUE

   } else // If Not, Deal With Window Messages

   {

    TranslateMessage(&msg); // Translate The Message

    DispatchMessage(&msg); // Dispatch The Message

   }

  } else // If There Are No Messages

  {

   // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()

   if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?

   {

    done=TRUE; // ESC or DrawGLScene Signalled A Quit

   } else // Not Time To Quit, Update Screen

   {

    SwapBuffers(hDC); // Swap Buffers (Double Buffering)

 Now for our simple key handling code. We check to see if the spacebar is being pressed. If it is, we set the sp variable to TRUE. If sp is TRUE, the code below will not run a second time until the spacebar has been released. This keeps our program from flipping back and forth from scene to scene very rapidly. After we set sp to TRUE, we toggle the scene. If it was TRUE, it becomes FALSE, if it was FALSE it becomes TRUE. In our drawing code above, if scene is FALSE the first scene is drawn. If scene is TRUE the second scene is drawn.

    if (keys[' '] && !sp) // Is Space Being Pressed?

    {

     sp=TRUE; // Tell Program Spacebar Is Being Held