您的位置:首页 > 理论基础

Win32+OpenGL计算机图形学光照阴影算法(参照超级宝典4改编)

2017-02-09 17:01 381 查看
#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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: