提要

OpenGL视口(Viewport)可以看作是窗口中OpenGL的绘制输出区域,可以通过一条简单的glViewport命令设置。一般的OpenGL教程都是单视口,即整个窗口为惟一的一个视口,Nehe的OpenGL教程是我最早见到涉及多视口的。与单视口程序相比,多视口程序的变化主要是:

(一)多视口程序不能在窗口resize/reshape时直接调用glViewport,而应该在此时记下窗口大小,然后在绘制场景时多次调用glViewport设置每个视口的位置和大小;

(二)对于每个视口,应分别调用glMatrixMode(GL_PROJECTION)和glMatrixMode(GL_MODELVIEW)以设置投影和建模矩阵。

多视口的最常见的应用,就是3DMax中的多视口建模,每一个观察口都从不同的方向去观察模型,从而很方便地去获取模型当前的状态。

还有就是×××游戏中的后视镜等等.

具体实现的思路就是对每个视口进行独立的渲染。


函数解析

下面是需要调用到的一些OpenGL的函数。

glLoadIdentity()

重置当前指定的矩阵为单位矩阵.

glViewport(GLint x,GLint y,GLsizei width,GLsizei height)

在窗口中定义一个像素矩形,最终将图像映射到这个矩形中。

void gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)

建立了一个可视的二位平面区域。这个和用glOrtho函数的当near=0,far=1时效果是一样。

void gluPerspective(GLdouble fovy, GLdouble aspect,GLdouble zNear,GLdouble zFar)

这个函数指定了观察的视景体(frustum为锥台的意思,通常译为视景体)在世界坐标系中的具体大小,一般而言,其中的参数aspect应该与窗口的宽高比大小相同。

void glScissor(GLint x,GLint y,GLsizei width,GLsizei height)

设置一个裁剪窗口,前两个参数为窗口左下角位置,后两个参数是窗口的宽度和高度。

使用前一定要glEnable(GL_SCISSOR_TEST);

代码实现

实现一:

void renderGL() {     glClear (GL_COLOR_BUFFER_BIT);     glLoadIdentity();					                // 重置模型观察矩阵      for (int loop=0; loop<4; loop++)					// 循环绘制4个视口     {         if (loop==0)									// 绘制左上角的视口         {             // 设置视口区域             glViewport (0, window_height/2, window_width/2, window_height/2);             glMatrixMode (GL_PROJECTION);             glLoadIdentity ();             gluOrtho2D(0, window_width/2, window_height/2, 0);         }         if (loop==1)									// 绘制右上角视口         {              glViewport (window_width/2, window_height/2, window_width/2, window_height/2);             glMatrixMode (GL_PROJECTION);             glLoadIdentity ();             gluPerspective( 45.0, 1.0f, 0.1f, 500.0 );         }         if (loop==2)									// 绘制右下角视口         {             glViewport (window_width/2, 0, window_width/2, window_height/2);             glMatrixMode (GL_PROJECTION);             glLoadIdentity ();             gluPerspective( 45.0, 1.0f, 0.1f, 500.0 );         }         if (loop==3)									// 绘制左下角视口         {             glViewport (0, 0, window_width/2, window_height/2);             glMatrixMode (GL_PROJECTION);             glLoadIdentity ();             gluPerspective( 45.0, 1.0f, 0.1f, 500.0 );         }         glMatrixMode (GL_MODELVIEW);							         glLoadIdentity ();          glClear (GL_DEPTH_BUFFER_BIT);         if (loop==0)									// 绘制左上角的视图         {             glBegin(GL_QUADS);             glColor3f(1.0f,0.0f,0.0f);			    // 设置当前色为红色             glVertex2i(window_width/2, 0              );             glColor3f(0.0f,1.0f,0.0f);			    // 设置当前色为绿色             glVertex2i(0,              0              );             glColor3f(0.0f,1.0f,1.0f);			    // 设置当前色为蓝色             glVertex2i(0, window_height/2);             glColor3f(1.0f,1.0f,0.0f);			    // 设置当前色为红色             glVertex2i(window_width/2, window_height/2);             glEnd();         }         if (loop==1)									// 绘制右上角的视图         {             glColor3f(1.0f,0.0f,1.0f);	             glTranslatef(0.0f,0.0f,-9.0f);             glRotatef(rtri,1.0,1.0,0.0);              glBegin(GL_TRIANGLES);					    // 绘制三角形             glVertex3f( 0.0f, 1.0f, 0.0f);			// 上顶点             glVertex3f(-1.0f,-1.0f, 0.0f);			// 左下             glVertex3f( 1.0f,-1.0f, 0.0f);			// 右下             glEnd();						            // 三角形绘制结束          }         if (loop==2)									// 绘制右下角的视图         {             glTranslatef(0.0f,0.0f,-2.0f);             glRotatef(-45.0f,1.0f,0.0f,0.0f);             glRotatef(rtri,0.0f,0.0f,1.0f);              glBegin(GL_QUADS);             glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.5f,  0.5f, 0.0f);             glColor3f(0.0f,1.0f,0.0f); glVertex3f(-0.5f,  0.5f, 0.0f);             glColor3f(0.0f,0.0f,1.0f); glVertex3f(-0.5f, -1.0f, 0.0f);             glColor3f(0.0f,0.0f,0.0f); glVertex3f( 0.5f, -1.0f, 0.0f);             glEnd();          }         if (loop==3)									// 绘制左下角的视图         {             glColor3f(0.0f,0.0f,0.0f);             glTranslatef(0.0f,0.0f,-4.0f);             glRotatef(-rtri/2,1.0f,0.0f,0.0f);             glRotatef(-rtri/2,0.0f,1.0f,0.0f);             glRotatef(-rquad/2,0.0f,0.0f,1.0f);              glBegin(GL_QUADS);             glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.5f,  0.5f, 0.0f);             glColor3f(0.0f,1.0f,0.0f); glVertex3f(-0.3f,  0.5f, 0.0f);             glColor3f(0.0f,0.0f,1.0f); glVertex3f(-0.5f, -1.0f, 0.0f);             glColor3f(0.0f,0.0f,0.0f); glVertex3f( 0.5f, -1.0f, 0.0f);             glEnd();         }     }     rtri+=0.2f;						                  // 旋转变量     rquad-=0.15f;						              // 旋转变量     SDL_GL_SwapBuffers( ); }

效果:



实现二:

void renderGL2() {	      //视口一  左下角     glEnable(GL_SCISSOR_TEST);     glScissor(0,0,window_width/2-1,window_height/2-1);      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     glDisable(GL_SCISSOR_TEST);      glViewport(0,0,window_width/2-1,window_height/2-1);     glMatrixMode(GL_PROJECTION);     glLoadIdentity();     gluPerspective(45.0f,(GLfloat)window_width/(GLfloat)window_height,0.1f,100.0f);      glMatrixMode(GL_MODELVIEW);     glLoadIdentity();      //绘制部分				     glTranslatef(0.0f  ,0.0f  ,-5.0f  );       glRotatef(rtri,0.0f  ,1.0f  ,0.0f  );        //绘制一个三角锥       glBegin( GL_TRIANGLE_STRIP );       glColor3f( 1.0, 0.0, 0.0 );       glVertex3f(  0.0,  1.0,  0.0 );       glColor3f( 0.0, 1.0, 0.0 );       glVertex3f(-1.0, -1.0,  1.0 );       glColor3f( 0.0, 0.0, 1.0 );       glVertex3f(  1.0, -1.0,  1.0 );       glColor3f( 0.0, 1.0, 0.0 );       glVertex3f(  1.0, -1.0, -1.0 );       glColor3f( 1.0, 0.0, 0.0 );       glVertex3f(  0.0,  1.0,  0.0 );       glColor3f( 0.0, 1.0, 0.0 );       glVertex3f(-1.0, -1.0,  1.0 );       glEnd();        //视口二 左上角     glEnable(GL_SCISSOR_TEST);     glScissor(0,window_height/2+1,window_width/2-1,window_height/2-1);     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     glDisable(GL_SCISSOR_TEST);      glViewport(0,window_height/2+1,	window_width/2-1,	window_height/2-1);     glMatrixMode(GL_PROJECTION);     glLoadIdentity();      gluPerspective(45.0f,(GLfloat)window_width/(GLfloat)window_height,0.1f,100.0f);      glMatrixMode(GL_MODELVIEW);     glLoadIdentity();      //绘制部分     glColor3f(1.0f,0.0f,1.0f);     glTranslatef(0.0f,0.0f,-9.0f);     glRotatef(rtri,1.0,1.0,0.0);      glBegin(GL_TRIANGLES);					    // 绘制三角形     glVertex3f( 0.0f, 1.0f, 0.0f);			// 上顶点     glVertex3f(-1.0f,-1.0f, 0.0f);			// 左下     glVertex3f( 1.0f,-1.0f, 0.0f);			// 右下     glEnd();						            // 三角形绘制结束      //视口三  右下角     glEnable(GL_SCISSOR_TEST);     glScissor(window_width/2+1,	0,	window_width/2-1,	window_height/2-1);     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     glDisable(GL_SCISSOR_TEST);      glViewport(window_width/2+1,0,window_width/2-1,	window_height/2-1);     glMatrixMode(GL_PROJECTION);     glLoadIdentity();      gluPerspective(45.0f,(GLfloat)window_width/(GLfloat)window_height,0.1f,100.0f);     glMatrixMode(GL_MODELVIEW);     glLoadIdentity();      //绘制部分     glTranslatef(0.0f,0.0f,-2.0f);     glRotatef(-45.0f,1.0f,0.0f,0.0f);     glRotatef(rtri,0.0f,0.0f,1.0f);      glBegin(GL_QUADS);     glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.5f,  0.5f, 0.0f);     glColor3f(0.0f,1.0f,0.0f); glVertex3f(-0.5f,  0.5f, 0.0f);     glColor3f(0.0f,0.0f,1.0f); glVertex3f(-0.5f, -1.0f, 0.0f);     glColor3f(0.0f,0.0f,0.0f); glVertex3f( 0.5f, -1.0f, 0.0f);     glEnd();      //视口四  右上角     glEnable(GL_SCISSOR_TEST);      glScissor(window_width/2+1,	window_height/2+1, window_width/2-1, window_height/2-1);     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     glDisable(GL_SCISSOR_TEST);      glViewport(window_width/2+1,	window_height/2+1, window_width/2-1, window_height/2-1);     glMatrixMode(GL_PROJECTION);     glLoadIdentity();      gluPerspective(45.0f,(GLfloat)window_width/(GLfloat)window_height,0.1f,100.0f);      glMatrixMode(GL_MODELVIEW);     glLoadIdentity();      //绘制部分     glColor3f(0.0f,0.0f,0.0f);     glTranslatef(0.0f,0.0f,-4.0f);     glRotatef(-rtri/2,1.0f,0.0f,0.0f);     glRotatef(-rtri/2,0.0f,1.0f,0.0f);     glRotatef(-rquad/2,0.0f,0.0f,1.0f);      glBegin(GL_QUADS);     glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.5f,  0.5f, 0.0f);     glColor3f(0.0f,1.0f,0.0f); glVertex3f(-0.3f,  0.5f, 0.0f);     glColor3f(0.0f,0.0f,1.0f); glVertex3f(-0.5f, -1.0f, 0.0f);     glColor3f(0.0f,0.0f,0.0f); glVertex3f( 0.5f, -1.0f, 0.0f);     glEnd();     rtri+=0.2f;						                  // 旋转变量     rquad-=0.15f;						              // 旋转变量     SDL_GL_SwapBuffers( ); } void initGL( int width, int height ) {     float ratio = (float) width / (float) height;     // Our shading model--Gouraud (smooth).      glShadeModel( GL_SMOOTH );     // Set the clear color.      glClearColor( 0, 0, 0, 0 );     // Setup our viewport.      glViewport( 0, 0, width, height );     //Change to the projection matrix and set our viewing volume.     glMatrixMode( GL_PROJECTION );     glLoadIdentity();     gluPerspective( 60.0, ratio, 1.0, 100.0 ); }



参考:OpenGL中的多视口-