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

* DOWNLOAD Visual C++ / OpenIL Code For This Lesson. (Conversion by Denton Woods)

* DOWNLOAD Visual Basic Code For This Lesson. (Conversion by Edo

Lesson 20

Welcome to Tutorial 20. The bitmap image format is supported on just about every computer, and just about every operating system. Not only is it easy to work with, it's very easy to load and use as a texture. Up until now, we've been using blending to place text and other images onto the screen without erasing what's underneath the text or image. This is effective, but the results are not always pretty.

Most the time a blended texture blends in too much or not enough. When making a game using sprites, you don't want the scene behind your character shining through the characters body. When writing text to the screen you want the text to be solid and easy to read.

That's where masking comes in handy. Masking is a two step process. First we place a black and white image of our texture on top of the scene. The white represents the transparent part of our texture. The black represents the solid part of our texture. Because of the type of blending we use, only the black will appear on the scene. Almost like a cookie cutter effect. Then we switch blending modes, and map our texture on top of the black cut out. Again, because of the blending mode we use, the only parts of our texture that will be copied to the screen are the parts that land on top of the black mask.

I'll rewrite the entire program in this tutorial aside from the sections that haven't changed. So if you're ready to learn something new, let's begin!

#include <windows.h> // Header File For Windows

#include <math.h> // Header File For Windows Math Library

#include <stdio.h> // Header File For Standard Input/Output

#include <gl\gl.h> // Header File For The OpenGL32 Library

#include <gl\glu.h> // Header File For The GLu32 Library

#include <gl\glaux.h> // Header File For The Glaux Library

HDC hDC=NULL; // Private GDI Device Context

HGLRC hRC=NULL; // Permanent Rendering Context

HWND hWnd=NULL; // Holds Our Window Handle

HINSTANCE hInstance; // Holds The Instance Of The Application

We'll be using 7 global variables in this program. masking is a boolean variable (TRUE / FALSE) that will keep track of whether or not masking is turned on of off. mp is used to make sure that the 'M' key isn't being held down. sp is used to make sure that the 'Spacebar' isn't being held down and the variable scene will keep track of whether or not we're drawing the first or second scene.

We set up storage space for 5 textures using the variable texture[5]. loop is our generic counter variable, we'll use it a few times in our program to set up textures, etc. Finally we have the variable roll. We'll use roll to roll the textures across the screen. Creates a neat effect! We'll also use it to spin the object in scene 2.

bool keys[256]; // Array Used For The Keyboard Routine

bool active=TRUE; // Window Active Flag Set To TRUE By Default

bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default

bool masking=TRUE; // Masking On/Off

bool mp; // M Pressed?

bool sp; // Space Pressed?

bool scene; // Which Scene To Draw

GLuint texture[5]; // Storage For Our Five Textures

GLuint loop; // Generic Loop Variable

GLfloat roll; // Rolling Texture

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc

The load bitmap code hasn't changed. It's the same as it was in lesson 6, etc.

In the code below we create storage space for 5 images. We clear the space and load in all 5 bitmaps. We loop through each image and convert it into a texture for use in our program. The textures are stored in texture[0-4].

int LoadGLTextures() // Load Bitmaps And Convert To Textures

{

 int Status=FALSE; // Status Indicator

 AUX_RGBImageRec *TextureImage[5]; // Create Storage Space For The Texture Data

 memset(TextureImage, 0, sizeof(void *)*5); // Set The Pointer To NULL

 if ((TextureImage[0]=LoadBMP("Data/logo.bmp")) && // Logo Texture

  (TextureImage[1]=LoadBMP("Data/mask1.bmp")) && // First Mask

  (TextureImage[2]=LoadBMP("Data/image1.bmp")) && // First Image

  (TextureImage[3]=LoadBMP("Data/mask2.bmp")) && // Second Mask

  (TextureImage[4]=LoadBMP("Data/image2.bmp"))) // Second Image

 {

  Status=TRUE; // Set The Status To TRUE

  glGenTextures(5, &texture[0]); // Create Five Textures

  for (loop=0; loop<5; loop++) // Loop Through All 5 Textures

  {

   glBindTexture(GL_TEXTURE_2D, texture[loop]);

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

   glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data);

  }

 }

 for (loop=0; loop<5; loop++) // Loop Through All 5 Textures

 {

  if (TextureImage[loop]) // If Texture Exists

  {

   if (TextureImage[loop]->data) // If Texture Image Exists

   {

    free(TextureImage[loop]->data); // Free The Texture Image Memory

   }

   free(TextureImage[loop]); // Free The Image Structure

  }

 }

 return Status; // Return The Status

}

The ReSizeGLScene() code hasn't changed so we'll skip over it.

The Init code is fairly bare bones. We load in our textures, set the clear color, set and enable depth testing, turn on smooth shading, and enable texture mapping. Simple program so no need for a complex init :)

int InitGL(GLvoid) // All Setup For OpenGL Goes Here

{

 if (!LoadGLTextures()) // Jump To Texture Loading Routine

 {

  return FALSE; // If Texture Didn't Load Return FALSE

 }

 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Clear The Background Color To Black

 glClearDepth(1.0); // Enables Clearing Of The Depth Buffer

 glEnable(GL_DEPTH_TEST); // Enable Depth Testing

 glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading

 glEnable(GL_TEXTURE_2D); // Enable 2D Texture Mapping

 return TRUE; // Initialization Went OK

}

Now for the fun stuff. Our drawing code! We start off the same as usual. We clear the background color and the depth buffer. Then we reset the modelview matrix, and translate into the screen 2 units so that we can see our scene.