VS2010下OPENGL的配置使用

来源:互联网 发布:淘宝店铺装修设计师 编辑:程序博客网 时间:2024/06/05 11:47

工作后一直跟opencv打交道,各种版本各种配置也早就用烂了。忽然想到还有个专业的图形程序接口一直没用过,然后就在网上找了一个并down个程序简单看看效果。这里主要是写一下openGL下载、配置以及写程序时要注意的一些东西吧。

首先下载openGL的压缩文件http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip

里面5个文件 glut.h  glut.dll,glut32.dll glut.lib,glut32.lib,至于这些东西放哪就不多说了,随便百度一下就有。

但我down的那个程序中需要包含一个头文件#include "glaux.h",这是GLAUX库的头文件,这个文件在我电脑上毫无踪影,没办法只好有下了一个OpenGL的版本:

http://d.download.csdn.net/download/ssagnn23/2560229


然后把解压的.h、.dll、.lib文件又重新归置了一次,这下可以找到头文件了,然后编译时又遇到问题:“无法解析的外部符号 _auxDIBImageLoadA……”,查了一下是没有加入lib。打开“工程属性”-->"输入"-->"附加依赖项",把OpenGL32.lib  GLu32.lib  GLaux.lib加进去,编译运行OK,然后可以看到程序运行效果。(程序里加载的图像貌似只能是24位bmp图像,没有验证,jpg肯定不行)

#include <iostream>#define GLUT_DISABLE_ATEXIT_HACK#include "gl\glut.h"#include "gl\GLAUX.H" using namespace std;bool g_bBlend;//  是否混合?bool g_bKeyB = false;// B 键按下了么?bool    g_bLight=false;//  光源的开/ 关bool    g_bKeyL=false;// L键按下了么?bool    g_bKeyF=false;// F键按下了么?GLfloat g_fXrot=5;// X 旋转GLfloat g_fYrot=5;// Y 旋转GLfloat g_fXSpeed=0;// X 旋转速度GLfloat g_fYSpeed=0;// Y 旋转速度GLfloat g_fZ=-5.0f;//  深入屏幕的距// 接着设置用来创建光源的数组。我们将使用两种不同的光。第一种称为环境光。环境光来自于四面// 八方。所有场景中的对象都处于环境光的照射中。第二种类型的光源叫做漫射光。漫射光由特定的// 光源产生,并在您的场景中的对象表面上产生反射。处于漫射光直接照射下的任何对象表面都变得// 很亮,而几乎未被照射到的区域就显得要暗一些。这样在我们所创建的木板箱的棱边上就会产生的很不错的阴影效果。// 创建光源的过程和颜色的创建完全一致。前三个参数分别是RGB三色分量,最后一个是alpha通道参数。// 因此,下面的代码我们得到的是半亮(0.5f)的白色环境光。如果没有环境光,未被漫射光照到的地方会变得十分黑暗。GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };//  环境光参数//下一行代码我们生成最亮的漫射光。所有的参数值都取成最大值1.0f 。它将照在我们木板箱的前面,看起来挺好。GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };//  漫射光参数// 最后我们保存光源的位置。前三个参数和glTranslate中的一样。依次分别是XYZ轴上的位移。由于// 我们想要光线直接照射在木箱的正面,所以XY轴上的位移都是0.0f 。第三个值是Z 轴上的位移。为// 了保证光线总在木箱的前面,所以我们将光源的位置朝着观察者( 就是您哪。) 挪出屏幕。我们通常// 将屏幕也就是显示器的屏幕玻璃所处的位置称作Z 轴的0.0f 点。所以Z 轴上的位移最后定为2.0f 。假// 如您能够看见光源的话,它就浮在您显示器的前方。当然,如果木箱不在显示器的屏幕玻璃后面的// 话,您也无法看见箱子。GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };//  光源位置// filter 变量跟踪显示时所采用的纹理类型。//第一种纹理(texture[0])使用gl_nearest(不光滑) 滤波方式构建。//第二种纹理 (texture[1])使用gl_linear(线性滤波)方式,离屏幕越近的图像看起来就越光滑。//第三种纹理 (texture[2])使用mipmapped滤波方式,这将创建一个外观十分优秀的纹理。//根据我们的使用类型,filter 变量的值分别等于0,1或2。下面我们从第一种纹理开始。//GLuint texture[3] 为三种不同纹理分配储存空间。它们分别位于在 texture[0], texture[1]和texture[2] 中。GLuint  filter;// 滤波类型GLuint  texture[3]; // 3种纹理的储存空间//现在载入一个位图,并用它创建三种不同的纹理。这一课使用glaux辅助库来载入位图,因此在编译//时您应该确认是否包含了glaux库。我知道Delphi 和VC++都包含了glaux库,但别的语言不能保证都//有。『译者注:glaux是OpenGL辅助库,根据OpenGL的跨平台特性,所有平台上的代码都应通用。//但辅助库不是正式的OpenGL标准库,没有出现在所有的平台上。但正好在Win32平台上可用。AUX_RGBImageRec *TextureImage=new AUX_RGBImageRec;//辅助函数AUX_RGBImageRec *LoadBMP(char* FileName){FILE *file = 0;if(!FileName)return 0;file = fopen(FileName,"r");if(file){fclose(file);cout<<"start open!";return auxDIBImageLoad(FileName);//如果此处出现Fail to open DIB是字符串的问题//修改项目配置,字符集中将Unicode改成多级字符即可}return 0;}void LoadTexture(){//图像的宽和高必须是2的n次方memset(TextureImage,0,sizeof(void *)*1);//现在载入位图,并将其转换为纹理。TextureImage = LoadBMP("E:\\pic\\2.bmp");if(0 == TextureImage){cout<<"error bmp"<<endl;return;}//告诉OpenGL我们要创建三个纹理,它们将存放在texture[0],texture[1]和texture[2]中glGenTextures(3,&texture[0]);//第六课中我们使用了线性滤波的纹理贴图。这需要机器有相当高的处理能力,但它们看起来很不//错。这一课中,我们接着要创建的第一种纹理使用 GL_NEAREST 方式。从原理上讲,这种方式没//有真正进行滤波。它只占用很小的处理能力,看起来也很差。唯一的好处是这样我们的工程在很快//和很慢的机器上都可以正常运行。//您会注意到我们在 MIN  和 MAG  时都采用了GL_NEAREST,你可以混合使用 GL_NEAREST和//GL_LINEAR。纹理看起来效果会好些,但我们更关心速度,所以全采用低质量贴//图。MIN_FILTER在图像绘制时小于贴图的原始尺寸时采用。MAG_FILTER在图像绘制时大于贴图//的原始尺寸时采用。//###创建 Nearest 滤波贴图###glBindTexture(GL_TEXTURE_2D, texture[0]);  // 告诉OpenGL将纹理名字texture绑定到纹理目标上。glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage->sizeX, TextureImage->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);//###创建线性滤波纹理###glBindTexture(GL_TEXTURE_2D, texture[1]);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage->sizeX, TextureImage->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);//glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);//下面是创建纹理的新方法。 Mipmapping!//您可能会注意到当图像在屏幕上变得很小的时候,很多细节将会//丢失。刚才还很不错的图案变得很难看。当您告诉OpenGL创建一个 mipmapped 的纹理//后,OpenGL将尝试创建不同尺寸的高质量纹理。当您向屏幕绘制一个 mipmapped 纹理的时//候,OpenGL将选择它已经创建的外观最佳的纹理( 带有更多细节) 来绘制,而不仅仅是缩放原先的图//像( 这将导致细节丢失) 。//我曾经说过有办法可以绕过OpenGL对纹理宽度和高度所加的限制——64、128、256,等等。//办法就是 gluBuild2DMipmaps 。据我的发现,您可以使用任意的位图来创建纹理。OpenGL将自动将它缩放到正常的大小。//因为是第三个纹理,我们将它存到texture[2] 。这样本课中的三个纹理全都创建好了。glBindTexture(GL_TEXTURE_2D,texture[2]);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);//下面一行生成 mipmapped 纹理。gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage->sizeX, TextureImage->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);//释放前面用来存放位图数据的内存if(TextureImage){if(TextureImage->data){free(TextureImage->data);}free(TextureImage);}}void DrawScene(void){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除屏幕及其缓存glLoadIdentity();//重置当前模型观察矩阵glTranslatef(0.0f,0.0f,g_fZ);  //  移入/ 移出屏幕glRotatef(g_fXrot,1.0f,0.0f,0.0f);//  绕X轴旋转glRotatef(g_fYrot,0.0f,1.0f,0.0f);//  绕Y轴旋转g_fXrot += g_fXSpeed;g_fYrot += g_fYSpeed;// 下一行代码选择我们使用的纹理。如果您在您的场景中使用多个纹理,您应该使用来// glBindTexture(GL_TEXTURE_2D, texture[ 所使用纹理对应的数字 ]) 选择要绑定的纹理。当您想改变// 纹理时,应该绑定新的纹理。有一点值得指出的是,您不能在 glBegin()  和 glEnd()  之间绑定纹理,// 必须在 glBegin()  之前或 glEnd()  之后绑定。注意我们在后面是如何使用 glBindTexture  来指定和绑定纹理的。glBindTexture(GL_TEXTURE_2D, texture[filter]);//  选择纹理// 为了将纹理正确的映射到四边形上,您必须将纹理的右上角映射到四边形的右上角,纹理的左上角// 映射到四边形的左上角,纹理的右下角映射到四边形的右下角,纹理的左下角映射到四边形的左下// 角。如果映射错误的话,图像显示时可能上下颠倒,侧向一边或者什么都不是。glBegin(GL_QUADS);//////////////////////////////glNormal3f 是这一课的新东西。Normal就是法线的意思,所谓法线是指经过面( 多边形)上的一点且//垂直于这个面多边形的直线。使用光源的时候必须指定一条法线。法线告诉 这个多边形的//朝向,并指明多边形的正面和背面。如果没有指定法线,什么怪事情都可能发生:不该照亮的面被//照亮了,多边形的背面也被照亮....。对了,法线应该指向多边形的外侧。////看着木箱的前面您会注意到法线与Z 轴正向同向。这意味着法线正指向观察者-您自己。这正是我//们所希望的。对于木箱的背面,也正如我们所要的,法线背对着观察者。如果立方体沿着X 或Y 轴//转个180度的话,前侧面的法线仍然朝着观察者,背面的法线也还是背对着观察者。换句话说,不//管是哪个面,只要它朝着观察者这个面的法线就指向观察者。由于光源紧邻观察者,任何时候法线//对着观察者时,这个面就会被照亮。并且法线越朝着光源,就显得越亮一些。如果您把观察点放到//立方体内部,你就会法线里面一片漆黑。因为法线是向外指的。如果立方体内部没有光源的话,当//然是一片漆黑。//前侧面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();///////////////////////////////glFlush();}void ReSizeFunc(int width,int height){glViewport(0,0,width,height);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(45,width/height,0.1,100);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void KeyBoardFunc(unsigned char key, int x, int y){cout<<"curren key"<<(int)key<<" what:"<<key<<endl;if(VK_ESCAPE == key){exit(0);}if((key == 'l') && !g_bKeyL){g_bKeyL = true;g_bLight = !g_bLight;if(!g_bLight){glDisable(GL_LIGHTING);//  禁用光源cout<<"禁用光源"<<endl;}else{glEnable(GL_LIGHTING);//  启用光源cout<<"启用光源"<<endl;}}//下面的代码查看是否松开了"L" 键。如果松开,变量lp 将设为false 。这意味着"L" 键没有按下。如果//不作此检查,光源第一次打开之后,就无法再关掉了。计算机会以为"L" 键一直按着呢。if(key != 'l'){g_bKeyL = false;}if((key == 'f') && !g_bKeyF){g_bKeyF = true;filter += 1;if(filter>2){filter = 0;}cout<<"filter="<<filter<<endl;}if(key != 'f'){g_bKeyF = false;}if(('b' == key)&&!g_bKeyB)// B 健按下且bp为 FALSE 么?{g_bKeyB = true;//  若是, bp 设为 TRUEg_bBlend = !g_bBlend;//  切换混合选项的 TRUE / FALSEif(g_bBlend)//  混合打开了么?{glEnable(GL_BLEND);//  打开混合glDisable(GL_DEPTH_TEST);//  关闭深度测试}else{glDisable(GL_BLEND);//  关闭混合glEnable(GL_DEPTH_TEST);//  关闭混合}}if('b'!=key)//  B  键松开了么?{g_bKeyB = false;//  若是, bp 设为 FALSE}DrawScene();}void SpecialKeys(int key, int x, int y){cout<<"curren special key"<<(int)key<<" what:"<<key<<endl;//现在检查方向键。按下左右方向键xspeed 相应减少或增加。按下上下方向键yspeed 相应减少或增//加。记住在以后的教程中如果xspeed 、yspeed 的值增加的话,立方体就转的更快。如果一直按着某//个方向键,立方体会在那个方向上转的越快。if(GLUT_KEY_UP == key){g_fXSpeed -= 0.01;}if(GLUT_KEY_DOWN == key){g_fXSpeed += 0.01;}if(GLUT_KEY_LEFT == key){g_fYSpeed -= 0.01;}if(GLUT_KEY_RIGHT == key){g_fYSpeed += 0.01;}//接着四行检查PageDown键是否按下,若是的话,增加z 变量的值。这样DrawGLScene 函数中包含//的glTranslatef(0.0f,0.0f,z) 调用将使木箱向着观察者移近一点。if(GLUT_KEY_PAGE_DOWN == key){g_fZ+=0.02;}DrawScene();}int Init(){LoadTexture();glEnable(GL_TEXTURE_2D);//  启用纹理映射glShadeModel(GL_SMOOTH);//  启用阴影平滑glClearColor(0,0,0,0); //  黑色背景glClearDepth(1); //  设置深度缓存glEnable(GL_DEPTH_TEST);//  启用深度测试glDepthFunc(GL_LEQUAL); //  所作深度测试的类型glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);//  真正精细的透视修正glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);                          //  设置环境光glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);                          //  设置漫射光glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);                        //  设置光源位置//我们启用一号光源。我们还没有启用GL_LIGHTING,所以您看不见任何光线。记住:只对//光源进行设置、定位、甚至启用,光源都不会工作。除非我们启用GL_LIGHTING。glEnable(GL_LIGHT1);//第一行以全亮度绘制此物体,并对其进行50% 的alpha混合( 半透// 明) 。当混合选项打开时,此物体将会产生50% 的透明效果。第二行设置所采用的混合类型。// Rui Martins 的补充: alpha 通道的值为 0.0 意味着物体材质是完全透明的。1.0 则意味着完全不透明。glColor4f(1,1,1,0.5);//  全亮度, 50% Alpha  混合glBlendFunc(GL_SRC_ALPHA,GL_ONE);//  基于源象素alpha通道值的半透明混合函数return 0;}int main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);glutInitWindowPosition(100, 100);glutInitWindowSize(500, 500);glutCreateWindow("第八个OpenGL程序");glutReshapeFunc(ReSizeFunc);glutDisplayFunc(DrawScene);glutKeyboardFunc(KeyBoardFunc);glutSpecialFunc(SpecialKeys);Init();glutMainLoop();return 0;}





0 0
原创粉丝点击