Win32+OpenGL計算機圖形學光照陰影算法(參照超級寶典4改編)

#pragma once
#include <windows.h>
#include "math3d.h"
#define GLUT_DISABLE_ATEXIT_HACK
#include <gl/glut.h>


// 旋轉變量
static float xRot = 0.0f;
static float yRot = 0.0f;
float g_cameraX=0.0, g_cameraY=2.0, g_cameraZ=10.0;


// 全局變量光照參數
float  ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };/*環境光參數*/
float  diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };/*漫反射光參數*/
float  specular[] =     { 1.0f, 1.0f, 1.0f, 1.0f };/*鏡面反射光參數*/
float  lightPos[] =     { -100.0f, 100.0f, -10.0f, 0.0f };/*光源位置*/
float  specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };/*材質屬性*/


// 聲明一個陰影轉換矩陣
M3DMatrix44f shadowMat;

////////////////////////////////////////////////
// 繪製光照物以及影子
void Draw(int nShadow)
{

// 設置材質的顏色這裏我們只需要設置爲黑色表示陰影
if (nShadow == 0)
glColor3f(1.0, 1.0, 1.0);/*非陰影時顏色設置爲白色等*/
else
glColor3f(0.2, 0.2, 0.2);/*陰影時顏色設置爲黑色*/
/*繪製實體與陰影*/
glBegin(GL_QUADS);       // 開始繪製四邊形
// 前側面
glNormal3f(0.0f, 0.0f, 1.0f);   // 法線指向觀察者
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// 後側面
glNormal3f(0.0f, 0.0f, -1.0f);   // 法線背向觀察者
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f);
// 頂面
glNormal3f(0.0f, 1.0f, 0.0f);   // 法線向上
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f);
// 底面
glNormal3f(0.0f, -1.0f, 0.0f);   // 法線朝下
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// 右側面
glNormal3f(1.0f, 0.0f, 0.0f);   // 法線朝右
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
// 左側面
glNormal3f(-1.0f, 0.0f, 0.0f);   // 法線朝左
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();            // 四邊形繪製結束


}

/*場景結果截圖*/



// 繪製場景
void RenderScene(void)
{


//地面任意三點 
M3DVector3f points[3] = { { -3.0f, -7.0f, -2.0f },
{ -3.0f, -7.0f, 2.0f },
{ 4.0f, -7.0f, 2.0f } };
// Get the plane equation from three points on the ground
M3DVector4f vPlaneEquation;
m3dGetPlaneEquation(vPlaneEquation, points[0], points[1], points[2]);


// Calculate projection matrix to draw shadow on the ground
m3dMakePlanarShadowMatrix(shadowMat, vPlaneEquation, lightPos);


glEnable(GL_NORMALIZE);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//// Move out Z axis so we can see everything
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
//glTranslatef(0, 0, 0);
//// 繪製平面即陰影體的依附平面
gluLookAt(g_cameraX, g_cameraY, g_cameraZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glPushMatrix();
glBegin(GL_QUADS);
glColor3f(0.5, 0.1, 0.8);
glVertex3f(15.0f, -5.0f, -15.0f);
glVertex3f(-15.0f, -5.0f, -15.0f);
glVertex3f(-15.0f, -5.0f, 15.0f);
glVertex3f(1.0f, -5.0f, 15.0f);
glEnd();


// 保存矩陣狀態並進行旋轉
glPushMatrix();


// 在繪製物體前將光源放在合適位置
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);


Draw(0);/*繪製物體*/
// 恢復原矩陣狀態
glPopMatrix();




// 繪製陰影與地面
// 首先關閉光照和深度測試
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glPushMatrix();


// 乘以陰影矩陣
glMultMatrixf((float *)shadowMat);


// 旋轉物體
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);


// 給予true來繪製陰影
Draw(1);


// 恢復矩陣
glPopMatrix();


// 繪製光源體
glPushMatrix();
glTranslatef(lightPos[0]/10, lightPos[1]/10, lightPos[2]/10);
glColor3ub(255, 255, 0);
glutSolidSphere(0.5f, 10, 10);
glPopMatrix();


// 開啓深度測試
glEnable(GL_DEPTH_TEST);
// 緩衝
glutSwapBuffers();
}


// This function does any needed initialization on the rendering
// context. 
void SetupRC()
{



glEnable(GL_DEPTH_TEST);// 隱藏面消除;
glFrontFace(GL_CCW);// 逆時針多邊形面
glEnable(GL_CULL_FACE);     // 剔除內部表面影響


// Setup and enable light 0
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
glEnable(GL_LIGHT0);


// Enable color tracking
glEnable(GL_COLOR_MATERIAL);


// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);


// All materials hereafter have full specular reflectivity
// with a high shine
glMaterialfv(GL_FRONT, GL_SPECULAR, specref);/*指定用於光照計算的當前材質屬性*/
glMateriali(GL_FRONT, GL_SHININESS, 128);/*高亮顯示*/


// Light blue background
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);



}


void SpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_UP)
xRot -= 5.0f;


if (key == GLUT_KEY_DOWN)
xRot += 5.0f;


if (key == GLUT_KEY_LEFT)
yRot -= 5.0f;


if (key == GLUT_KEY_RIGHT)
yRot += 5.0f;


if (key > 356.0f)
xRot = 0.0f;


if (key < -1.0f)
xRot = 355.0f;


if (key > 356.0f)
yRot = 0.0f;


if (key < -1.0f)
yRot = 355.0f;


// Refresh the Window
glutPostRedisplay();
}


void NormalKeys(unsigned char key, int x, int y)
{
switch (key) {
case VK_ESCAPE:exit(0); break;
/*攝像機移動命令*/
case 'w': g_cameraZ -= 2.0; glutPostRedisplay(); break;
case 's': g_cameraZ += 2.0; glutPostRedisplay(); break;
case 'a':lightPos[0] += 20.0; glutPostRedisplay(); break;
case 'd':lightPos[0] -= 20.0; glutPostRedisplay(); break;
default:break;


}
}


void ChangeSize(int w, int h)
{
float fAspect;


// Prevent a divide by zero
if (h == 0)
h = 1;




// Set Viewport to window dimensions
glViewport(0, 0, w, h);


// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();


fAspect = (float)w / (float)h;
gluPerspective(60.0f, fAspect, 0.1, 1000.0);


glMatrixMode(GL_MODELVIEW);


}


int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("Shadow");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutKeyboardFunc(NormalKeys);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();


return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章