From Jim Blinn The Journey Down The Graphic Pipeline, p. 138.
To begin with, at first it may seem like the easiest conversion: the normalized coordinates of the device into pixel space. Conversion
s_x * X_NDC + d_x = X_pixel s_y * Y_NDC + d_y = Y_pixel
The user / programmer performs the entire screen design at NDC. There are three unpleasant hardware realities that NDC hides from us:
The actual number of pixels in x and y.
Uneven distance between pixels in x and y.
Up and down for the Y coordinate. The NDC-to-pixel transformation will invert Y if you want the Y in NDC to point up.
...
s_x = ( N_x - epsilon ) / 2 d_x = ( N_x - epsilon ) / 2 s_y = ( N_y - epsilon ) / (-2*a) d_y = ( N_y - epsilon ) / 2 epsilon = .001 a = N_y/N_x (physical screen aspect ratio)
source share