are you ready for a mindfuck ? are you ready for a mindfuck?

....::::Menu::::....
...::About::...
...::Articles::...
...::Contact::...
...::Home & News::...
...::Links & Credits::... OpenGL logo
Valid XHTML 1.0!

Using multiple viewports and the scissortest

by Elie De Brauwer

Goal of this file

This artcle gives an example of how to use multiple viewports in your application.

History of this file

  • 24 august 2003: created

Multiple viewports ?

Indeed multiple viewports, for those of you who already worked with (or have seen) 3d modelers or used applications like blender know that it is a nice feature that you can view a three dimensional object that you are creating from multiple angles. So many of thos applications split the screen in four and show a perspective in one segment and an xy, xz, yz orthographic projection in the remaining three windows.
In this article we won't display the orthographic projections (but you can modify the example to do so by calling glOrtho() before drawing the scene, and leave one image in perspective projection and you obtain the wanted result).
Here we will split the window in four, define the region and draw our primitive in each of the four parts. To do this we have to follow the following steps:

enable scissor testing
Use glEnable(GL_SCISSOR_TEST) to enable the scissor test. It is disabled by default.
define a viewport
void glViewport(GLint x,GLint y,GLsizei width,GLsizei height), x and y are the lower left coordinates and width and height are the width and height of the viewport.
define a matching scissorbox
void glViewport(GLint x,GLint y,GLsizei width,GLsizei height), define a rectangle in which we can modify the pixels, if the GL_SCISSOR_TEST draw is disabled the default is that the whole window is modifiable.

If you would try to run the application without using the scissor test each viewport would be overwritten and only the last viewport drawn would remain visible.

Putting it all together

In the code we use the glutReshapeFunc to set the global variables x and y that contain the dimensions of the window.
This is a fairly simple topic and everything that has to be said has already been said.
As you can see on the snapshot below we use four different viewports and each viewport contains a rotation of a primitive but one can easily replace the void drawScene(void) function with a more complex function but we just want to illustrate the concept here.

using multiple viewports
#include <cstdlib>
#include <GL/glut.h>
using namespace std;

typedef unsigned char uchar;

// callbacks 
void disp(void);
void drawScene(void);
void keyb(uchar key, int x, int y);
void reshape(int x, int y);

static int width =0 , height=0;


////////////////////////////////
// main
int main(int argc, char **argv){

  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
  glutInitWindowSize(600,600);
  glutInitWindowPosition(100,100);
  glutCreateWindow("scissor test");

  glClearColor(0.0,0.0,0.0,0.0);
  glutDisplayFunc(disp);
  glutKeyboardFunc(keyb);
  glutReshapeFunc(reshape);
  glutMainLoop();
  return 0;
}


////////////////
// disp
void disp(void){

  glEnable(GL_SCISSOR_TEST);
  glMatrixMode(GL_MODELVIEW);

  // lower left
  glViewport(0,0,width/2,height/2);
  glScissor(0,0,width/2,height/2);
  glLoadIdentity();
  glClear(GL_COLOR_BUFFER_BIT);
  drawScene();

  // lower right
  glViewport(width/2,0,width/2,height/2);
  glScissor(width/2,0,width/2,height/2);
  glLoadIdentity();
  glRotatef(90,0.0,1.0,0.0);
  glClear(GL_COLOR_BUFFER_BIT);
  drawScene();

  // upper left
  glViewport(0,height/2,width/2,height/2);
  glScissor(0,height/2,width/2,height/2);
  glLoadIdentity();
  glRotatef(90,1.0,0.0,0.0);
  glClear(GL_COLOR_BUFFER_BIT);
  drawScene();

  // upper right
  glViewport(width/2,height/2,width/2,height/2);
  glScissor(width/2,height/2,width/2,height/2);
  glLoadIdentity();
  glRotatef(90,0.0,0.0,1.0);
  glClear(GL_COLOR_BUFFER_BIT);
  drawScene();

  glFlush();
}

/////////////////////
// drawScene
void drawScene(void){
  glutWireTeapot(0.5);
}

////////////////////////////////////
// keyb
void keyb(uchar key, int x, int y ){
  if(key == 'q'){
    exit(0);
  }
}

//////////////////////////
// reshape
void reshape(int x,int y){
   width = x;
   height=y;
}

You can also download the sourcode here