viewport fine, larger screen display blank

Hi,

My goal is to create a viewport within a full screen, high def, window (1920 x 1080). The program creates the larger window but remains blank although the viewport appears and behaves as predicted. What am I doing wrong? I want the small viewport to be an inset on the screen sized display. I didn’t know,also, whether to call glutSwapBuffer only once after both “canvases” - the large display and the viewport - are finished drawing. Or should glutSwapBuffer should occur twice here. Also when to create a viewport versus subwindow.


void display (void) {

	    glClearColor (0.0,0.0,0.0,1.0); //clear the screen to black
	    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the color buffer and the depth buffer
	    glLoadIdentity();
	    camera();
	    enable();
	    cube(); //call the cube drawing function
	    glutSwapBuffers(); //swap the buffers
	    angle++; //increase the angle

}

void viewport1 (void) {
		glViewport(0,0,600,600);
	    //glClearColor (0.0,0.0,0.0,1.0); //clear the screen to black
	    //glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the color buffer and the depth buffer
	    glLoadIdentity();
	    glOrtho(0, 600, 0, 600, -1, 1);
	    camera();
	    enable();
	    cube(); //call the cube drawing function
	    //glutSwapBuffers(); //swap the buffers
	    angle++; //increase the angle

}

.....

int main (int argc, char **argv) {
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);
    //
    //glutGameModeString( "1024×768:32@75" ); //the settings for fullscreen mode
    //glutEnterGameMode(); //set glut to fullscreen using the settings in the line above
    //to revert comment 2 above and uncomment the 3 below
    glutInitWindowSize (1920, 1080);
    glutInitWindowPosition (0,0);
    int mainWindow = glutCreateWindow ("A basic FPS OpenGL Window");
    glutFullScreen();
    glViewport(0,0, 1280, 720);
    init ();
    glutDisplayFunc(display);
    glutDisplayFunc(viewport1);
    glutIdleFunc(display);
    glutReshapeFunc (reshape);
    glutPassiveMotionFunc(mouseMovement); //check for mouse movement
    glutKeyboardFunc (keyboard);
    glutMainLoop ();
    return 0;
}

The viewport1() function sets the viewport to 600x600, and it stays that way forever after. If you want the display() function to use a different portion of the window, you need another glViewport() call there.

Once. It’s still only one window.

Use a subwindow if you want to register different callbacks for it, or if you want it to have a different display mode, or a separate context from the main window (note that contexts created by GLUT never share data, so you’ll need to create shader programs, textures, etc separately for the subwindow). From the application’s perspective, a subwindow behaves largely like a top-level window; anything that differs between windows also differs between a top-level window and its subwindows.

Also, note that the viewport clips geometry, not rendering. So primitives which aren’t bounded by geometry (wide points and lines, bitmaps) can extend beyond the viewport. If you want to clip rendering, you need to use a scissor rectangle (glEnable(GL_SCISSOR_TEST) and glScissor()).


void display (void) {
		glViewport(0,0,600,600);
	    glClearColor (1.0,1.0,0.0,1.0); //clear the screen to yellow
	    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the color buffer and the depth buffer
	    glLoadIdentity();
	    //glOrtho(0, 1920, 0, 1080, -1, 1);
	    camera();
	    enable();
	    cube(); //call the cube drawing function
	    glutSwapBuffers(); //swap the buffers
	    angle++; //increase the angle

}

I think it should be painting the viewport background yellow but its painting the entire screen yellow, including the viewport. If I could focus the yellow in the viewport, the rest of the display could be used. Why is it painting the entire screen?

The customary way to set the viewport for a window in GLUT is to use a reshape callback:


void reshape( int width, int height )
{
  glViewport(0, 0, width, height);
}

...

glutReshapeFunc( reshape );

Then whenever your window is first created or resized, it’ll automatically call glViewport with the correct size.

If you want your viewport to be a subset of the full window, you can easily do that by passing other values to glViewport such as 100, 100, width - 100, height - 100. You might do some clamping though to make sure your viewport is still valid even if the window size is < 100 pixels wide or tall.

The program creates the larger window but remains blank although the viewport appears and behaves as predicted. What am I doing wrong?

You’re calling glutDisplayFunc multiple times. There’s only 1 display function per window, so GLUT is only paying attention to the last call you’ve made to glutDisplayFunc.

Ok, got it to work by deploying glScissor. By limiting the size of the repaint on the small viewport this preserved the main display viewport from being improperly over-painted before using glScissor. Now I have a display sized viewport with a small overlapping it. The effect is neat: flying boxes in the main, mirrored by same such on the small inset. I am sure I have made some mistakes though which is why I am posting the code. For example my viewports spin without glLoadIdentity().

From here, how do I use text on the small viewport? Is that better suited with a subwindow? I would also like to tag mouse-over objects in the box with text data. Can someone point me in the right direction with that? A sort of HUD?

void display (void) {
		glViewport(0,0,1920,1080);
	    glClearColor (0.0,0.0,0.0,1.0); //clear the screen to black
	    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the color buffer and the depth buffer
	    glLoadIdentity();
	    camera();
	    enable();
	    cube(); //call the cube drawing function
	    glViewport(0,0,1920/3,1080/3);
	    glScissor(0,0,1920/3,1080/3);
	    glEnable(GL_SCISSOR_TEST);
	    glClearColor (0.0,0.0,0.0,1.0); //should set the viewport to black
	    glClear(GL_COLOR_BUFFER_BIT);
	    glDisable(GL_SCISSOR_TEST);
	    cube(); //draw cubes
	    glutSwapBuffers(); //swap the buffers
	    angle++; //increase the angle

}

void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h); //set the viewport to the current window specifications
    glMatrixMode (GL_PROJECTION); //set the matrix to projection
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 1000.0); //set the perspective (angle of sight, width, height, depth)
    glMatrixMode (GL_MODELVIEW); //set the matrix back to model

}


int main (int argc, char **argv) {
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);
    //
    //glutGameModeString( "1024×768:32@75" ); //the settings for fullscreen mode
    //glutEnterGameMode(); //set glut to fullscreen using the settings in the line above
    //to revert comment 2 above and uncomment the 3 below
    glutInitWindowSize (1920, 1080);
    glutInitWindowPosition (0,0);
    int mainWindow = glutCreateWindow ("A basic FPS OpenGL Window");
    glutFullScreen();
    init ();
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutReshapeFunc (reshape);
    glutPassiveMotionFunc(mouseMovement); //check for mouse movement
    glutKeyboardFunc (keyboard);
    glutMainLoop ();
    return 0;
}

Note that glScissor() won’t have any effect for rendering triangles, quads, or polygons, or single-pixel points and lines. I note that you have now added a glViewport() call to your display() function, the absence of which was the cause of your original problem.

For example my viewports spin without glLoadIdentity().

Without that, the rotations made in each call to display() will accumulate. The context state doesn’t magically get reset between each callback; once you set something, it stays set.

For legacy OpenGL, you can use glutBitmapCharacter() or glutStrokeCharacter(). Typical usage is to create a set of contiguously-numbered display lists containing individual characters then use glCallLists() to render strings.

This doesn’t work in “modern” OpenGL (3.0 and 3.2+ core profile), as neither bitmaps nor display lists exist. You need to use textured triangles instead (you can use instanced rendering or a geometry shader to do some of the work).

Am I working with mostly outdated code? I intend to create a redistributable - should I marry up and start doing these tasks in opengl 2/3? One advantage of doing the glut tutorials was the quickness you could get things going: mouse and keyboard movement in the first 4 tutorials. In opengl 2/3 these tutorials are spent on loading and creating shader programs, etc.

OpenGL 1.x isn’t going away; there’s too much code which uses it and which won’t be re-written (e.g. all of the games based upon the idTech engines).

However: if you want to use the more recent features (e.g. instancing) and you want cross-platform code, bear in mind that the Mac doesn’t support 3+ compatibility profile. It supports 2.1 and 3/4 core profile. So if you want post-2.1 features in something which runs on a Mac, you’re limited to the core profile, which means no bitmaps, display lists, matrix stack, etc. Similarly, if you want your code to be (largely) portable between desktop OpenGL and OpenGL ES 2/3, you need to use the core profile (ES 2/3 doesn’t have any of the legacy stuff).

Does that mean opengl is not backwards compatible to 1.1?

In OpenGL 3 and later, backward compatibility is optional.

On Windows and Linux, all drivers I’m aware of support the compatibility profile. On Mac, you have a choice of OpenGL 2.1 (which is backward compatible with previous versions) or 3+ core profile (which isn’t compatible).