OpenGL进阶(一):多视口
提要
OpenGL视口(Viewport)可以看作是窗口中OpenGL的绘制输出区域,可以通过一条简单的glViewport命令设置。一般的OpenGL教程都是单视口,即整个窗口为惟一的一个视口,而下面要和大家介绍的是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中的多视口