⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 refshad.cpp

📁 一本关于OPenGL的很好的电子书
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 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 + -