📄 main.cpp
字号:
#define WIN32_LEAN_AND_MEAN // trim the excess fat from Windows
/*******************************************************************
* Program: Chapter 12 OpenGL Buffers Example 3: Stencil Buffers
* Author: Kevin Hawkins
* Description: Displays rotating, texture mapped torus that is reflected in the
* checker textured floor.
********************************************************************/
////// Defines
#define BITMAP_ID 0x4D42 // the universal bitmap ID
#define PI 3.14195
////// Includes
#include <windows.h> // standard Windows app include
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gl/gl.h> // standard OpenGL include
#include <gl/glu.h> // OpenGL utilties
#include <gl/glaux.h> // OpenGL auxiliary library
////// Types
typedef struct
{
int width; // width of texture
int height; // height of texture
unsigned int texID; // the texture object id of this texture
unsigned char *data; // the texture data
} texture_t;
////// Global Variables
HDC g_HDC; // global device context
bool fullScreen = false; // true = fullscreen; false = windowed
bool keyPressed[256]; // holds true for keys that are pressed
float objectAngle = 0.0f; // object rotation angle
float angle = 0.0f; // camera angle
float radians = 0.0f; // camera angle in radians
////// Mouse/Camera Variables
int mouseX, mouseY; // mouse coordinates
float cameraX, cameraY, cameraZ; // camera coordinates
float lookX, lookY, lookZ; // camera look-at coordinates
////// Texture Information
texture_t *envTex; // environment map
texture_t *floorTex; // floor texture
// vertices for the floor
float floorData[4][3] = { { -5.0, 0.0, 5.0 }, { 5.0, 0.0, 5.0 },
{ 5.0, 0.0, -5.0 }, { -5.0, 0.0, -5.0 } };
// LoadBitmapFile
// desc: Returns a pointer to the bitmap image of the bitmap specified
// by filename. Also returns the bitmap header information.
// No support for 8-bit bitmaps.
unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
FILE *filePtr; // the file pointer
BITMAPFILEHEADER bitmapFileHeader; // bitmap file header
unsigned char *bitmapImage; // bitmap image data
int imageIdx = 0; // image index counter
unsigned char tempRGB; // swap variable
// open filename in "read binary" mode
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// read the bitmap file header
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// verify that this is a bitmap by checking for the universal bitmap id
if (bitmapFileHeader.bfType != BITMAP_ID)
{
fclose(filePtr);
return NULL;
}
// read the bitmap information header
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// move file pointer to beginning of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// allocate enough memory for the bitmap image data
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
// verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
// read in the bitmap image data
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// make sure bitmap image data was read
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
// swap the R and B values to get RGB since the bitmap color format is in BGR
for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
// close the file and return the bitmap image data
fclose(filePtr);
return bitmapImage;
}
texture_t *LoadTextureFile(char *filename)
{
BITMAPINFOHEADER texInfo;
texture_t *thisTexture;
// allocate memory for the texture structure
thisTexture = (texture_t*)malloc(sizeof(texture_t));
if (thisTexture == NULL)
return NULL;
// load the texture data and check validity
thisTexture->data = LoadBitmapFile(filename, &texInfo);
if (thisTexture->data == NULL)
{
free(thisTexture);
return NULL;
}
// set width and height info for this texture
thisTexture->width = texInfo.biWidth;
thisTexture->height = texInfo.biHeight;
// generate the texture object for this texture
glGenTextures(1, &thisTexture->texID);
return thisTexture;
}
bool LoadAllTextures()
{
// load the environment map
envTex = LoadTextureFile("waterenv.bmp");
if (envTex == NULL)
return false;
// load the floor texture
floorTex = LoadTextureFile("chess.bmp");
if (floorTex == NULL)
return false;
// setup the torus' environment map
glBindTexture(GL_TEXTURE_2D, envTex->texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, envTex->width, envTex->height, GL_RGB, GL_UNSIGNED_BYTE, envTex->data);
// setup the floor texture
glBindTexture(GL_TEXTURE_2D, floorTex->texID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, floorTex->width, floorTex->height, GL_RGB, GL_UNSIGNED_BYTE, floorTex->data);
return true;
}
void CleanUp()
{
free(envTex);
free(floorTex);
}
// Initialize
// desc: initializes OpenGL
void Initialize()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // clear to black
glShadeModel(GL_SMOOTH); // use smooth shading
glEnable(GL_CULL_FACE); // do not calculate inside of poly's
glFrontFace(GL_CCW); // counter clock-wise polygons are out
glEnable(GL_TEXTURE_2D); // enable 2D texturing
LoadAllTextures();
}
// DrawFloor()
// desc: draws the floor (one quad)
void DrawFloor()
{
glBindTexture(GL_TEXTURE_2D, floorTex->texID);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3fv(floorData[0]);
glTexCoord2f(0.0, 4.0); glVertex3fv(floorData[1]);
glTexCoord2f(4.0, 4.0); glVertex3fv(floorData[2]);
glTexCoord2f(4.0, 0.0); glVertex3fv(floorData[3]);
glEnd();
}
// DrawTorus()
// desc: draws the environment mapped torus
void DrawTorus()
{
glPushMatrix();
// setup environment mapping
glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
// bind the environment texture
glBindTexture(GL_TEXTURE_2D, envTex->texID);
// translate and rotate
glTranslatef(0.0f, 4.0f, 0.0f);
glRotatef(objectAngle, 1.0f, 1.0f, 0.0f);
glRotatef(objectAngle, 0.0f, 1.0f, 0.0f);
glRotatef(objectAngle, 0.0f, 0.0f, 1.0f);
// draw torus
auxSolidTorus(1.0f, 2.0f);
// disable texture coordinate generation
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_S);
glPopMatrix();
}
// Render
// desc: handles drawing of scene
void Render()
{
objectAngle += 0.2f; // increase object rotation angle
radians = float(PI*(angle-90.0f)/180.0f);
// calculate the camera's position
cameraX = lookX + sin(radians)*mouseY; // multiplying by mouseY makes the
cameraZ = lookZ + cos(radians)*mouseY; // camera get closer/farther away with mouseY
cameraY = lookY + mouseY / 2.0f;
// point camera at (0,0,0)
lookX = 0.0f;
lookY = 2.0f;
lookZ = 0.0f;
// clear color, depth, and stencil buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
// set the camera position
gluLookAt(cameraX, cameraY, cameraZ, lookX, lookY, lookZ, 0.0, 1.0, 0.0);
/// disable depth testing
glDisable(GL_DEPTH_TEST);
// disable modification of all color components
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// enable stencil testing
glEnable(GL_STENCIL_TEST);
// setup the stencil buffer for a function reference value
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glStencilFunc(GL_ALWAYS, 1, 1);
// draw the floor; this will set the floor pixels in the stencil buffer
// to 1, since we defined 1 as the mask value with the glStencilFunc() command
DrawFloor();
// enable modification of all color components
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// enable depth testing
glEnable(GL_DEPTH_TEST);
// make it so we can only render where the stencil buffer is equal to 1
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -