您的当前位置:首页正文

简析OpenGL的2D、3D切换

2020-11-09 来源:步旅网

最近做游戏的时候遇到了一个小问题,我们的游戏是2D、3D结合的(准确的说是主菜单、议会界面是2D的,但是真实打斗场景为3D),由2D切换到3D没有问题,但是由3D切换回2D问题就来了:每次切换都只有glClear()管用,其余的加载图片之类的都显示不了。经过分析感

最近做游戏的时候遇到了一个小问题,我们的游戏是2D、3D结合的(准确的说是主菜单、议会界面是2D的,但是真实打斗场景为3D),由2D切换到3D没有问题,但是由3D切换回2D问题就来了:每次切换都只有glClear()管用,其余的加载图片之类的都显示不了。经过分析感觉应该是视图矩阵的问题,因为在3D场景中我们多次调用了glLookAt()、gluPerspective()等函数,而每调用一次,OpenGL的机理是把当前矩阵乘上转换算子,所以每次都乘,到了2D场景的时候如果不转换回来就会出问题。

可以关注我的个人主页:http://alanzjl.sinaapp.com

解决这个问题有两种办法,第一种是在display()函数里通过glPushMatrix()、glPopMatrix()解决。但是我们遇到的问题是可能在display中Push、Pop的次数太多,导致最终这种办法不行。还有一种就是在初始状态下记录初始矩阵,在将切换回2D的时候恢复初始矩阵。

可通过
glGetIntegerv(GL_VIEWPORT,&view); //viewport
glGetDoublev(GL_MODELVIEW_MATRIX,&model);//model
glGetDoublev(GL_PROJECTION_MATRIX,&proj);//projection
得到。

但是我们只要得到一次而且是第一次的矩阵就可以,所以要借助一个static int变量。具体实现代码:

void my_display(void){
 static flagggg;
 if(flagggg==0){
 //只取第一次的初始矩阵
 glGetIntegerv(GL_VIEWPORT,&view); //viewport
 glGetDoublev(GL_MODELVIEW_MATRIX,&model);//model
 glGetDoublev(GL_PROJECTION_MATRIX,&proj);//projection
 flagggg=1;
 }
 
 /**************************************************************
 模式入口
 **************************************************************/
 if(Enter_Mode==-1)
 introduction();
 else if(Enter_Mode==0)
 main_menu();
 else if(Enter_Mode==1){
 adventure(); //此处是3D
 }
 else if(Enter_Mode==2){ //此处是2D,会由上面一种模式切换到此模式,需要矩阵还原
 glLoadMatrixd(view);
 glMatrixMode(GL_MODELVIEW);
 glLoadMatrixd(model);
 glMatrixMode(GL_PROJECTION);
 glLoadMatrixd(proj);
 congress();
 }
 else if(Enter_Mode==3)
 achievement();
 else if(Enter_Mode==4)
 quit();
 else if(Enter_Mode==5)
 complete();
 
 /**************************************************************/
}

其中,view、model、proj被我定义为了全局变量,它们是:

GLint view[4];
GLdouble model[16];
GLdouble proj[16];
显示全文