OpenGl制作3D效果

来源:互联网 发布:access导入sql文件 编辑:程序博客网 时间:2024/04/28 17:08

为什么3D作图常常能产生另人震惊的效果?因为利用3D作图,你可以生成一些现实中难得实现的真实的感受。特别是一些特殊的光影效果。 其实光源前面已经讲的很全面了,只是缺少一些专门的例子。这里我们来稍微加深一下认识,我们将在例子中看到一个地方的光源对不同物体发出不同的光 这在现实中是少见的吧?  1.双面光照: void glLightModeli(LIGHT_MODEL_TWO_SIDE,GL_TRUE); 光照计算通常是对多边形进行的。一般设置光照的条件总是对正面的多边形,而不考虑背面,但是如果考虑一个物体被劈开,光源的个数又会影响可见性,那么 有必要对多边形双面都进行计算,这就是上面函数的功能;取消这一功能只须把第三个参数改为GL_FALSE。  2.聚光源 定义聚光源的函数仍是利用glLightfv(),需要设定的参数包括:光源位置、光源发散半角和光源聚光方向。  具体实现可以看下面例子: ////////////////////////////////////////////////////////// //sample.cpp #include <gl/gl.h>#include <gl/glu.h>#include <gl/glaux.h>#pragma comment(lib, "OpenGl32.lib")#pragma comment(lib, "glu32.lib")#pragma comment(lib, "glaux.lib")#pragma warning(disable : 4244)// MIPS#pragma warning(disable : 4136)// X86#pragma warning(disable : 4051)// ALPHA void myinit(void); void CALLBACK  display(void); void CALLBACK  reshape(GLsizei w,GLsizei h);  void initlights(void) { //定义物体材质特性的数值         GLfloat mat_ambient[]={0.2,0.2,0.2,1.0};         GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0};         GLfloat mat_specular[]={1.0,1.0,1.0,1.0};         GLfloat mat_shininess[]={80.0};  //定义第0个光源的属性(这是平行的环境光,没有聚光效果)             GLfloat light0_diffuse[]={0.0,0.0,1.0,1.0};         GLfloat light0_position[]={1.0,1.0,1.0,0.0}; //定义第一个光源的属性(聚光灯一)         GLfloat light1_ambient[]={0.2,0.2,0.2,1.0};         GLfloat light1_diffuse[]={1.0,0.0,0.0,1.0};         GLfloat light1_specular[]={1.0,0.6,0.6,1.0};         GLfloat light1_position[]={-3.0,-3.0,3.0,1.0};         GLfloat spot_direction[]={1.0,1.0,-1.0};  //定义第二个光源的属性(聚光灯二)         GLfloat light2_ambient[]={0.2,0.6,0.2,1.0};         GLfloat light2_diffuse[]={0.0,1.0,0.0,1.0};         GLfloat light2_specular[]={0.0,1.0,0.0,1.0};         GLfloat light2_position[]={-3.0,-3.0,3.0,1.0};         GLfloat spot2_direction[]={1.0,1.0,-1.0}; //!!!我们看到第一和第二个聚光源除了在颜色的定义上一个偏红,一个偏绿 //其他没有任何不同,所以如果象我们后面作的,对一个物体开启一个光源,对 //另一个物体开启另一个光源,就会产生一个点光源对不同物体发出不同光的效果  //将前面的属性定义加以应用         glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);         glLightfv(GL_LIGHT0,GL_POSITION,light0_position);          glLightfv(GL_LIGHT1,GL_AMBIENT,light1_ambient);         glLightfv(GL_LIGHT1,GL_DIFFUSE,light1_diffuse);         glLightfv(GL_LIGHT1,GL_SPECULAR,light1_specular);         glLightfv(GL_LIGHT1,GL_POSITION,light1_position); //定义聚光灯发散角         glLightf(GL_LIGHT1,GL_SPOT_CUTOFF,30.0); //定义聚光灯发射方向的向量         glLightfv(GL_LIGHT1,GL_SPOT_DIRECTION,spot_direction);          glLightfv(GL_LIGHT2,GL_AMBIENT,light2_ambient);         glLightfv(GL_LIGHT2,GL_DIFFUSE,light2_diffuse);         glLightfv(GL_LIGHT2,GL_SPECULAR,light2_specular);         glLightfv(GL_LIGHT2,GL_POSITION,light2_position);          glLightf(GL_LIGHT2,GL_SPOT_CUTOFF,30.0);         glLightfv(GL_LIGHT2,GL_SPOT_DIRECTION,spot2_direction);          glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);         glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);         glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);         glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);          glEnable(GL_LIGHTING);         glEnable(GL_LIGHT0);         glEnable(GL_LIGHT1);         glEnable(GL_LIGHT2);  }  void myinit(void) {          auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);         auxInitPosition(0,0,500,500);         auxInitWindow("sample1");         glClearColor(0.0,0.0,0.0,0.0);         glClear(GL_COLOR_BUFFER_BIT);          glDepthFunc(GL_LESS);         glEnable(GL_DEPTH_TEST);         initlights(); //      glShadeModel(GL_FLAT); }  void CALLBACK reshape(GLsizei w,GLsizei h) {  glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity();  if(w<=h)  glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0); else   glOrtho(-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }   void CALLBACK display(void) {   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //首先标出聚光源一、二的位置(同一位置)   glPushMatrix();   glTranslated(-3.0,-3.0,3.0);   glDisable(GL_LIGHTING);   glColor3f(1.0,0.0,0.0);   auxWireCube(0.1);   glEnable(GL_LIGHTING);   glPopMatrix();  //关掉第二个光源,只启用第一个光源(红),绘制球体一   glPushMatrix();   glDisable(GL_LIGHT2);    glTranslated(0.0,2.0,0.0);   auxSolidSphere(2.0);   glPopMatrix();    //关掉第一个光源,只启用第二个光源(绿),绘制球体二   glPushMatrix();   glDisable(GL_LIGHT1);   glEnable(GL_LIGHT2);   glTranslated(0.0,-2.0,0.0);   auxSolidSphere(2.0);   glPopMatrix();    glFlush(); } void main(void) {     myinit();          auxReshapeFunc(reshape);     auxMainLoop(display); } //end of sample /////////////////////////////////////////////////////////////// 一个现实中难以见到的情景出现了。还不快试试?  结束光源之前,再给出一个光源移动的例子,其中用到了鼠标消息的响应,实现 非常简单,以OPENGL的辅助库提供的方式调用一个CALLBACK函数即可,和以前讲 的响应键盘输入的方法完全一样。 ////////////////////////////////////////////////////////////// //sample.cpp #include <gl/gl.h>#include <gl/glu.h>#include <gl/glaux.h>#pragma comment(lib, "OpenGl32.lib")#pragma comment(lib, "glu32.lib")#pragma comment(lib, "glaux.lib")#pragma warning(disable : 4244)// MIPS#pragma warning(disable : 4136)// X86#pragma warning(disable : 4051)// ALPHA
void myinit(void); void CALLBACK  display(void); void CALLBACK  reshape(GLsizei w,GLsizei h);  //控制光源移动的变量 static int step=0;  //鼠标响应的CALLBACK函数 void CALLBACK movelight(AUX_EVENTREC *event) { step=(step+15)%360; }  void initlights(void) {         GLfloat mat_ambient[]={0.2,0.2,0.2,1.0};         GLfloat mat_diffuse[]={0.8,0.8,0.8,1.0};         GLfloat mat_specular[]={1.0,1.0,1.0,1.0};         GLfloat mat_shininess[]={80.0};              GLfloat light0_diffuse[]={0.0,0.0,1.0,1.0};         GLfloat light0_ambient[]={0.2,0.5,0.5,1.0};            glLightfv(GL_LIGHT0,GL_DIFFUSE,light0_diffuse);         glLightfv(GL_LIGHT0,GL_AMBIENT,light0_ambient);            glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);         glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);         glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);         glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);          glEnable(GL_LIGHTING);         glEnable(GL_LIGHT0);  }  void myinit(void) {          auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);         auxInitPosition(0,0,500,500);         auxInitWindow("sample1");         glClearColor(0.0,0.0,0.0,0.0);         glClear(GL_COLOR_BUFFER_BIT);          glDepthFunc(GL_LESS);         glEnable(GL_DEPTH_TEST);         initlights(); //      glShadeModel(GL_FLAT); }  void CALLBACK reshape(GLsizei w,GLsizei h) {  glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity();  if(w<=h)  glOrtho(-5.0,5.0,-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0); else   glOrtho(-5.0*(GLfloat)h/(GLfloat)w,          5.0*(GLfloat)h/(GLfloat)w,-5.0,5.0,-5.0,5.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }   void CALLBACK display(void) {   GLfloat position[]={0.0,0.0,1.5,1.0};    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);      glPushMatrix();   glTranslatef(0.0,0.0,-5.0);   glPushMatrix();  //光源的位置只由旋转变量step决定,每按下鼠标左键一下,step的值便会改变 //导致光源位置的改变   glRotated((GLdouble)step,-1.0,1.0,1.0);   glLightfv(GL_LIGHT0,GL_POSITION,position);   glTranslated(0.0,0.0,1.5);    glDisable(GL_LIGHTING);   glColor3f(1.0,1.0,0.0);   auxWireSphere(0.25);   glEnable(GL_LIGHTING);    glPopMatrix();   auxSolidTorus(0.5,2.5);   glPopMatrix();    glFlush();   } void main(void) {     myinit();          auxMouseFunc(AUX_LEFTBUTTON,AUX_MOUSEDOWN,movelight);     auxReshapeFunc(reshape);     auxMainLoop(display); } //end of sample ///////////////////////////////////////////////////////////// 在例子中,黄色的小球表示当前光源的位置,它的旋转导致了环状体表面受光照部分的光影的变化,每按下鼠标左键一下,光源就会作响应的旋转。