📄 refshad.cpp
字号:
Deletes the DC, RC, and Window, and restores the original display.
*****************************************************************************/
BOOL KillWindow()
{
// restore the original display if we're in fullscreen mode
if (g_isFullscreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(TRUE);
}
// if we have an RC, release it
if (g_hrc)
{
// release the RC
if (!wglMakeCurrent(NULL,NULL))
{
MessageBox(NULL, "Unable to release rendering context", "Error", MB_OK | MB_ICONINFORMATION);
}
// delete the RC
if (!wglDeleteContext(g_hrc))
{
MessageBox(NULL, "Unable to delete rendering context", "Error", MB_OK | MB_ICONINFORMATION);
}
g_hrc = NULL;
}
// release the DC if we have one
if (g_hdc && !ReleaseDC(g_hwnd, g_hdc))
{
MessageBox(NULL, "Unable to release device context", "Error", MB_OK | MB_ICONINFORMATION);
g_hdc = NULL;
}
// destroy the window if we have a valid handle
if (g_hwnd && !DestroyWindow(g_hwnd))
{
MessageBox(NULL, "Unable to destroy window", "Error", MB_OK | MB_ICONINFORMATION);
g_hwnd = NULL;
}
// unregister our class so we can create a new one if we need to
if (!UnregisterClass(WND_CLASS_NAME, g_hInstance))
{
MessageBox(NULL, "Unable to unregister window class", "Error", MB_OK | MB_ICONINFORMATION);
g_hInstance = NULL;
}
return TRUE;
} // end KillWindow()
/*****************************************************************************
ResizeScene()
Called once when the application starts and again every time the window is
resized by the user.
*****************************************************************************/
GLvoid ResizeScene(GLsizei width, GLsizei height)
{
// avoid divide by zero
if (height==0)
{
height=1;
}
// set the viewport to the new dimensions
glViewport(0, 0, width, height);
// select the projection matrix and clear it out
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// set the perspective with the appropriate aspect ratio
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 1.0f, 100.0f);
// select modelview matrix
glMatrixMode(GL_MODELVIEW);
} // end ResizeScene()
/*****************************************************************************
InitializeScene()
Performs one-time application-specific setup. Returns FALSE on any failure.
*****************************************************************************/
BOOL InitializeScene()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
// set up a single white light
GLfloat lightColor[] = { 1.0f, 1.0f, 1.0f, 1.0 };
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightColor);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
LoadTexture("marble.bmp", g_marbleTexture);
LoadTexture("gdlogo.bmp", g_cubeTexture);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
g_timer.Init();
float plane[4] = { 0.0, 1.0, 0.0, 0.0 };
SetShadowMatrix(g_shadowMatrix, g_lightPos, plane);
return TRUE;
} // end InitializeScene()
/*****************************************************************************
DisplayScene()
The work of the application is done here. This is called every frame, and
handles the actual rendering of the scene.
*****************************************************************************/
BOOL DisplayScene()
{
// set up the view orientation
glLoadIdentity();
gluLookAt(0.0, 3.0, 10.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
// clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// rotate the scene
g_rotationAngle += (DEGREES_PER_SECOND * g_timer.GetElapsedSeconds());
glRotated(-g_rotationAngle/8.0, 0.0, 1.0, 0.0);
glRotated(10.0 * sin(g_rotationAngle/45.0), 1.0, 0.0, 0.0);
// prepare to write to the stencil buffer by turning off writes to the
// color and depth buffer
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
// set up the stencil func and op to place a 1 in the stencil buffer
// everywhere we're about to draw
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
// render the surface. Since the depth and color buffers are disabled,
// only the stencil buffer will be modified
DrawSurface();
// turn the color and depth buffers back on
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
// from this point until the stencil test is disabled, only draw where
// the stencil buffer is set to 1
glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
// don't modify the contents of the stencil buffer
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// draw the reflected cube first
glPushMatrix();
glScalef(1.0, -1.0, 1.0);
glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);
DrawCube();
glPopMatrix();
// draw the surface normally, blending it with the reflected cube
glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);
glEnable(GL_BLEND);
DrawSurface();
glDisable(GL_BLEND);
// draw the shadow
glPushMatrix();
// draw the shadow as black, blended with the surface, with no lighting, and not
// preforming the depth test
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
// make sure that we don't draw at any raster position more than once
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
glColor4f(0.0, 0.0, 0.0, 0.5f);
// project the cube through the shadow matrix
glMultMatrixf(g_shadowMatrix);
DrawCube();
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glEnable(GL_LIGHTING);
glPopMatrix();
glDisable(GL_STENCIL_TEST);
// draw the cube normally
glPushMatrix();
DrawCube();
glPopMatrix();
return TRUE;
} // end DisplayScene()
/*****************************************************************************
Cleanup()
Called at the end of successful program execution.
*****************************************************************************/
BOOL Cleanup()
{
glDeleteTextures(1, &g_marbleTexture);
glDeleteTextures(1, &g_cubeTexture);
return TRUE;
} // end Cleanup()
/****************************************************************************
DrawCube()
Draws the rotating cube
*****************************************************************************/
void DrawCube()
{
// set the color of the cube's surface
GLfloat cubeColor[] = { 1.0f, 1.0f, 1.0f, 1.0 };
glMaterialfv(GL_FRONT, GL_SPECULAR, cubeColor);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cubeColor);
glMaterialf(GL_FRONT, GL_SHININESS, 50.0);
glTranslatef(0.0, 2.0, 0.0);
glRotatef(g_rotationAngle, 1.0, 0.5, 1.0);
// set up the cube's texture
glBindTexture(GL_TEXTURE_2D, g_cubeTexture);
// the cube will just be drawn as six quads for the sake of simplicity
// for each face, we specify the quad's normal (for lighting), then
// specify the quad's 4 vertices and associated texture coordinates
glBegin(GL_QUADS);
// front
glNormal3f(0.0, 0.0, 1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
// back
glNormal3f(0.0, 0.0, -1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, -1.0);
// top
glNormal3f(0.0, 1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, 1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
// bottom
glNormal3f(0.0, -1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, -1.0, 1.0);
// left
glNormal3f(-1.0, 0.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
// right
glNormal3f(1.0, 0.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 1.0);
glEnd();
} // end DrawCube()
/****************************************************************************
DrawSurface()
Draws a simple plane to provide a reflection surface.
*****************************************************************************/
void DrawSurface()
{
// set up the surface's color
GLfloat surfaceColor[] = { 1.0f, 1.0f, 1.0f, 0.6f };
glMaterialfv(GL_FRONT, GL_SPECULAR, surfaceColor);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, surfaceColor);
glMaterialf(GL_FRONT, GL_SHININESS, 200.0);
// set up blending so we can see the reflected cube through the
// surface, and thus create the illusion of reflection
glBindTexture(GL_TEXTURE_2D, g_marbleTexture);
glBegin(GL_QUADS);
glNormal3f(0.0, 1.0, 0.0);
// to have lighting effects show up at all, we need to draw the
// surface as a lot of quads, not just one
GLfloat x = -5.0, z = -5.0;
for (GLint i = 0; i < 10; i++, x += 1.0)
{
for (GLint j = 0; j < 10; j++, z += 1.0)
{
// draw the plane slightly offset so the shadow shows up
glTexCoord2f(0.0, 0.0);
glVertex3f(x, 0.0, z);
glTexCoord2f(1.0, 0.0);
glVertex3f(x + 1.0f, 0.0, z);
glTexCoord2f(1.0, 1.0);
glVertex3f(x + 1.0f, 0.0, z + 1.0f);
glTexCoord2f(0.0, 1.0);
glVertex3f(x, 0.0, z + 1.0f);
}
z = -5.0;
}
glEnd();
} // end DrawSurface()
/****************************************************************************
LoadTexture()
Loads the texture from the specified file and stores it in iTexture.
*****************************************************************************/
void LoadTexture(char *filename, GLuint &texture)
{
// get a texture object
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// load the bitmap
BITMAPINFOHEADER bitmapInfoHeader;
unsigned char *buffer = LoadBitmapFile(filename, &bitmapInfoHeader);
// set up the texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
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, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
// we're done with the bitmap data
free(buffer);
} // end LoadTexture()
/****************************************************************************
SetShadowMatrix()
Calculates the shadow projection matrix based on the light position and plane
*****************************************************************************/
void SetShadowMatrix(GLfloat destMat[16], float lightPos[4], float plane[4])
{
GLfloat dot;
// dot product of plane and light position
dot = plane[0] * lightPos[0] + plane[1] * lightPos[1] + plane[1] * lightPos[2] + plane[3] * lightPos[3];
// first column
destMat[0] = dot - lightPos[0] * plane[0];
destMat[4] = 0.0f - lightPos[0] * plane[1];
destMat[8] = 0.0f - lightPos[0] * plane[2];
destMat[12] = 0.0f - lightPos[0] * plane[3];
// second column
destMat[1] = 0.0f - lightPos[1] * plane[0];
destMat[5] = dot - lightPos[1] * plane[1];
destMat[9] = 0.0f - lightPos[1] * plane[2];
destMat[13] = 0.0f - lightPos[1] * plane[3];
// third column
destMat[2] = 0.0f - lightPos[2] * plane[0];
destMat[6] = 0.0f - lightPos[2] * plane[1];
destMat[10] = dot - lightPos[2] * plane[2];
destMat[14] = 0.0f - lightPos[2] * plane[3];
// fourth column
destMat[3] = 0.0f - lightPos[3] * plane[0];
destMat[7] = 0.0f - lightPos[3] * plane[1];
destMat[11] = 0.0f - lightPos[3] * plane[2];
destMat[15] = dot - lightPos[3] * plane[3];
} // end SetShadowMatrix()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -