Fix black 3D viewport when building with Qt6#1017
Fix black 3D viewport when building with Qt6#1017jenningsloy318 wants to merge 3 commits intoleozide:masterfrom
Conversation
The 3D viewport, brick thumbnails, and canvas were rendered entirely black when LeoCAD was built against Qt6, while the rest of the UI (menus, panels, timeline) worked normally. Root cause: Qt6's QOpenGLWidget internal FBO pipeline silently failed to render with the legacy GLSL 110 shaders using attribute/varying keywords, even though the OpenGL 4.6 Compatibility Profile context accepted them without errors. Changes: - Upgrade GLSL shader prefix from #version 110 to #version 330 core, replacing attribute/varying with in/out, gl_FragColor with an explicit out vec4 FragColor, and texture2D/textureCube with texture - Always initialize QSurfaceFormat with depth buffer (24-bit), stencil buffer (8-bit), and renderableType set to Desktop OpenGL, instead of only setting the format when anti-aliasing samples > 1. This ensures proper depth testing and prevents Qt6 EGL from creating an OpenGL ES context on NVIDIA - Guard Qt::AA_ShareOpenGLContexts with a Qt5 version check since it was removed in Qt6 - Remove unused QOpenGLFunctions_3_2_Core include (versionFunctions API was removed in Qt6) Tested on Linux (NVIDIA GTX 1070 Ti, driver 580.105.08) with Qt 6.x on Wayland-EGL. All 16 shaders compile and 8 programs link successfully. Viewport renders gradient background, brick geometry, part thumbnails, and view sphere correctly.
The previous commit hardcoded #version 330 core shaders which requires OpenGL 3.3+. This would break Qt5 builds on older hardware with only OpenGL 2.x or 3.0-3.2 support. Detect the GL version at runtime via QOpenGLContext::currentContext() format and select the appropriate shader prefix: - GL >= 3.3: Use #version 330 core with modern in/out syntax - GL < 3.3: Fall back to #version 110 with legacy attribute/varying Verified builds and renders correctly on both Qt5 and Qt6 with OpenGL 4.6 (NVIDIA). The legacy path preserves the original shader behavior for older GL contexts.
|
|
||
| lcInitializeSurfaceFormat(argc, argv); | ||
|
|
||
| #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) |
There was a problem hiding this comment.
We rely on shared contexts, it's supported in Qt6. The app crashes with this change.
| QCoreApplication Application(argc, argv); | ||
| const lcCommandLineOptions Options = lcApplication::ParseCommandLineOptions(); | ||
|
|
||
| QSurfaceFormat Format = QSurfaceFormat::defaultFormat(); |
There was a problem hiding this comment.
The original code here works better:
- We need to set the AA samples here for CLI rendering
- We don't need stencil, it may take precision away from the depth buffer depending on the driver
- We use GLES on iOS
|
I don't think the black screen you're seeing is directly related to Qt6, I've been using it for a while without problems on both Mac and Windows. |
|
I am not sure , but I am running under debian Linux 13 with lxqt 2.3 ( qt 6.8.2 and wayland/labwc). and these changes are modified by claude code, so i am not expert in this, can you please help me debug this ? |
|
This is something specific to your setup, so I can't help debug directly. See if reverting the changes to qtmain.cpp still work and we can take the shader changes only. |
Wrap the QSurfaceFormat::setRenderableType(QSurfaceFormat::OpenGL) call in #ifndef LC_OPENGLES so that iOS builds using OpenGL ES are not forced to desktop OpenGL, while Linux/Wayland with NVIDIA EGL still gets the explicit desktop OpenGL context needed to prevent a driver crash in libnvidia-eglcore.so during glDrawArrays.
|
Hi @leozide, I tried reverting all qtmain.cpp changes as you suggested, keeping only the shader changes. The black viewport returned — and it turned out to be a segfault inside The NVIDIA EGL driver on Wayland requires explicit depth/stencil buffer sizes for proper context creation. Here's how I addressed your concerns:
If the stencil or AA_ShareOpenGLContexts guard causes problems on Mac/Windows, we could platform-guard them with #ifdef Q_OS_LINUX. |
|
D24S8 definitely reduces precision compared to D32, it's 8 bits less for depth. Shared Contexts are a requirement as we don't create resources per context. Your driver may be sharing resources by default but it won't happen everywhere, this is not something that can be disabled on any platform. It would be interesting to try 1 change at a time to see what's actually fixing the black window for you. |

The 3D viewport, brick thumbnails, and canvas were rendered entirely black when LeoCAD was built against Qt6, while the rest of the UI (menus, panels, timeline) worked normally.
Root cause: Qt6's QOpenGLWidget internal FBO pipeline silently failed to render with the legacy GLSL 110 shaders using attribute/varying keywords, even though the OpenGL 4.6 Compatibility Profile context accepted them without errors.
Changes:
Upgrade GLSL shader prefix from #version 110 to #version 330 core, replacing attribute/varying with in/out, gl_FragColor with an explicit out vec4 FragColor, and texture2D/textureCube with texture
Always initialize QSurfaceFormat with depth buffer (24-bit), stencil buffer (8-bit), and renderableType set to Desktop OpenGL, instead of only setting the format when anti-aliasing samples > 1. This ensures proper depth testing and prevents Qt6 EGL from creating an OpenGL ES context on NVIDIA
Guard Qt::AA_ShareOpenGLContexts with a Qt5 version check since it was removed in Qt6
Remove unused QOpenGLFunctions_3_2_Core include (versionFunctions API was removed in Qt6)
Tested on Linux (NVIDIA GTX 1070 Ti, driver 580.105.08) with Qt 6.x on Wayland-EGL. All 16 shaders compile and 8 programs link successfully. Viewport renders gradient background, brick geometry, part thumbnails, and view sphere correctly.