From 1c2e61126b6e098e0d2930c91181fff58ebc0fe8 Mon Sep 17 00:00:00 2001 From: fuzhenn Date: Fri, 5 Sep 2025 16:30:38 +0800 Subject: [PATCH 1/4] add terrain mask specs --- debug/gl/terrain-mask.html | 15 +++--- .../gl/src/layer/terrain/TerrainLitPainter.js | 10 +++- .../reshader.gl/src/pbr/glsl/standard.vert | 7 ++- .../src/pbr/wgsl/standard_vert.wgsl | 6 ++- .../src/shaderlib/glsl/output.vert | 15 +++++- .../src/shaderlib/wgsl/common_pack_float.ts | 28 ++++++++++ .../reshader.gl/src/shaderlib/wgsl/output.ts | 14 +++++ .../vt/src/layer/layer/VectorTileLayer.ts | 3 ++ .../terrain/terrain-lit-mask/expected.png | Bin 0 -> 9467 bytes .../terrain/terrain-lit-mask/index.js | 49 ++++++++++++++++++ .../terrain/terrain-mask/expected.png | Bin 0 -> 1508 bytes .../fixtures/terrain/terrain-mask/index.js | 48 +++++++++++++++++ packages/vt/test/integration/terrain.spec.js | 15 +++++- 13 files changed, 198 insertions(+), 12 deletions(-) create mode 100644 packages/vt/test/integration/fixtures/terrain/terrain-lit-mask/expected.png create mode 100644 packages/vt/test/integration/fixtures/terrain/terrain-lit-mask/index.js create mode 100644 packages/vt/test/integration/fixtures/terrain/terrain-mask/expected.png create mode 100644 packages/vt/test/integration/fixtures/terrain/terrain-mask/index.js diff --git a/debug/gl/terrain-mask.html b/debug/gl/terrain-mask.html index f96c2c79d7..15318de935 100644 --- a/debug/gl/terrain-mask.html +++ b/debug/gl/terrain-mask.html @@ -31,6 +31,7 @@ "zoom": 13, "pitch": 10, "bearing": 0, + renderer: 'gl', queryTerrainInMapEvents: false }); @@ -51,6 +52,7 @@ const terrain = { debug: true, + shader: 'lit', type: "mapbox", urlTemplate: `https://{s}.tiles.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=${token}`, subdomains: ["a", "b", "c", "d"] @@ -65,11 +67,11 @@ type: "Polygon", coordinates: [ [ - [94.50812103, 29.45095163, 3000], - [94.59012103, 29.45095163, 3000], - [94.59012103, 29.40095163, 3000], - [94.50812103, 29.40095163, 3000], - [94.50812103, 29.45095163, 3000] + [94.50812103, 29.45095163, 0], + [94.59012103, 29.45095163, 0], + [94.59012103, 29.40095163, 0], + [94.50812103, 29.40095163, 0], + [94.50812103, 29.45095163, 0] ] ] }, @@ -99,11 +101,10 @@ renderPlugin: { dataConfig: { type: "fill", + altitudeOffset: 3000 }, sceneConfig: {}, type: "terrain-flat-mask", - }, - symbol: { } } ] diff --git a/packages/gl/src/layer/terrain/TerrainLitPainter.js b/packages/gl/src/layer/terrain/TerrainLitPainter.js index 1e98fdaa27..6d0f645e24 100644 --- a/packages/gl/src/layer/terrain/TerrainLitPainter.js +++ b/packages/gl/src/layer/terrain/TerrainLitPainter.js @@ -105,11 +105,16 @@ class TerrainLitPainter extends TerrainPainter { const material = new reshader.pbr.StandardMaterial(matInfo); const mesh = new reshader.Mesh(geo, material); mesh.properties.matVer = this._matVer; + if (!mesh.uniforms.flatMask) { + const emptyTexture = this.getEmptyTexture(); + mesh.setUniform('flatMask', emptyTexture); + } const defines = mesh.defines; defines['HAS_UV_FLIP'] = 1; defines['HAS_TERRAIN_NORMAL'] = 1; defines['HAS_MAP'] = 1; defines['HAS_LAYER_OPACITY'] = 1; + defines['HAS_TERRAIN_FLAT_MASK'] = 1; mesh.defines = defines; // mesh.setUniform('terrainTileResolution', tileInfo.res); this.prepareMesh(mesh, tileInfo, terrainImage); @@ -126,7 +131,10 @@ class TerrainLitPainter extends TerrainPainter { mesh.properties.matVer = this._matVer; } if (tileImage.skin) { - mesh.material.set('skinTexture', tileImage.skin); + mesh.material.set('skinTexture', tileImage.skin.color[0]); + } + if (tileImage.mask) { + mesh.setUniform('flatMask', tileImage.mask.color[0]); } mesh.setUniform('polygonOpacity', 1.0); // const { skirtOffset, skirtCount } = mesh.properties; diff --git a/packages/reshader.gl/src/pbr/glsl/standard.vert b/packages/reshader.gl/src/pbr/glsl/standard.vert index 3d1e342aa0..8d56c5ef30 100644 --- a/packages/reshader.gl/src/pbr/glsl/standard.vert +++ b/packages/reshader.gl/src/pbr/glsl/standard.vert @@ -4,8 +4,13 @@ precision highp float; attribute vec3 aPosition; -#if defined(HAS_MAP) +#if defined(HAS_NORMAL) || defined(HAS_TERRAIN_FLAT_MASK) attribute vec2 aTexCoord; + #include +#endif + +#if defined(HAS_MAP) + uniform vec2 uvOrigin; uniform vec2 uvScale; uniform vec2 uvOffset; diff --git a/packages/reshader.gl/src/pbr/wgsl/standard_vert.wgsl b/packages/reshader.gl/src/pbr/wgsl/standard_vert.wgsl index 51defac84f..702578b99b 100644 --- a/packages/reshader.gl/src/pbr/wgsl/standard_vert.wgsl +++ b/packages/reshader.gl/src/pbr/wgsl/standard_vert.wgsl @@ -8,6 +8,7 @@ #include #endif #include +#include struct VertexInput { #ifdef POSITION_IS_INT @@ -16,8 +17,11 @@ struct VertexInput { @location($i) aPosition: vec3f, #endif - #if HAS_MAP + #if HAS_MAP || HAS_TERRAIN_FLAT_MASK @location($i) aTexCoord: vec2f, + #endif + #if HAS_MAP + #ifdef HAS_I3S_UVREGION @location($i) uvRegion: vec4f, #endif diff --git a/packages/reshader.gl/src/shaderlib/glsl/output.vert b/packages/reshader.gl/src/shaderlib/glsl/output.vert index c9fcada760..35fe7804d9 100644 --- a/packages/reshader.gl/src/shaderlib/glsl/output.vert +++ b/packages/reshader.gl/src/shaderlib/glsl/output.vert @@ -69,7 +69,11 @@ mat4 getPositionMatrix() { } #ifdef HAS_MIN_ALTITUDE -uniform float minAltitude; + uniform float minAltitude; +#endif + +#ifdef HAS_TERRAIN_FLAT_MASK + uniform sampler2D flatMask; #endif vec4 getPosition(vec3 aPosition) { @@ -84,6 +88,15 @@ vec4 getPosition(vec3 aPosition) { #ifdef HAS_TERRAIN_ALTITUDE POSITION.z += aTerrainAltitude * 100.0; #endif + #ifdef HAS_TERRAIN_FLAT_MASK + vec2 uv = aTexCoord; + uv.y = 1.0 - uv.y; + vec4 encodedHeight = texture2D(flatMask, uv); + if (length(encodedHeight) < 2.0) { + float maskHeight = decodeFloat32(encodedHeight); + POSITION.z = min(POSITION.z, maskHeight); + } + #endif #ifdef HAS_MIN_ALTITUDE POSITION.z += minAltitude * 100.0; #endif diff --git a/packages/reshader.gl/src/shaderlib/wgsl/common_pack_float.ts b/packages/reshader.gl/src/shaderlib/wgsl/common_pack_float.ts index cb8fefceb5..809133f8cb 100644 --- a/packages/reshader.gl/src/shaderlib/wgsl/common_pack_float.ts +++ b/packages/reshader.gl/src/shaderlib/wgsl/common_pack_float.ts @@ -67,6 +67,34 @@ fn common_encodeDepth(depth: f32) -> vec4f { fn common_decodeDepth(pack: vec4f) -> f32 { return pack.r + pack.g / 255.0; } + +// https://cloud.tencent.com/developer/ask/sof/103481834 +fn encodeFloat32(f: f32) -> vec4f { + var e = 5.0; + + var F = abs(f); + var Sign = step(0.0, -f); + var Exponent = floor(log2(F)); + var Mantissa = (exp2(- Exponent) * F); + Exponent = floor(log2(F) + 127.0) + floor(log2(Mantissa)); + var rgba = vec4(0.0); + rgba[0] = 128.0 * Sign + floor(Exponent*exp2(-1.0)); + rgba[1] = 128.0 * mod(Exponent,2.0) + mod(floor(Mantissa*128.0),128.0); + rgba[2] = floor(mod(floor(Mantissa*exp2(23.0 -8.0)),exp2(8.0))); + rgba[3] = floor(exp2(23.0)*mod(Mantissa,exp2(-15.0))); + return rgba / 255.0; +} + +fn decodeFloat32(rgba: vec4f) -> f32 { + rgba *= 255.0; + var Sign = 1.0 - step(128.0,rgba[0])*2.0; + var Exponent = 2.0 * mod(rgba[0],128.0) + step(128.0,rgba[1]) - 127.0; + var Mantissa = mod(rgba[1],128.0)*65536.0 + rgba[2]*256.0 +rgba[3] + float(0x800000); + var Result = Sign * exp2(Exponent) * (Mantissa * exp2(-23.0 )); + return Result; +} + + `; const frag = vert; diff --git a/packages/reshader.gl/src/shaderlib/wgsl/output.ts b/packages/reshader.gl/src/shaderlib/wgsl/output.ts index ce5d6d108e..169442dd2b 100644 --- a/packages/reshader.gl/src/shaderlib/wgsl/output.ts +++ b/packages/reshader.gl/src/shaderlib/wgsl/output.ts @@ -31,6 +31,11 @@ const vert = /* wgsl */` @group(0) @binding($b) var altitudeUniforms: AltitudeUniforms; #endif +#ifdef HAS_TERRAIN_FLAT_MASK + @group(0) @binding($b) var flatMask: texture_2d; + @group(0) @binding($b) var flatMaskSampler: sampler; +#endif + fn getPositionMatrix(input: VertexInput, vertexOutput: ptr, positionMatrix: mat4x4f) -> mat4x4f { var worldMatrix: mat4x4f; #ifdef HAS_INSTANCE @@ -79,6 +84,15 @@ fn getPosition(inputPosition: vec3f, vertexInput: VertexInput) -> vec4f { #ifdef HAS_TERRAIN_ALTITUDE outputPosition.z += vertexInput.aTerrainAltitude * 100.0; #endif + #ifdef HAS_TERRAIN_FLAT_MASK + var uv = aTexCoord; + uv.y = 1.0 - uv.y; + let encodedHeight = textureSample(flatMask, flatMaskSampler, uv); + if (length(encodedHeight) < 2.0) { + float maskHeight = decodeFloat32(encodedHeight); + outputPosition.z = min(outputPosition.z, maskHeight); + } + #endif #ifdef HAS_MIN_ALTITUDE outputPosition.z += altitudeUniforms.minAltitude * 100.0; #endif diff --git a/packages/vt/src/layer/layer/VectorTileLayer.ts b/packages/vt/src/layer/layer/VectorTileLayer.ts index 75abdf06e8..2df1806870 100644 --- a/packages/vt/src/layer/layer/VectorTileLayer.ts +++ b/packages/vt/src/layer/layer/VectorTileLayer.ts @@ -1291,6 +1291,9 @@ class VectorTileLayer extends maptalks.TileLayer { ) { throw new Error(`Invalid filter at ${i} : ${JSON.stringify(filter)}`); } + if (!styles[i].symbol) { + styles[i].symbol = {}; + } //TODO 如果定义了renderPlugin就必须定义symbol } } diff --git a/packages/vt/test/integration/fixtures/terrain/terrain-lit-mask/expected.png b/packages/vt/test/integration/fixtures/terrain/terrain-lit-mask/expected.png new file mode 100644 index 0000000000000000000000000000000000000000..2b00d505a62ea407f5a1a00572d65f2767d68f91 GIT binary patch literal 9467 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 hB?Elb%Eq#Bnytkw)o4dtkNIsw$civg { let map, container, server; const containerSize = 128; @@ -76,18 +78,29 @@ describe('vector tile on terrain integration specs', () => { fadeAnimation: false // shader: 'lit' }; + if (style.lit) { + terrain.shader = 'lit'; + } const group = new GroupGLLayer('group', [layer], { terrain }); group.addTo(map); + const terrainLayer = group.getTerrainLayer(); let count = 0; let ended = false; terrainLayer.on('terrainreadyandrender', () => { count++; - const canvas = map.getRenderer().canvas; + const mapCanvas = map.getRenderer().canvas; const expectedPath = style.expected; if (!ended && count >= limit) { ended = true; + + const canvas = TEST_CANVAS; + canvas.width = mapCanvas.width; + canvas.height = mapCanvas.height; + const ctx = canvas.getContext('2d'); + ctx.drawImage(mapCanvas, 0, 0); + //比对测试 match(canvas, expectedPath, (err, result) => { if (err) { From ba518ae8c13e0120cbb0a09b9e02c053cf45c8a0 Mon Sep 17 00:00:00 2001 From: fuzhenn Date: Fri, 5 Sep 2025 16:52:32 +0800 Subject: [PATCH 2/4] fixing specs --- packages/reshader.gl/src/pbr/glsl/standard.vert | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/reshader.gl/src/pbr/glsl/standard.vert b/packages/reshader.gl/src/pbr/glsl/standard.vert index 8d56c5ef30..674251014d 100644 --- a/packages/reshader.gl/src/pbr/glsl/standard.vert +++ b/packages/reshader.gl/src/pbr/glsl/standard.vert @@ -4,7 +4,7 @@ precision highp float; attribute vec3 aPosition; -#if defined(HAS_NORMAL) || defined(HAS_TERRAIN_FLAT_MASK) +#if defined(HAS_MAP) || defined(HAS_TERRAIN_FLAT_MASK) attribute vec2 aTexCoord; #include #endif From e208c5fd3806a5e56f95231746a7e0abf9344767 Mon Sep 17 00:00:00 2001 From: fuzhenn Date: Fri, 5 Sep 2025 17:29:20 +0800 Subject: [PATCH 3/4] fixing specs --- packages/vt/test/integration/terrain.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vt/test/integration/terrain.spec.js b/packages/vt/test/integration/terrain.spec.js index 21a641bb51..fb14ec4a2b 100644 --- a/packages/vt/test/integration/terrain.spec.js +++ b/packages/vt/test/integration/terrain.spec.js @@ -53,6 +53,7 @@ describe('vector tile on terrain integration specs', () => { options.lights = DEFAULT_VIEW.lights; } options.devicePixelRatio = 1; + options.renderer = 'canvas'; const limit = style.renderingCount || 6; map = new maptalks.Map(container, options); From 2f3b7771c35821a6c3f8baf456ec2adfd688628c Mon Sep 17 00:00:00 2001 From: fuzhenn Date: Fri, 5 Sep 2025 18:01:54 +0800 Subject: [PATCH 4/4] fixing specs --- packages/vt/test/specs/update.vector.symbol.spec.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/vt/test/specs/update.vector.symbol.spec.js b/packages/vt/test/specs/update.vector.symbol.spec.js index 25d26340fd..9950a72999 100644 --- a/packages/vt/test/specs/update.vector.symbol.spec.js +++ b/packages/vt/test/specs/update.vector.symbol.spec.js @@ -73,6 +73,7 @@ describe('vector layers symbol update specs', () => { count++; }); let updated = false; + let doneCalled = false; group.on('layerload', () => { if (count >= 1 && !updated) { const pixel = readPixel(layer.getRenderer().canvas, x + 20, y); @@ -83,11 +84,12 @@ describe('vector layers symbol update specs', () => { markerHeight: 60 }); updated = true; - } else if (updated && count >= 4) { + } else if (updated && count >= 4 && !doneCalled) { const pixel = readPixel(renderer.canvas, x + 20, y); //中心点往外40,能读到像素了 assert.deepEqual(pixel, [255, 0, 0, 255]); assert(!partialUpdate); + doneCalled = true; done(); } }); @@ -123,6 +125,7 @@ describe('vector layers symbol update specs', () => { }); let updated = false; let partialUpdate = false; + let doneCalled = false; layer.on('partialupdate', () => { partialUpdate = true; }); @@ -151,12 +154,13 @@ describe('vector layers symbol update specs', () => { }, ]); updated = true; - } else if (updated && count >= 3) { + } else if (updated && count >= 3 && !doneCalled) { const pixel = readPixel(renderer.canvas, x + 20, y); assert.deepEqual(pixel, [0, 255, 0, 255]); const pixel1 = readPixel(renderer.canvas, x, y); assert.deepEqual(pixel1, [255, 0, 0, 255]); assert(!partialUpdate); + doneCalled = true; done(); } });