Win32+OpenGL计算机图形学光照阴影算法 可控制光源、光照物等位置的移动以及漫游等

来源:互联网 发布:淘宝上李选民书法真吗 编辑:程序博客网 时间:2024/04/29 03:01

参考opengl的第四版的阴影算法,通过好长时间的修改与研究,终于明白了opengl 的坐标系,以及矩阵的操作。接下来就来

显示下计算机图形学里的光照阴影的算法,采用再次以黑色渲染物体本身进而投影在所要求的平面上,达到一般所要求的阴影效果

#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 DrawJet(int nShadow)
{


//M3DVector3f vNormal;/*存储已经计算好的表面法向量*/



// 设置材质的颜色这里我们只需要设置为黑色表示阴影
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);


DrawJet(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来绘制阴影
DrawJet(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();
}


void SetupRC()
{



glEnable(GL_DEPTH_TEST);// 隐藏面消除;
glFrontFace(GL_CCW);// 逆时针多边形面
glEnable(GL_CULL_FACE);     // 剔除内部表面影响


// 启动光源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);


// 启用颜色跟踪
glEnable(GL_COLOR_MATERIAL);


// 设置材料属性遵循glColor值
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);


// 所有材料有全反射
glMaterialfv(GL_FRONT, GL_SPECULAR, specref);/*指定用于光照计算的当前材质属性*/
glMateriali(GL_FRONT, GL_SHININESS, 128);/*高亮显示*/


// 黑色背景
glClearColor(0.0f, 0.0f, 0.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;


// 防止被0除
if (h == 0)
h = 1;
glViewport(0, 0, w, h);
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("光照阴影算法");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutKeyboardFunc(NormalKeys);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();


return 0;
}

0 0