Basic_viewer: fix wrong edge width and vertex size in line-width shader#9335
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes the line-width rendering path in CGAL’s Basic Viewer so size_edges() / size_vertices() map correctly to on-screen pixel sizes across perspective vs. orthographic projections and after window resizes.
Changes:
- Correct orthographic line-width scaling so
u_PointSizeis no longer silently canceled out. - Fix geometry-shader offset math to remove unintended quadratic dependence on
u_PointSize. - Upload dynamic viewport dimensions each frame for correct NDC↔pixel conversions after resize.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| Basic_viewer/include/CGAL/Qt/Basic_viewer.h | Updates u_Viewport uniform to use current widget dimensions instead of initial constants. |
| Basic_viewer/include/CGAL/Basic_shaders.h | Fixes line-width vertex/geometry shader math for correct pixel-width behavior in ortho and perspective. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Use the actual current viewport dimensions so that the line-width | ||
| // geometry shader converts between NDC and screen-pixels correctly | ||
| // even after the window has been resized. | ||
| QVector2D viewport(static_cast<float>(this->width()), | ||
| static_cast<float>(this->height())); |
There was a problem hiding this comment.
u_Viewport appears to be used as a screen-pixel scale in the line-width geometry shader. Using this->width()/this->height() here will be in Qt device-independent pixels, so on HiDPI displays the viewport uniform will be off by devicePixelRatio() and line widths will render incorrectly. Consider uploading framebuffer pixel dimensions instead (e.g., width()*devicePixelRatio() and height()*devicePixelRatio(), or use the camera’s pixel ratio if that’s the established source of truth).
| // Use the actual current viewport dimensions so that the line-width | |
| // geometry shader converts between NDC and screen-pixels correctly | |
| // even after the window has been resized. | |
| QVector2D viewport(static_cast<float>(this->width()), | |
| static_cast<float>(this->height())); | |
| // Use the actual current framebuffer pixel dimensions so that the line-width | |
| // geometry shader converts between NDC and screen-pixels correctly | |
| // even after the window has been resized and on HiDPI displays. | |
| const float pixel_ratio = static_cast<float>(this->devicePixelRatio()); | |
| QVector2D viewport(static_cast<float>(this->width()) * pixel_ratio, | |
| static_cast<float>(this->height()) * pixel_ratio); |
714ec53 to
5eb7423
Compare
Three bugs caused incorrect edge widths and vertex sizes in the
line-width (non-geometry-feature) rendering path:
1. Quadratic dependence on u_PointSize in GEOMETRY_SOURCE_LINE_WIDTH.
The perpendicular offset vector n0 was computed as
n0 = normalize(perp) * u_PointSize * 0.5
and then scaled by gs_in[i].pointSize (= u_PointSize / effectiveDistance),
making the actual half-width u_PointSize^2 / (2 * effectiveDistance).
For large bounding-box diagonals this produces lines far wider than
intended, and the user-facing size_edges() API has super-linear
effect. Fix: remove the extra u_PointSize factor from n0 so the
half-width is linear: u_PointSize / (2 * effectiveDistance).
2. Orthographic mode always produced width 1 in VERTEX_SOURCE_LINE_WIDTH.
Setting distance = u_PointSize caused pointSize = u_PointSize /
u_PointSize = 1.0, completely ignoring the user-specified size.
Fix: use distance = 1.0 so pointSize = u_PointSize passes through
as a direct screen-pixel width (correct for orthographic).
3. Baked-in viewport in the C++ drawing code.
The u_Viewport uniform was always uploaded as the initial window size
(500 x 450) instead of the current framebuffer dimensions. Resizing
the window produced incorrect line geometry because the NDC <-> pixel
conversions inside the geometry shader used stale dimensions.
Fix: use this->width() / this->height() every frame.
Fixes CGAL#9327
5eb7423 to
e7a3382
Compare
|
Thanks @RajdeepKushwaha5 for the patch. |
|
hi @gdamiand, I know this is addressed to @RajdeepKushwaha5, but having impelemented a similar patch I can share some of the results: |
|
Thanks @gdamiand! Yes, I tested the patch across different geometries and scales, both 2D and 3D. Bug 1 — Quadratic edge width at large scaleUsing Before — edges are massively blown out due to quadratic
After — correct linear edge width, cube fully visible:
At normal scale (bbox diagonal ≈ 8.2), before and after both look correct — the bug only manifests at larger scales: Before (normal scale):
After (normal scale):
Bug 2 — Orthographic mode ignores
|
Thanks @aminkhalsi for testing and sharing results — glad the large-scale fix is confirmed on your side too! A few clarifications on the technical points you raised: On removing On On the viewport fix: On step size proportional to bbox: |
|
ping @gdamiand |
|
Successfully tested in CGAL-6.3-Ic-1 |
|
Thanks @sloriot ! |














Fix three bugs in the line-width rendering path that caused edges to appear at incorrect widths and made the
size_edges()/size_vertices()API behave incorrectly or have no effect in certain modes.Bug 1 — Quadratic dependence on
u_PointSizeinGEOMETRY_SOURCE_LINE_WIDTHThe perpendicular offset vector was computed as:
and then scaled by
gs_in[i].pointSize = u_PointSize / effectiveDistance, making the actual half-width proportional tou_PointSize². For scenes with large bounding-box diagonals this produced edges far wider than intended, andsize_edges()had a super-linear effect.Fix: remove
u_PointSizefromn0so the half-width is linear:u_PointSize / (2 * effectiveDistance).Bug 2 — Orthographic mode always produced width 1.0
In
VERTEX_SOURCE_LINE_WIDTH, the orthographic branch setdistance = u_PointSize, sopointSize = u_PointSize / u_PointSize = 1.0. The user-specified size was silently ignored in every 2D viewer.Fix: use
distance = 1.0sopointSize = u_PointSizepasses through directly as a screen-pixel width.Bug 3 — Baked-in viewport dimensions
The
u_Viewportuniform was always uploaded as the initial window size{500, 450}:QVector2D viewport = { CGAL_BASIC_VIEWER_INIT_SIZE_X, CGAL_BASIC_VIEWER_INIT_SIZE_Y };After any window resize the NDC↔pixel conversions inside the geometry shader used stale dimensions, producing incorrect edge geometry.
Fix: use
this->width()/this->height()on every frame.Files changed
Basic_viewer/include/CGAL/Basic_shaders.h—VERTEX_SOURCE_LINE_WIDTH,GEOMETRY_SOURCE_LINE_WIDTHBasic_viewer/include/CGAL/Qt/Basic_viewer.h— viewport uniform in the edge-drawing rendererFixes #9327