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;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值