From 996b388601605093be968aee52370c906f7297ae Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Thu, 13 Jul 2023 12:34:14 -0700 Subject: [PATCH] Make stencil mode selection more explicit to fix 3D mode with no stenciling (#1369) --- src/mbgl/gl/layer_group_gl.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index ea01eebeb..90ccb66b7 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -51,6 +51,8 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) // `stencilModeFor3D` uses a different stencil mask value each time its called, so if the // drawables in this layer use 3D stencil mode, we need to set it up here so that all the // drawables end up using the same mode value. + // 2D and 3D features in the same layer group is not supported. + bool features3d = false; bool stencil3d = false; gfx::StencilMode stencilMode3d; @@ -63,21 +65,27 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) // Collect the tile IDs relevant to stenciling and update the stencil buffer, if necessary. std::set tileIDs; observeDrawables([&](const gfx::Drawable& drawable) { - if (drawable.getEnabled() && drawable.getEnableStencil() && drawable.hasRenderPass(parameters.pass)) { - if (drawable.getIs3D()) { + if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) { + return; + } + if (drawable.getIs3D()) { + features3d = true; + if (drawable.getEnableStencil()) { stencil3d = true; } - if (!stencil3d && drawable.getTileID()) { - tileIDs.emplace(drawable.getTileID()->toUnwrapped()); - } + } + if (!features3d && drawable.getEnableStencil() && drawable.getTileID()) { + tileIDs.emplace(drawable.getTileID()->toUnwrapped()); } }); - // If we're doing 3D stenciling, set up the single-value stencil mask. - // If we're doing 2D stenciling, render each tile with a different value. - if (stencil3d) { - stencilMode3d = parameters.stencilModeFor3D(); - } else { + // If we're doing 3D stenciling and have any features + // to draw, set up the single-value stencil mask. + // If we're doing 2D stenciling and have any drawables with tile IDs, + // render each tile into the stencil buffer with a different value. + if (features3d) { + stencilMode3d = stencil3d ? parameters.stencilModeFor3D() : gfx::StencilMode::disabled(); + } else if (!tileIDs.empty()) { parameters.renderTileClippingMasks(tileIDs); } } @@ -105,7 +113,10 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) tweaker->execute(drawable, parameters); } - if (stencil3d) { + // For layer groups with 3D features, enable either the single-value + // stencil mode for features with stencil enabled or disable stenciling. + // 2D drawables will set their own stencil mode within `draw`. + if (features3d) { context.setStencilMode(drawable.getEnableStencil() ? stencilMode3d : gfx::StencilMode::disabled()); }