# Formulas for glViewport may be not exact

• 04-14-2014, 07:18 PM
NanoGL
Formulas for glViewport may be not exact
On this link I found the formulas for glViewport.
<www.opengl.org/wiki/GLAPI/glViewport>

xw = (xnd + 1) (width / 2) + x;
yw = (ynd + 1) (height / 2) + y;

First test: Assume x=0 and width=800, then the window coordinates go from 0 to 799.
xnd = 1 should result in the rightmost pixel 799.
xw ( 1 ) = ( 1 + 1 ) * 800 / 2 + 0 = 800; And not 799.

I derivated the formula for normalized device to window coordinates and came to a slightly different result
to replace "width" by "(width - 1)":

xw = (xnd + 1) ((width - 1) / 2) + x;
yw = (ynd + 1) ((height - 1) / 2) + y;

Can someone confirm or disprove that?

Here my derivation for glViewport( x, y, width, height ):
So the rectangle is from (x) to (x + width - 1), and from (y) to (y + height - 1).

Example: glViewport( 400, 200, 800, 600 ) has a rectangle from x: 400 to 1199, and y: 200 to 799.

Formula for x:
xw - x = xnd * a + b; // Linear equation, resolve a and b.

1. xnd = -1, and xw = x:
x - x = -1 * a + b; -> a = b;

2. xnd = +1, and xw = x + width - 1:
x + width - 1 - x = 1 * a + b; -> width - 1 = 2 a; -> a = ( width - 1 ) / 2;

Insert in formula for x:
xw - x = xnd * (width - 1) / 2 + (width - 1) / 2;
xw = ( xnd + 1 ) * (( width - 1 ) / 2 ) + x;

Test:
1. xnd = -1: xw = ( -1 + 1 ) * (( width - 1 ) / 2 ) + x = x; -> ok, 400 by the example.
2. xnd = +1: xw = ( 1 + 1 ) * (( width - 1 ) / 2 ) + x = width - 1 + x; -> ok, 1199 by the example.

Analogical for y.
• 04-15-2014, 01:47 AM
GClements
Quote:

Originally Posted by NanoGL
First test: Assume x=0 and width=800, then the window coordinates go from 0 to 799

No, the coordinates go from 0 to 800, 800 being the right-hand edge of the right-most pixel. 799 would be the left-hand edge of the right-most pixel, which is one pixel in from the right-hand edge of the window.
• 04-15-2014, 07:58 AM
NanoGL
Quote:

Originally Posted by GClements
No, the coordinates go from 0 to 800, 800 being the right-hand edge of the right-most pixel. 799 would be the left-hand edge of the right-most pixel, which is one pixel in from the right-hand edge of the window.

Hello GClements,

thanks for your answer. As I understand you, in OpenGL the edges between the pixels are counted? Then there are 800 edges between 801 pixels. Do you know a reference for that?

In the MacOS X API the pixels themselves are counted. Because the pixel on position zero has also a count, a window with width=800 goes here from 0 to 799.

Best regards
• 04-15-2014, 09:40 AM
arekkusu
Read the rasterization rules. It depends what type of primitive you're drawing.
• 05-09-2014, 03:36 PM
GClements
Quote:

Originally Posted by NanoGL
As I understand you, in OpenGL the edges between the pixels are counted? Then there are 800 edges between 801 pixels.

No; there are 801 edges "around" 800 pixels. There is an edge before the first pixel, after the last pixel, and between each pair of adjacent pixels.

Quote:

Originally Posted by NanoGL
In the MacOS X API the pixels themselves are counted. Because the pixel on position zero has also a count, a window with width=800 goes here from 0 to 799.

You're conflating coordinates with row/column indices.

Consider an 800x600 window, which has 800 columns and 600 rows.

The bottom-left pixel has its bottom-left corner at (0,0) in window coordinates, while its top-right corner is at (1,1) and its centre is at (0.5,0.5). Similarly, the top-right pixel has its bottom-left corner at (799,599), its top-right corner at (800,600), and its centre at (799.5,599.5).

The bottom-left corner of the window is at (0,0) while the top-right corner is at (800,600).

Essentially, a pixel as a whole doesn't have specific coordinates; particular points within a pixel (e.g. corners, centre, edge midpoints) have specific coordinates. The pixel spans a range of coordinates.