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;
}
#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;
}
相关文章推荐
- Win32+OpenGL计算机图形学光照阴影算法 可控制光源、光照物等位置的移动以及漫游等
- OpenGL光照阴影算法的实现
- openGL 超级宝典第五版学习 第一个程序
- 学习opengl(一)opengl 超级宝典 第5版 vs2013+opengl配置
- OpenGL: 阴影算法
- [OpenGL学习] openGL超级宝典 无法打开文件“freeglut_static.lib”
- OpenGL超级宝典笔记二 - 基础变换
- OpenGL超级宝典 5e 环境配置
- OpenGL(3)超级宝典笔记——GLSL语言基础
- 《OpenGL 超级宝典(Super Bible)第七版》 有关 PBO 的 Example
- OpenGL 4.0 GLSL 用 shadow map 算法 生成阴影
- 【转载】OpenGL超级宝典笔记——GLSL语言基础
- opengl超级宝典中例子出现的问题
- [OpenGL 超级宝典][笔记] 8.2 帧缓冲区(FBO)
- Opengl超级宝典 Xcode环境配置
- 【OpenGL超级宝典第五版】【第二章】OpenGL入门指南 读书笔记
- Ubuntu下搭建OpenGL超级宝典源码环境
- 抗锯齿 多重采样 opengl超级宝典
- 遮挡查询 OpenGL超级宝典 第十七章
- OpenGL 3D 超级宝典学习笔记