光照阴影镜面反射综合算法

来源:互联网 发布:4钻淘宝店铺转让 编辑:程序博客网 时间:2024/06/02 21:02

#pragma once#include <windows.h>#include "math_3d.h"#define GLUT_DISABLE_ATEXIT_HACK#include <gl/glew.h>/*GL_BGR*/#include <gl/glut.h>#include <atlimage.h>// 全局变量光照参数float  ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };/*环境光参数*/float  diffuseLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };/*漫反射光参数*/float  specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };/*镜面反射光参数*/float  specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };/*材质镜面反射颜色属性*/float  lightPos[] = { 8.0f, 10.0f, 4.0f, 1.0f };/*光源位置*///如果我们把lightPos数组的最后一个值设为0.0,//可以使光源看上去像是来自无限远处,并沿着向量(X,Y,Z)所指定的方向射入。//这种看似来自无限远处的光源称为方向性光源,它会均匀地照射在物体的表面,//它的所有光线都是平行的, 是一种平行光。//反之,对于位置性光源,光线会从光源处向不同方向发散开来。float spotDir[] = { 0.0f, 0.0f, -1.0f };//聚光灯参数//全局变量设置// 旋转变量static float g_xRot = 0.0f;static float g_yRot = 0.0f;float g_lightPos[] = { 4.0f, 4.0f, 2.0f, 1.0f };float g_ambientLight[] = { 0.0f, 0.0f, 1.0f, 1.0f };float g_cameraX = 0.0, g_cameraY = 0.0, g_cameraZ = 40.0;unsigned int ATLLoadTexture(const char* fileName);unsigned int g_groundtex;unsigned int g_mirrorTex;void InitTexture(){g_groundtex = ATLLoadTexture("data/ground.jpg");g_mirrorTex = ATLLoadTexture("data/mirror.jpg");}//加载jpg/bmp等各种纹理返回纹理idunsigned int ATLLoadTexture(const char* fileName){BITMAP bm;GLuint idTexture = 0;CImage img;             //需要头文件atlimage.h  HRESULT hr = img.Load(fileName);if (!SUCCEEDED(hr))   //文件加载失败  {MessageBox(NULL, "文件加载失败", "ERROR", 0);return NULL;}HBITMAP hbmp = img;if (!GetObject(hbmp, sizeof(bm), &bm))return 0;glGenTextures(1, &idTexture);if (idTexture){glBindTexture(GL_TEXTURE_2D, idTexture);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);glPixelStoref(GL_PACK_ALIGNMENT, 1);glTexImage2D(GL_TEXTURE_2D, 0, 3, bm.bmWidth, bm.bmHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, bm.bmBits); //这里不是GL_RGB  }return idTexture;}// 声明一个阴影转换矩阵M3DMatrix44f shadowMat;
//截图效果
<img src="http://img.blog.csdn.net/20151021183128451?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />////////////////////////////////////////////////// 绘制光照物以及影子void DrawaScenes(int nShadow){glPushAttrib(GL_CURRENT_BIT);// 设置材质的颜色这里我们只需要设置为黑色表示阴影if (nShadow == 0)glColor3f(1.0, 1.0, 1.0);/*非阴影时颜色设置为白色等*/else{glColor3f(0.1, 0.1, 0.1);/*阴影时颜色设置为黑色*//*绘制还要镜面反射的球体阴影*/glPushMatrix();glPushAttrib(GL_CURRENT_BIT);glTranslatef(g_yRot, g_xRot, 4);//物体位置glutSolidSphere(0.3, 20, 20);glPopMatrix();glPopAttrib();}/*绘制实体与阴影*/glPushMatrix();glTranslatef(-10.0, -5.0, 0.0);glScalef(0.5, 0.5, 0.5);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();            // 四边形绘制结束//glPopMatrix();/*绘制一个三角形*/glPushMatrix();glTranslatef(-8, 0.0, -2.0);glBegin(GL_TRIANGLES);glVertex3f(0.0, 0.0, -1.0);glVertex3f(-1.0, 0.0, 1.0);glVertex3f(1.0, 0.0, 1.0);glEnd();glTranslatef(-5.0, 0.0, 0.0);//glEnable(GL_TEXTURE_2D);//glBindTexture(GL_TEXTURE_2D, g_groundtex);glutSolidSphere(3.0, 20, 20);//glDisable(GL_TEXTURE_2D);glPopMatrix();glPopAttrib();}//绘制球体的函数void drawSphere(){glEnable(GL_LIGHTING);glPushMatrix();glPushAttrib(GL_CURRENT_BIT);glColor3f(0.0, 0.5, 0.8);glTranslatef(g_yRot, g_xRot, 4);//物体位置glutSolidSphere(0.3, 20, 20);glPopMatrix();glPopAttrib();glDisable(GL_LIGHTING);}// 绘制场景void RenderScene(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();glTranslatef(0.0, 0.0, 0.0);//// 移动z轴坐标系看到前面的一切东西glLightfv(GL_LIGHT0, GL_POSITION, lightPos);/*实时改变光源的位置*///glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDir);/*聚光灯效果*///glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 60.0f);gluLookAt(g_cameraX, g_cameraY, g_cameraZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);//地面任意三点 M3DVector3f points[3] = { { -3.0f, -10.0f, -2.0f },{ -3.0f, -10.0f, 2.0f },{ 4.0f, -10.0f, 2.0f } };// 从三点得到的平面方程M3DVector4f vPlaneEquation;m3dGetPlaneEquation(vPlaneEquation, points[0], points[1], points[2]);// 计算投影在一个平面上的阴影矩阵m3dMakePlanarShadowMatrix(shadowMat, vPlaneEquation, lightPos);//glEnable(GL_NORMALIZE);glPushMatrix();//绘制平面即阴影体的依附平面glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, g_groundtex);float lenghtGround = 80.0;//地面长宽度float heightGround = -11.0;glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f); glVertex3f(-lenghtGround, heightGround, -lenghtGround);// 纹理和四边形的左下glTexCoord2f(1.0f, 0.0f); glVertex3f(-lenghtGround, heightGround, lenghtGround);// 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(lenghtGround, heightGround, lenghtGround);    // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(lenghtGround,heightGround, -lenghtGround);// 纹理和四边形的左上glEnd();glDisable(GL_TEXTURE_2D);glPopMatrix();// 保存矩阵状态并进行旋转glPushMatrix();// 在绘制物体前将光源放在合适位置glEnable(GL_LIGHTING);glRotatef(g_xRot, 1.0f, 0.0f, 0.0f);glRotatef(g_yRot, 0.0f, 1.0f, 0.0f);DrawaScenes(0);/*绘制物体*/// 恢复原矩阵状态glPopMatrix();//// 绘制阴影与地面//// 首先关闭光照和深度测试glDisable(GL_DEPTH_TEST);glDisable(GL_LIGHTING);glPushMatrix();// 绘制光源体glPushMatrix();glTranslatef(lightPos[0], lightPos[1], lightPos[2]);glColor3f(1.0, 0.0, 0.0);glutSolidSphere(0.5f, 20, 20);glPopMatrix();glEnable(GL_DEPTH_TEST);glDisable(GL_STENCIL_TEST);drawSphere();glClearStencil(0x0);glClear(GL_STENCIL_BUFFER_BIT);glStencilFunc(GL_ALWAYS, 1, 0xFF);glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);glEnable(GL_STENCIL_TEST);glDisable(GL_LIGHTING);/*绘制平面镜子*/glPushMatrix();glPushAttrib(GL_CURRENT_BIT);glColor3f(1.0f, 1.0f, 1.0f);glDepthMask(GL_FALSE);//设置深度缓冲区为只读glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, g_mirrorTex);float lengthMirror = 10.0;//镜子长宽glBegin(GL_QUADS);//前面glTexCoord2f(0.0f, 0.0f); glVertex3f(-lengthMirror, -lengthMirror, -2.0f);// 纹理和四边形的左下glTexCoord2f(1.0f, 0.0f); glVertex3f(lengthMirror, -lengthMirror, -2.0f);// 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(lengthMirror, lengthMirror, -2.0f);    // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(-lengthMirror, lengthMirror, -2.0f);// 纹理和四边形的左上glEnd();glDisable(GL_TEXTURE_2D);glPopMatrix();glPopAttrib();/*绘制光源体*/glPushMatrix();glTranslatef(lightPos[0], lightPos[1], lightPos[2]);glColor3f(1.0, 1.0, 1.0);glutSolidSphere(0.1f, 20, 20);glPopMatrix();//// 乘以阴影矩阵glMultMatrixf((float *)shadowMat);//// 旋转物体glRotatef(g_xRot, 1.0f, 0.0f, 0.0f);glRotatef(g_yRot, 0.0f, 1.0f, 0.0f);// 给予true来绘制阴影DrawaScenes(1);// 恢复矩阵glPopMatrix();glDepthMask(GL_TRUE);//重新启用深度缓冲区///明确说明函数的测试功能GL_NEVER,,GL_LESS, GL_LEQUAL,//GL_GREATER, GL_GEQUAL,,GL_EQUAL, GL_NOTEQUAL和 GL_ALWAYS。//初始化的值是GL_ALWAYS//ref//明确说明该模板测试的引用值。 ref 值被限制在0~2 ^ (n - 1)间,//其中n是模板缓存中位平面数。初始化值是0//mask//该参数表示一个模板,用来和ref值以及存储的模板值做与运算。初始化值是全1//要允许或禁止该测试的话,使用glEnable(GL_STENCIL_TEST)或glDisable(GL_STENCIL_TEST)glStencilFunc(GL_EQUAL, 1, 0xFF);//0xff==255//glStencilOp函数,它用来根据比较结果修改蒙板缓存区中的值//sfail当蒙板测试失败时所执行的操作//zfail当蒙板测试通过,深度测试失败时所执行的操作//zpass当蒙板测试通过,深度测试通过时所执行的操作glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);glScalef(1.0f, 1.0f, -1.0f);//镜子里的影子方向取反glPushAttrib(GL_CURRENT_BIT);drawSphere();glPopAttrib();glDisable(GL_STENCIL_TEST);glDepthMask(true);//重新启用深度缓冲区glutSwapBuffers();}void SetupRC(){InitTexture();/*初始化图片纹理*/glShadeModel(GL_SMOOTH);glEnable(GL_DEPTH_TEST);// 隐藏面消除;glFrontFace(GL_CCW);// 逆时针多边形面glEnable(GL_CULL_FACE);     // 剔除内部表面影响// 启动光源0glLightfv(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)g_xRot -= 1.0f;if (key == GLUT_KEY_DOWN)g_xRot += 1.0f;if (key == GLUT_KEY_LEFT)g_yRot -= 1.0f;if (key == GLUT_KEY_RIGHT)g_yRot += 1.0f;// Refresh the WindowglutPostRedisplay();}void NormalKeys(unsigned char key, int x, int y){switch (key) {case VK_ESCAPE:exit(0); break;/*摄像机移动命令*/case 'w': g_cameraZ -= 1.0; glutPostRedisplay(); break;case 's': g_cameraZ += 1.0; glutPostRedisplay(); break;case 'a':lightPos[0] += 2.0; glutPostRedisplay(); break;case 'd':lightPos[0] -= 2.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, 2000.0);glMatrixMode(GL_MODELVIEW);}int main(int argc, char* argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL);glutInitWindowSize(1366, 768);glutCreateWindow("LightShadowMirrorReflect");glutReshapeFunc(ChangeSize);glutSpecialFunc(SpecialKeys);glutKeyboardFunc(NormalKeys);glutDisplayFunc(RenderScene);SetupRC();glutMainLoop();return 0;}

光照阴影镜面反射综合算法:


0 0
原创粉丝点击