Fix projection matrix for raster image drawables (#2242)

This commit is contained in:
Stefan Karschti
2024-04-17 16:11:08 +03:00
committed by GitHub
parent e53143c902
commit 6919081030
10 changed files with 219 additions and 20 deletions

View File

@@ -62,6 +62,13 @@ protected:
/// Determine whether this tweaker should apply to the given drawable /// Determine whether this tweaker should apply to the given drawable
bool checkTweakDrawable(const gfx::Drawable&) const; bool checkTweakDrawable(const gfx::Drawable&) const;
/// Multiplies with the projection matrix (either default, near clipped or aligned) for the given drawable
static void multiplyWithProjectionMatrix(/*in-out*/ mat4& matrix,
const PaintParameters& parameters,
const gfx::Drawable& drawable,
bool nearClipped,
bool aligned);
std::string id; std::string id;
Immutable<style::LayerProperties> evaluatedProperties; Immutable<style::LayerProperties> evaluatedProperties;

View File

@@ -0,0 +1,35 @@
{
"network": [
[
"probeNetwork - default - end",
1,
48979
],
[
"probeNetwork - default - start",
0,
0
]
],
"gfx": [
[
"probeGFX - default - end",
13,
11,
19,
1,
[
1298436,
1298436
],
[
318,
318
],
[
236,
236
]
]
]
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -0,0 +1,109 @@
{
"version": 8,
"metadata": {
"test": {
"width": 456,
"height": 456
}
},
"center": [
-75.9705,
42.1865
],
"zoom": 5,
"sources": {
"image": {
"type": "image",
"url": "local://image/radar2.png",
"coordinates": [
[
-80.425,
46.437
],
[
-71.516,
46.437
],
[
-71.516,
37.936
],
[
-80.425,
37.936
]
]
},
"geojson": {
"type": "geojson",
"data": {
"type": "Polygon",
"coordinates": [
[
[
-80.425,
46.437
],
[
-71.516,
46.437
],
[
-71.516,
37.936
],
[
-80.425,
37.936
],
[
-80.425,
46.437
]
],
[
[
-78.425,
44.437
],
[
-78.425,
39.936
],
[
-73.516,
39.936
],
[
-73.516,
44.437
],
[
-78.425,
44.437
]
]
]
}
}
},
"layers": [
{
"id": "fill-opaque",
"type": "fill",
"source": "geojson",
"paint": {
"fill-color": "blue"
}
},
{
"id": "image-translucent",
"type": "raster",
"source": "image",
"paint": {
"raster-fade-duration": 0
}
}
]
}

View File

@@ -0,0 +1,35 @@
{
"network": [
[
"probeNetwork - default - end",
1,
48979
],
[
"probeNetwork - default - start",
0,
0
]
],
"gfx": [
[
"probeGFX - default - end",
13,
11,
19,
1,
[
1298436,
1298436
],
[
318,
318
],
[
236,
236
]
]
]
}

View File

@@ -32,7 +32,7 @@ mat4 LayerTweaker::getTileMatrix(const UnwrappedTileID& tileID,
style::TranslateAnchorType anchor, style::TranslateAnchorType anchor,
bool nearClipped, bool nearClipped,
bool inViewportPixelUnits, bool inViewportPixelUnits,
[[maybe_unused]] const gfx::Drawable& drawable, const gfx::Drawable& drawable,
bool aligned) { bool aligned) {
// from RenderTile::prepare // from RenderTile::prepare
mat4 tileMatrix; mat4 tileMatrix;
@@ -40,24 +40,7 @@ mat4 LayerTweaker::getTileMatrix(const UnwrappedTileID& tileID,
if (const auto& origin{drawable.getOrigin()}; origin.has_value()) { if (const auto& origin{drawable.getOrigin()}; origin.has_value()) {
matrix::translate(tileMatrix, tileMatrix, origin->x, origin->y, 0); matrix::translate(tileMatrix, tileMatrix, origin->x, origin->y, 0);
} }
multiplyWithProjectionMatrix(/*in-out*/ tileMatrix, parameters, drawable, nearClipped, aligned);
// nearClippedMatrix has near plane moved further, to enhance depth buffer precision
auto projMatrix = aligned ? parameters.transformParams.alignedProjMatrix
: (nearClipped ? parameters.transformParams.nearClippedProjMatrix
: parameters.transformParams.projMatrix);
#if !MLN_RENDER_BACKEND_OPENGL
// If this drawable is participating in depth testing, offset the
// projection matrix NDC depth range for the drawable's layer and sublayer.
if (!drawable.getIs3D() && drawable.getEnableDepth()) {
projMatrix[14] -= ((1 + drawable.getLayerIndex()) * PaintParameters::numSublayers -
drawable.getSubLayerIndex()) *
PaintParameters::depthEpsilon;
}
#endif
matrix::multiply(tileMatrix, projMatrix, tileMatrix);
return RenderTile::translateVtxMatrix( return RenderTile::translateVtxMatrix(
tileID, tileMatrix, translation, anchor, parameters.state, inViewportPixelUnits); tileID, tileMatrix, translation, anchor, parameters.state, inViewportPixelUnits);
} }
@@ -67,4 +50,31 @@ void LayerTweaker::updateProperties(Immutable<style::LayerProperties> newProps)
propertiesUpdated = true; propertiesUpdated = true;
} }
void LayerTweaker::multiplyWithProjectionMatrix(/*in-out*/ mat4& matrix,
const PaintParameters& parameters,
[[maybe_unused]] const gfx::Drawable& drawable,
bool nearClipped,
bool aligned) {
// nearClippedMatrix has near plane moved further, to enhance depth buffer precision
const auto& projMatrixRef = aligned ? parameters.transformParams.alignedProjMatrix
: (nearClipped ? parameters.transformParams.nearClippedProjMatrix
: parameters.transformParams.projMatrix);
#if !MLN_RENDER_BACKEND_OPENGL
// If this drawable is participating in depth testing, offset the
// projection matrix NDC depth range for the drawable's layer and sublayer.
if (!drawable.getIs3D() && drawable.getEnableDepth()) {
// copy and adjust the projection matrix
mat4 projMatrix = projMatrixRef;
projMatrix[14] -= ((1 + drawable.getLayerIndex()) * PaintParameters::numSublayers -
drawable.getSubLayerIndex()) *
PaintParameters::depthEpsilon;
// multiply with the copy
matrix::multiply(matrix, projMatrix, matrix);
// early return
return;
}
#endif
matrix::multiply(matrix, projMatrixRef, matrix);
}
} // namespace mbgl } // namespace mbgl

View File

@@ -55,8 +55,9 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup,
// this is an image drawable // this is an image drawable
if (const auto& data = drawable.getData()) { if (const auto& data = drawable.getData()) {
const gfx::ImageDrawableData& imageData = static_cast<const gfx::ImageDrawableData&>(*data); const gfx::ImageDrawableData& imageData = static_cast<const gfx::ImageDrawableData&>(*data);
matrix = imageData.matrix; matrix = imageData.matrix;
multiplyWithProjectionMatrix(
/*in-out*/ matrix, parameters, drawable, /*nearClipped*/ false, /*aligned*/ true);
} else { } else {
Log::Error(Event::General, "Invalid raster layer drawable: neither tile id nor image data is set."); Log::Error(Event::General, "Invalid raster layer drawable: neither tile id nor image data is set.");
return; return;

View File

@@ -101,7 +101,9 @@ void RenderImageSource::prepare(const SourcePrepareParameters& parameters) {
mat4& matrix = matrices[i]; mat4& matrix = matrices[i];
matrix::identity(matrix); matrix::identity(matrix);
transformParams.state.matrixFor(matrix, tileIds[i]); transformParams.state.matrixFor(matrix, tileIds[i]);
#if MLN_LEGACY_RENDERER
matrix::multiply(matrix, transformParams.alignedProjMatrix, matrix); matrix::multiply(matrix, transformParams.alignedProjMatrix, matrix);
#endif
} }
renderData = std::make_unique<ImageSourceRenderData>(bucket, std::move(matrices), baseImpl->id); renderData = std::make_unique<ImageSourceRenderData>(bucket, std::move(matrices), baseImpl->id);
} }