Multiple Viewports - Glew


Im currently making a game using a graphics engine based off Glew.
I am not allowed to use the full glu libraries and can only include the engine stuff that my school has built.

But I still have access to functions such as glViewPort.

I wish to make a 2D top down split screen shooter game for 2 players. However I am encountering problems trying to make the 2 viewports render the same object (E.g. the background object).

Here is my current algorithm:

glViewport(0, 0, 400, 600);
Render Background Obj;

glViewport(400, 0, 400, 600);
Render Background Obj;

The problem is why is the second viewport shearing my object? It seems that it is trying to squeeze my object into the second viewport.
Also the first object is not clipping along the first viewports edges and spilling into the second viewport.

Can someone explain what is the cause and a pseudo code fix for this?
Remember I only using Glew so I have no access to any of the GL matrices.
Any help will be appreciated.

GLEW is the “OpenGL® Extension Wrangler”. It loads OpenGL® functions (such as glViewport). It is NOT a
graphics engine and does not do anything beyond loading the function entry points.

Restrictions on GLU or OpenGL® matrix functions is a design choice by your engine. Any propper engine handles
transformations itself. Use that code instead.

First of all, are you using the propper projection matrices? If you change the size of the viewport, your aspect ratio changes. If you still
use the same perspective projection matrix as before, your objects will look distorted.

Second of all, the glViewport function specifies viewport mapping, i.e. how to transform normalized device coordinates to screen
coordinates. It does not automatically include clipping, i.e. if something pokes outside the NDC range, it will poke outside the viewport.

What you want is scissor testing, i.e. something like this:

glEnable( GL_SCISSOR_TEST );

glViewport(0, 0, 400, 600);
glScissor(0, 0, 400, 600);
Render Background Obj;

glViewport(400, 0, 400, 600);
glScissor(400, 0, 400, 600);
Render Background Obj;

glDisable( GL_SCISSOR_TEST );

if something pokes outside the NDC range, it will poke outside the viewport.

Yes, but nothing can poke outside of the NDC range, because everything was clipped to be within that volume.

AFAIK viewport mapping maps the [-1,+1] range on the X axis to [viewport_x,viewport_x+width-1] and the [-1,+1] range on the Y axis to [viewport_y,viewport_y+height-1].
Theoretically, that should be clipped (using Sutherland-Hodgman or whatever), so if it is clipped in a way that no polygon pokes outside the [-1,+1] range on either X or Y,
we would not need to scissor the area and we won’t see any pixels outside the viewport rectangle.

I just modified a program to restrict the viewport to a sub-section of a window and tried it with Mesa on an Intel card and with the proprietary
Nvidia drivers on an Nvidia card and it seems you are right.

However I can definitely remember having tried something like that in the past and seeing primitives partially outside the viewport area. Is that
implementation defined/nonconformat behaviour or am I confusing this with some version of Direct3D?

There are only a very few circumstances that the GL specification allows primitive rendering to (potentially) affect pixels outside the viewport.

Wide lines and point sizes are one. Lines and points are clipped before being inflated by their size, so by the spec, lines and points with sizes greater than 1 can render outside of the viewport. Indeed, if a point is near the boundary of the viewport and the size puts part of it over the edge, OpenGL requires that the whole point be visible. So if the point is within the viewport boundary, then we will see the entire point (or as much as the screen will allow).

Multisampling is another, as some samples of a triangle could be outside of the viewport size.

So using the scissor box may well be appropriate.