3D+OpenGL里的光照平面镜面反射以及漫游移动物体位置等的具体实现

来源:互联网 发布:网络营销是什么软件 编辑:程序博客网 时间:2024/05/17 04:02

3D+OpenGL里的光照平面镜面反射以及漫游移动物体位置等的具体实现

在实现过程中涉及到

1.opengl里的蒙版缓冲等相关知识

2.观察坐标系的转换摄像漫游等

3.此外图中的mirror图片为导入的mirror.jpg文件

4.在纹理贴图中

unsigned int ATLLoadTexture(const char* fileName)函数实现了jpg/bmp等图片的加载<pre name="code" class="cpp">//加载jpg/bmp等各种纹理返回纹理id

#define GLUT_DISABLE_ATEXIT_HACK #include <gl/glew.h>/*GL_BGR*/#include <atlimage.h>#include <GL/glut.h>//全局变量设置// 旋转变量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 = 10.0;unsigned int g_mirrorTex;//加载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;}void init(){glClearColor(0.0, 0.0, 0.0, 0.0);glShadeModel(GL_SMOOTH);g_mirrorTex = ATLLoadTexture("data/mirror.jpg");}//绘制球体的函数void drawSphere(){//光源设置glEnable(GL_LIGHT0);glEnable(GL_LIGHTING);glEnable(GL_COLOR_MATERIAL);glLightfv(GL_LIGHT0, GL_POSITION, g_lightPos);glLightfv(GL_LIGHT0, GL_AMBIENT, g_ambientLight);glPushMatrix();glPushAttrib(GL_CURRENT_BIT);glColor3f(0.0, 0.5,0.8);glTranslatef(g_xRot, g_yRot, 4);//物体位置glutSolidSphere(0.3, 20, 20);glPopMatrix();glPopAttrib();}void display(){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//设置观察点glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60, 1, 0.1, 500);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(g_cameraX,g_cameraY,g_cameraZ, 0, 0, 0, 0, 1, 0);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);glBegin(GL_QUADS);//前面glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.0f, -2.0f, 1.0f);// 纹理和四边形的左下glTexCoord2f(1.0f, 0.0f); glVertex3f(2.0f, -2.0f, 1.0f);// 纹理和四边形的右下glTexCoord2f(1.0f, 1.0f); glVertex3f(2.0f, 2.0f, 1.0f);    // 纹理和四边形的右上glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.0f, 2.0f, 1.0f);// 纹理和四边形的左上glEnd();glDisable(GL_TEXTURE_2D);glPopMatrix();glPopAttrib();/*绘制光源体*/glPushMatrix();glTranslatef(g_lightPos[0], g_lightPos[1], g_lightPos[2]);glColor3f(1.0, 1.0, 1.0);glutSolidSphere(0.1f, 20, 20);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();glutSwapBuffers();}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': g_cameraX += 1.0; glutPostRedisplay(); break;case 'd': g_cameraX -= 1.0; glutPostRedisplay(); break; default:break;}}void SpecialKeys(int key, int x, int y){if (key == GLUT_KEY_UP)g_yRot += 0.1f;if (key == GLUT_KEY_DOWN)g_yRot -= 0.1f;if (key == GLUT_KEY_LEFT)g_xRot -= 0.1f;if (key == GLUT_KEY_RIGHT)g_xRot += 0.1f;// Refresh the WindowglutPostRedisplay();}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_STENCIL | GLUT_DEPTH);glutInitWindowSize(1376, 768);glutInitWindowPosition(0, 0);glutCreateWindow("镜面反射");init();glutDisplayFunc(display);//glutReshapeFunc(reshape);glutKeyboardFunc(NormalKeys);glutSpecialFunc(SpecialKeys);glutMainLoop();return 0;}
镜面反射实现的结果截图:



0 0
原创粉丝点击