Skip to main content
GameDev.net gamedev.net
🔒 Locked

Why the transform between normalized device and viewport coordinates is different between OpenGL and Direct3D?

Started by leonard2012 Feb 10, 2018 at 2:30 PM 2 replies 3k views
Original Post
leonard2012
leonard2012

According to https://en.wikibooks.org/wiki/GLSL_Programming/Vertex_Transformations and https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glViewport.xml, the relation between normalized device coordinates (NDC) and viewport coordinates in OpenGL is

y_vp = (y_ndc + 1) * height / 2

For Direct3D however, it is said in section 16.1 of "Introduction to 3D Game Programming with DirectX 11" by F. D. Luna (https://www.amazon.com/Introduction-3D-Game-Programming-DirectX/dp/1936420228) that the relation is

y_vp = (1 - y_ndc) * height / 2

I could not figure out the reason of this difference. Could someone kindly give me some explanation?

Hodgman
Hodgman
On 11/02/2018 at 1:30 AM, leonard2012 said:

I could not figure out the reason of this difference. Could someone kindly give me some explanation?

There's endless different mathematical conventions for different things, most of which are equally valid and arbitrary choices. Historically, D3D and GL have disagreed with which way is up (do coordinates start at the top of the screen and increase downward, or start at the bottom and increase upwards?), and back in the early versions whether you should write vectors across the page or down the page... Most of the time you should be able to use whatever conventions you like at your application-level, and then do a bit of mathematical fiddling to translate that into D3D/GL's conventions. e.g. You could choose to have viewpoints be defined from the top corner or bottom corner, have Y be up or Z be up, use right-handed or left-handed coordinates, have NDC Z=1 be the near plane or far plane, use row-vectos or column-vectors, store 2D arrays in row-major or column-major order, etc....

Their NDC definitions also vary in Z: D3D uses a 0 to 1 range and GL uses a -1 to 1 range (by default - GL4 allows changing it). This is one case where there is an objective reason for the choice though. GL's convention here has a nice symmetry to it, but D3Ds offers precision benefits due to how floating point numbers work, allowing much better z-buffer precision.

leonard2012
leonard2012

Hi Hodgman,

Thank you for your help. It seems that I'd better accept and remember these nuances.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.