Skip to content

Fix CGAL::draw() black rendering on OpenGL < 4.3#9399

Open
RajdeepKushwaha5 wants to merge 5 commits intoCGAL:mainfrom
RajdeepKushwaha5:fix/compat-shaders-ogl-lt-4.3
Open

Fix CGAL::draw() black rendering on OpenGL < 4.3#9399
RajdeepKushwaha5 wants to merge 5 commits intoCGAL:mainfrom
RajdeepKushwaha5:fix/compat-shaders-ogl-lt-4.3

Conversation

@RajdeepKushwaha5
Copy link
Copy Markdown
Contributor

Summary of Changes

Fixes CGAL::draw() rendering solid black geometry on systems with OpenGL < 4.3 by correcting the compatibility GLSL shaders and improving OpenGL version detection.

Compatibility shader fixes (Basic_shaders.h):

  • VERTEX_SOURCE_COLOR_COMP: Changed varying to attribute for vertex inputs (a_Pos, a_Normal, a_Color). In GLSL 1.10/1.20, vertex shader inputs must use the attribute qualifier — varying is only for outputs passed to the fragment shader.
  • VERTEX_SOURCE_COLOR_COMP: Replaced the undefined mv_matrix variable with mat3(u_Mv) * a_Normal, using the already-declared u_Mv uniform (matching the OpenGL 4.3 shader path).
  • VERTEX_SOURCE_P_L_COMP: Changed varying to attribute for vertex inputs (a_Pos, a_Color), same fix as above.

OpenGL version detection fixes (qglviewer_impl.h):

  • defaultConstructor(): Initialize is_ogl_4_3 to false. Previously uninitialized, leading to undefined behavior.
  • initializeGL(): Fixed version check from format.majorVersion() != 4 to (format.majorVersion() < 4 || (format.majorVersion() == 4 && format.minorVersion() < 3)). The old check incorrectly classified OpenGL 4.0–4.2 as 4.3-capable and would have broken on future OpenGL 5+.

Diagnostic warning (Basic_viewer.h):

  • Added a std::cerr warning in compile_shaders() when compatibility shaders are selected, to aid debugging on OpenGL < 4.3 systems.

Release Management

The source variables CGAL_CXX_FLAGS_RELEASE, CGAL_CXX_FLAGS_DEBUG,
CGAL_MODULE_LINKER_FLAGS(_RELEASE|_DEBUG),
CGAL_SHARED_LINKER_FLAGS_RELEASE, CGAL_SHARED_LINKER_FLAGS_DEBUG,
CGAL_EXE_LINKER_FLAGS_RELEASE, and CGAL_EXE_LINKER_FLAGS_DEBUG
are never set anywhere in the codebase. The uniquely_add_flags()
macro is a complete no-op when its source argument is empty
(ARGC == 1 skips the body). Removing these 9 dead calls.

The 3 retained calls propagate variables that ARE populated:
- CGAL_CXX_FLAGS (MSVC, GCC, Intel, SunPro flags)
- CGAL_SHARED_LINKER_FLAGS (SunPro linker flags)
- CGAL_EXE_LINKER_FLAGS (SunPro linker flags)
Fix compatibility shaders and OpenGL version detection that caused
CGAL::draw() to render solid black geometry on systems with OpenGL < 4.3.

Basic_shaders.h:
- VERTEX_SOURCE_COLOR_COMP: change 'varying' to 'attribute' for vertex
  inputs (a_Pos, a_Normal, a_Color) as required by GLSL 1.10/1.20
- VERTEX_SOURCE_COLOR_COMP: replace undefined 'mv_matrix' reference with
  'mat3(u_Mv) * a_Normal' matching the declared uniform
- VERTEX_SOURCE_P_L_COMP: change 'varying' to 'attribute' for vertex
  inputs (a_Pos, a_Color)

qglviewer_impl.h:
- Initialize is_ogl_4_3 to false in defaultConstructor() to avoid UB
- Fix version check: use major < 4 || (major == 4 && minor < 3) instead
  of major != 4, so OpenGL 4.0-4.2 correctly falls back and 5+ works

Basic_viewer.h:
- Add std::cerr warning when compatibility shaders are selected
Copilot AI review requested due to automatic review settings March 24, 2026 10:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses incorrect rendering (solid black geometry) in CGAL::draw() on systems that don’t meet the “modern” OpenGL path requirements by fixing the compatibility GLSL shaders and adjusting OpenGL capability detection.

Changes:

  • Fix compatibility vertex shader inputs (attribute vs varying) and replace an undefined normal-transform matrix with mat3(u_Mv).
  • Initialize is_ogl_4_3 and update OpenGL version gating logic used to choose shader paths.
  • Add a diagnostic warning when compatibility shaders are selected.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
GraphicsView/include/CGAL/Qt/qglviewer_impl.h Initializes is_ogl_4_3 and changes OpenGL version check that drives shader-path selection.
Basic_viewer/include/CGAL/Qt/Basic_viewer.h Emits a warning when the compatibility shader path is used.
Basic_viewer/include/CGAL/Basic_shaders.h Fixes compatibility shader qualifiers and normal transform to avoid black rendering.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 207 to 212
QSurfaceFormat format = context()->format();
context()->format().setOption(QSurfaceFormat::DebugContext);
if ( !context()->isValid()
|| format.majorVersion() != 4
|| format.majorVersion() < 4
|| (format.majorVersion() == 4 && format.minorVersion() < 3)
|| QCoreApplication::arguments().contains(QStringLiteral("--old")))
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updated version check makes is_ogl_4_3 false for any desktop OpenGL context < 4.3 (e.g., macOS commonly provides 4.1 core via init_ogl_context), which will route execution to the compatibility shader path. Those compatibility shaders use attribute/varying and gl_FragColor without a #version, which won’t compile in core-profile desktop contexts (e.g., 4.1 core). Consider basing the decision on QSurfaceFormat::renderableType() / profile() (OpenGL ES vs desktop core) and/or GLSL version support, so desktop GL 3.2+ (including 4.1) continues using the modern #version 150 shaders.

Copilot uses AI. Check for mistakes.
@@ -206,7 +207,8 @@ void CGAL::QGLViewer::initializeGL() {
QSurfaceFormat format = context()->format();
context()->format().setOption(QSurfaceFormat::DebugContext);
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context()->format().setOption(QSurfaceFormat::DebugContext); modifies a temporary QSurfaceFormat (since format() returns by value), so it has no effect. If the intent is to enable a debug context, set the option on a QSurfaceFormat instance and apply it before context creation (e.g., via QSurfaceFormat::setDefaultFormat() or context()->setFormat(...) before create()).

Suggested change
context()->format().setOption(QSurfaceFormat::DebugContext);
format.setOption(QSurfaceFormat::DebugContext);
context()->setFormat(format);

Copilot uses AI. Check for mistakes.
Comment on lines +839 to +840
if (!isOpenGL_4_3())
{ std::cerr<<"CGAL Basic_viewer: OpenGL < 4.3 detected, using compatibility shaders"<<std::endl; }
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds an unconditional std::cerr message whenever compatibility shaders are selected. Since Basic_viewer.h is a public header and compile_shaders() is called during normal initialization, this can introduce noisy stderr output for end users. Consider using CGAL_warning_msg / qWarning() and/or guarding the message behind a verbosity/debug flag (or emitting it only once).

Suggested change
if (!isOpenGL_4_3())
{ std::cerr<<"CGAL Basic_viewer: OpenGL < 4.3 detected, using compatibility shaders"<<std::endl; }
static bool s_ogl_warning_emitted = false;
if (!isOpenGL_4_3() && !s_ogl_warning_emitted)
{
CGAL_warning_msg("CGAL Basic_viewer: OpenGL < 4.3 detected, using compatibility shaders");
s_ogl_warning_emitted = true;
}

Copilot uses AI. Check for mistakes.
- Version check: revert to majorVersion() < 4 instead of checking for
  specifically 4.3. On macOS, init_ogl_context() caps to 4.1 core
  profile; compat shaders (attribute/varying) would fail in core
  contexts. The #version 150 modern shaders work fine on any 4.x.
  This also correctly handles future OpenGL 5+.
- Warning: use static guard so the message emits only once, even if
  compile_shaders() is called multiple times.
@afabri
Copy link
Copy Markdown
Member

afabri commented Mar 24, 2026

Hello, I had hoped your pull request fixes that depending on the system edges of polygons, are not drawn.
When I compile Polygon/examples/Polygon/draw_polygon.cpp and execute it I see this.
image
On the console it says "Using OpenGL context 4.3 GL"

…ead g_Color, add OGL<4.3 edge fallback

- Add bindAttributeLocation(a_Pos, 0) and bindAttributeLocation(a_Color, 1)
  before link() for rendering_program_p_l, rendering_program_line, and
  rendering_program_cylinder to guarantee consistent attribute locations
  across all OpenGL drivers.
- Remove dead 'in mediump vec4 g_Color[]' from GEOMETRY_SOURCE_LINE_WIDTH
  geometry shader (no matching vertex shader output).
- Add proper edge rendering fallback via rendering_program_p_l for
  OpenGL < 4.3 where the geometry shader is unavailable.
- Re-add minor version check for OpenGL 4.0-4.2 in qglviewer_impl.h.
@RajdeepKushwaha5
Copy link
Copy Markdown
Contributor Author

Hi Sir, @afabri Thanks for reporting this, and for the screenshot — very helpful.

I looked into this and the missing edges you're seeing is actually a pre-existing bug on main, not something introduced by this PR. I can reproduce-ish: on my system (also OpenGL 4.3), edges render fine on all three versions — main, my original PR, and the updated branch — so the bug is driver-dependent.

MAIN (clean main branch):

main

BEFORE (original PR commits only):

before_pr

AFTER (PR + edge fixes):

after_PR

As you can see, all three look identical on my end — edges show up fine. So I can't visually reproduce the missing edges on my hardware, but I traced the root cause in code:

VAO_SEGMENTS gets its vertex attribute arrays (a_Pos, a_Color) set up under rendering_program_p_l, but edges are actually drawn using rendering_program_line (the geometry shader path for thick lines). Without explicit bindAttributeLocation() calls, the OpenGL driver assigns attribute locations independently per shader program. If they end up different between the two programs — which clearly happens on your driver but not mine — the VAO feeds position data into the color slot and vice versa, resulting in invisible edges.

The latest push adds fixes for this:

  1. bindAttributeLocation("a_Pos", 0) and bindAttributeLocation("a_Color", 1) before link() for rendering_program_p_l, rendering_program_line, and rendering_program_cylinder — pins attribute locations so they're consistent regardless of driver behavior.
  2. Removed a dead in mediump vec4 g_Color[] from the geometry shader that had no matching vertex shader output.
  3. Added a proper fallback path so edges render via rendering_program_p_l on OpenGL < 4.3 where the geometry shader isn't available.

Could you give it another try with the latest push and let me know if edges show up now?

@afabri
Copy link
Copy Markdown
Member

afabri commented Mar 24, 2026

You are right that it was a pre-existing bug. And you fixed it. Great.

@RajdeepKushwaha5
Copy link
Copy Markdown
Contributor Author

You are right that it was a pre-existing bug. And you fixed it. Great.

Thanks for confirming! Glad it's working now.
Let me know if there's anything else you'd like me to adjust in this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The function 'CGAL::draw' shows black triangle instead of polygon

3 participants