```public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h)
{
GL2 gl = drawable.getGL().getGL2();
gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
if (w <= h) //
gl.glOrtho(-1.0, 1.8, -1.0 * (float) h / (float) w, //
1.0 * (float) h / (float) w, -1.0, 1.0);
else gl.glOrtho(-1.0 * (float) w / (float) h, //
1.8 * (float) w / (float) h,//
-1.0, 1.0, -1.0, 1.0);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity(); }
This is the classic aspect-ratio-``` correction pattern for glOrtho, and the "flipping" is just making sure the shorter screen dimension keeps the fixed [-1, 1]-ish range while the longer dimension gets stretched by the aspect ratio — so that objects don't get squished or stretched when the window isn't square.
The core idea
glOrtho defines a clipping box in world coordinates. If you always used a fixed box like (-1, 1, -1, 1) regardless of window shape, then:
- A square in world space would render as a rectangle whenever the viewport (window) isn't square, because OpenGL maps that fixed clipping box onto whatever pixel dimensions
w × hyou gaveglViewport.
So you need the ratio of your ortho box's width to height to match the ratio of the viewport's width to height (w/h), otherwise you get non-uniform scaling (distortion).
Why the branch on w <= h
-
When
w <= h(window taller than wide, or square): the x-range is kept fixed at(-1, 1)(well, here-1.0to1.8, slightly asymmetric, but same idea), and the y-range is expanded byh/w, which is ≥ 1. So the y clipping range grows to match how much taller the window is relative to its width. -
When
w > h(window wider than tall): the y-range stays fixed at(-1, 1), and the x-range is expanded byw/h, which is ≥ 1.
In both cases, the multiplier used is always ≥ 1 — that's the "flipping ratio > 1" you're noticing. That's intentional: you always scale up the longer screen dimension's corresponding world-coordinate range, rather than shrinking the shorter one. This guarantees:
- The world-space region you can see along the "short" screen dimension never shrinks below the fixed range you defined (so nothing gets clipped away that you expect to always be visible).
- The "long" screen dimension gets extra world-space range proportionally, so a circle stays a circle, a square stays a square — no squash/stretch distortion.
Why not just always divide instead of conditionally choosing which axis to scale?
You could write it as always computing aspect = w/h and
scaling x by aspect (or scaling y by 1/aspect),
but that would mean when aspect < 1 (tall window)
you'd be scaling x by something less than 1,
shrinking your visible x-range below your intended baseline —
content could go out of view on the sides.
The if (w<=h) ... else ... branch avoids ever having a shrinking multiplier;
it always picks whichever axis needs to grow to preserve the fixed axis's minimum extent, and always multiplies (never divides) by a ratio ≥ 1.
In short: the branching + always-≥1 multiplier is just a clean way to implement "preserve aspect ratio without ever clipping your baseline view region" — the fixed dimension stays constant,
and the other dimension's ortho range is stretched by however much wider/taller the window is, so nothing distorts and nothing you expect to see gets cut off.
No comments:
Post a Comment