|
| 1 | +# DPI Scaling Logic Validation |
| 2 | + |
| 3 | +## Scenario 1: Normal DPI (1x) |
| 4 | +- Window logical size: 800x600 |
| 5 | +- RenderWidth: 800, RenderHeight: 600 (same as logical) |
| 6 | +- LogicalPixelSize: 1.0 |
| 7 | + |
| 8 | +### Before Fix (Incorrect): |
| 9 | +- Orthographic projection used RenderWidth/RenderHeight (800x600) |
| 10 | +- Mouse coords scaled by LogicalPixelSize (1.0) - no effect |
| 11 | +- Result: Correct behavior by accident |
| 12 | + |
| 13 | +### After Fix (Correct): |
| 14 | +- Orthographic projection uses Width/Height (800x600) |
| 15 | +- Mouse coords NOT scaled |
| 16 | +- Result: Correct behavior by design |
| 17 | + |
| 18 | +## Scenario 2: High DPI (2x) |
| 19 | +- Window logical size: 800x600 |
| 20 | +- RenderWidth: 1600, RenderHeight: 1200 (2x scaled) |
| 21 | +- LogicalPixelSize: 2.0 |
| 22 | + |
| 23 | +### Before Fix (Incorrect): |
| 24 | +- Orthographic projection used RenderWidth/RenderHeight (1600x1200) |
| 25 | + - View frustum: 1600 * zoom in world units wide |
| 26 | + - Objects appear 2x smaller than intended |
| 27 | +- Mouse coords at (400, 300) logical pixels scaled to (800, 600) |
| 28 | + - ScreenToWorld used RenderWidth/RenderHeight (1600x1200) |
| 29 | + - Incorrect world coordinate calculated |
| 30 | +- ZoomExtents divides world extent by 1600, making objects appear smaller |
| 31 | +- Result: Geometry too small, not centered |
| 32 | + |
| 33 | +### After Fix (Correct): |
| 34 | +- Orthographic projection uses Width/Height (800x600) |
| 35 | + - View frustum: 800 * zoom in world units wide |
| 36 | + - Objects appear correct size |
| 37 | +- Mouse coords at (400, 300) logical pixels NOT scaled |
| 38 | + - ScreenToWorld uses Width/Height (800x600) |
| 39 | + - Correct world coordinate calculated |
| 40 | +- ZoomExtents divides world extent by 800, correct zoom level |
| 41 | +- Result: Geometry properly sized and centered |
| 42 | + |
| 43 | +## Mathematical Example |
| 44 | + |
| 45 | +World space geometry bounds: 0 to 1000 units in X |
| 46 | + |
| 47 | +### Normal DPI (1x): |
| 48 | +- Before: zoomLevel = 1000 / 800 = 1.25 |
| 49 | +- After: zoomLevel = 1000 / 800 = 1.25 |
| 50 | +- Same result ✓ |
| 51 | + |
| 52 | +### High DPI (2x): |
| 53 | +- Before: zoomLevel = 1000 / 1600 = 0.625 (too zoomed out!) |
| 54 | +- After: zoomLevel = 1000 / 800 = 1.25 (correct!) |
| 55 | +- Fixed ✓ |
| 56 | + |
| 57 | +## Key Insight |
| 58 | + |
| 59 | +The framebuffer size (RenderWidth/RenderHeight) should only be used when: |
| 60 | +1. Creating the swapchain (already done correctly by platform handlers) |
| 61 | +2. Allocating GPU resources |
| 62 | + |
| 63 | +For all viewport calculations (projection, zoom, coordinate conversion), we should use the logical dimensions (Width/Height) to maintain consistent behavior across different DPI settings. |
0 commit comments