Skip to content

Commit d543526

Browse files
astojiljgithub-actions[bot]
authored andcommitted
Front cutoff properties for fill extrusions and buildings.
source-max-zoom layout property. (internal-11356) GitOrigin-RevId: 1c29f1223670427f4547d02ecab8ba2ca77bd1fb
1 parent e61deb0 commit d543526

File tree

113 files changed

+47763
-196
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+47763
-196
lines changed

3d-style/data/bucket/building_bucket.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -840,13 +840,20 @@ export class BuildingBucket implements BucketWithGroundEffect {
840840
building.layoutColorArray.uint16[(partVertexOffset + v) * 2 + 1] = c2;
841841
}
842842

843-
const cx = Math.floor(centroid.x);
844-
const cy = Math.floor(centroid.y);
843+
const cx = Math.min(8191, Math.max(0, Math.floor(centroid.x)));
844+
const cy = Math.min(8191, Math.max(0, Math.floor(centroid.y)));
845845
const ch = Math.floor(height);
846+
// Encode span (2 bits per axis) into lower bits of cx/cy: encoded = cx * 4 + spanBits
847+
// Each span bit represents ~20 meters; max 3 bits = ~60m
848+
const spanBucketMeters = 20;
849+
const spanX = Math.min(3, Math.round((bboxMax.x - bboxMin.x) * this.tileToMeter / spanBucketMeters));
850+
const spanY = Math.min(3, Math.round((bboxMax.y - bboxMin.y) * this.tileToMeter / spanBucketMeters));
851+
const cxEncoded = cx * 4 + spanX;
852+
const cyEncoded = cy * 4 + spanY;
846853
for (let v = 0; v < partVertexCount; ++v) {
847854
const idx = (partVertexOffset + v) * 3;
848-
building.layoutCentroidArray.int16[idx] = cx;
849-
building.layoutCentroidArray.int16[idx + 1] = cy;
855+
building.layoutCentroidArray.int16[idx] = cxEncoded;
856+
building.layoutCentroidArray.int16[idx + 1] = cyEncoded;
850857
building.layoutCentroidArray.int16[idx + 2] = ch;
851858
}
852859

3d-style/render/draw_building.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import StencilMode from '../../src/gl/stencil_mode';
88
import {getMetersPerPixelAtLatitude} from '../../src/geo/mercator_coordinate';
99
import {Debug} from '../../src/util/debug';
1010
import {DevTools} from '../../src/ui/devtools';
11-
import {drawGroundEffect as fillExtrusionDrawGroundEffect, GroundEffectProperties, frustumCullShadowCaster} from '../../src/render/draw_fill_extrusion';
11+
import {drawGroundEffect as fillExtrusionDrawGroundEffect, GroundEffectProperties, frustumCullShadowCaster, computeFrontCutoffParams} from '../../src/render/draw_fill_extrusion';
1212
import Color from '../../src/style-spec/util/color';
1313
import ColorMode from '../../src/gl/color_mode';
1414
import {PerformanceUtils} from '../../src/util/performance';
@@ -55,6 +55,14 @@ function drawTiles(params: DrawParams) {
5555
defines = defines.concat('RENDER_CUTOFF');
5656
}
5757

58+
const frontCutoffArray = layer.paint.get('building-front-cutoff');
59+
const frontCutoffEnabled = frontCutoffArray[2] < 1.0 && !painter.terrain;
60+
const frontCutoffParams = computeFrontCutoffParams(painter.transform.pitch, frontCutoffArray, !!painter.terrain);
61+
if (frontCutoffEnabled) {
62+
defines = defines.concat('RENDER_FRONT_CUTOFF');
63+
painter.maxFrontCutoffRawStart = Math.max(painter.maxFrontCutoffRawStart, frontCutoffArray[0]);
64+
}
65+
5866
if (params.floodLightIntensity > 0.0) {
5967
defines = defines.concat('FLOOD_LIGHT');
6068
}
@@ -120,7 +128,7 @@ function drawTiles(params: DrawParams) {
120128
mercCameraPos.z * tiles * EXTENT
121129
];
122130

123-
uniformValues = buildingUniformValues(matrix, normalMatrix, params.opacity, params.facadeAOIntensity, cameraPos, bucket.tileToMeter, params.facadeEmissiveChance, params.floodLightColor, params.floodLightIntensity);
131+
uniformValues = buildingUniformValues(matrix, normalMatrix, params.opacity, params.facadeAOIntensity, cameraPos, bucket.tileToMeter, params.facadeEmissiveChance, params.floodLightColor, params.floodLightIntensity, frontCutoffParams);
124132

125133
programWithoutFacades = painter.getOrCreateProgram('building',
126134
{config: programConfiguration, defines, overrideFog: false});
@@ -225,7 +233,7 @@ class DrawBuildingsDebugParams {
225233
}
226234
}
227235

228-
function drawGroundEffect(painter: Painter, source: SourceCache, layer: BuildingStyleLayer, coords: Array<OverscaledTileID>, aoPass: boolean, opacity: number, aoIntensity: number, aoRadius: number, floodLightIntensity: number, floodLightColor: [number, number, number], attenuationFactor: number, replacementActive: boolean, renderNeighbors: boolean) {
236+
function drawGroundEffect(painter: Painter, source: SourceCache, layer: BuildingStyleLayer, coords: Array<OverscaledTileID>, aoPass: boolean, opacity: number, aoIntensity: number, aoRadius: number, floodLightIntensity: number, floodLightColor: [number, number, number], attenuationFactor: number, replacementActive: boolean, renderNeighbors: boolean, frontCutoffParams?: [number, number, number]) {
229237
const lerp = (a: number, b: number, t: number) => { return (1 - t) * a + t * b; };
230238

231239
const gl = painter.context.gl;
@@ -242,15 +250,15 @@ function drawGroundEffect(painter: Painter, source: SourceCache, layer: Building
242250
const stencilSdfPass = new StencilMode({func: gl.ALWAYS, mask: 0xFF}, 0xFF, 0xFF, gl.KEEP, gl.KEEP, gl.REPLACE);
243251
const colorSdfPass = new ColorMode([gl.ONE, gl.ONE, gl.ONE, gl.ONE], Color.transparent, [false, false, false, true], gl.MIN);
244252

245-
fillExtrusionDrawGroundEffect(groundEffectProps, painter, source, layer, coords, depthMode, stencilSdfPass, colorSdfPass, CullFaceMode.disabled, aoPass, 'sdf', opacity, aoIntensity, aoRadius, floodLightIntensity, floodLightColor, attenuation, conflateLayer, false);
253+
fillExtrusionDrawGroundEffect(groundEffectProps, painter, source, layer, coords, depthMode, stencilSdfPass, colorSdfPass, CullFaceMode.disabled, aoPass, 'sdf', opacity, aoIntensity, aoRadius, floodLightIntensity, floodLightColor, attenuation, conflateLayer, false, undefined, frontCutoffParams);
246254
}
247255

248256
{
249257
// Draw the effects.
250258
const stencilColorPass = showOverdraw ? StencilMode.disabled : new StencilMode({func: gl.EQUAL, mask: 0xFF}, 0xFF, 0xFF, gl.KEEP, gl.DECR, gl.DECR);
251259
const colorColorPass = showOverdraw ? painter.colorModeForRenderPass() : new ColorMode([gl.ONE_MINUS_DST_ALPHA, gl.DST_ALPHA, gl.ONE, gl.ONE], Color.transparent, [true, true, true, true]);
252260

253-
fillExtrusionDrawGroundEffect(groundEffectProps, painter, source, layer, coords, depthMode, stencilColorPass, colorColorPass, CullFaceMode.disabled, aoPass, 'color', opacity, aoIntensity, aoRadius, floodLightIntensity, floodLightColor, attenuation, conflateLayer, false);
261+
fillExtrusionDrawGroundEffect(groundEffectProps, painter, source, layer, coords, depthMode, stencilColorPass, colorColorPass, CullFaceMode.disabled, aoPass, 'color', opacity, aoIntensity, aoRadius, floodLightIntensity, floodLightColor, attenuation, conflateLayer, false, undefined, frontCutoffParams);
254262
}
255263
}
256264

@@ -422,11 +430,14 @@ function draw(painter: Painter, source: SourceCache, layer: BuildingStyleLayer,
422430
floodLightColor
423431
});
424432

433+
const geFrontCutoffArray = layer.paint.get('building-front-cutoff');
434+
const geFrontCutoffParams = computeFrontCutoffParams(painter.transform.pitch, geFrontCutoffArray, !!painter.terrain);
435+
425436
if (aoEnabled) {
426-
drawGroundEffect(painter, source, layer, coords, true, opacity, aoIntensity, aoRadius, floodLightIntensity, floodLightColor, aoGroundAttenuation, conflateLayer, false);
437+
drawGroundEffect(painter, source, layer, coords, true, opacity, aoIntensity, aoRadius, floodLightIntensity, floodLightColor, aoGroundAttenuation, conflateLayer, false, geFrontCutoffParams);
427438
}
428439
if (floodLightEnabled) {
429-
drawGroundEffect(painter, source, layer, coords, false, opacity, aoIntensity, aoRadius, floodLightIntensity, floodLightColor, floodLightGroundAttenuation, conflateLayer, false);
440+
drawGroundEffect(painter, source, layer, coords, false, opacity, aoIntensity, aoRadius, floodLightIntensity, floodLightColor, floodLightGroundAttenuation, conflateLayer, false, geFrontCutoffParams);
430441
}
431442
} else if (painter.renderPass === 'light-beam' && drawLayer) {
432443
const definesForPass: Array<DynamicDefinesType> = [

3d-style/render/program/building_program.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ export type BuildingUniformsType = {
1414
['u_facade_emissive_chance']: Uniform1f;
1515
['u_flood_light_color']: Uniform3f;
1616
['u_flood_light_intensity']: Uniform1f;
17+
['u_front_cutoff_params']: Uniform3f;
1718
};
1819

19-
export type BuildingDefinesType = 'DEBUG_SHOW_NORMALS' | 'HAS_ATTRIBUTE_a_part_color_emissive' | 'HAS_ATTRIBUTE_a_bloom_attenuation' | 'BUILDING_FAUX_FACADE' | 'HAS_ATTRIBUTE_a_faux_facade_color_emissive';
20+
export type BuildingDefinesType = 'DEBUG_SHOW_NORMALS' | 'HAS_ATTRIBUTE_a_part_color_emissive' | 'HAS_ATTRIBUTE_a_bloom_attenuation' | 'BUILDING_FAUX_FACADE' | 'HAS_ATTRIBUTE_a_faux_facade_color_emissive' | 'RENDER_FRONT_CUTOFF';
2021

2122
const buildingUniforms = (context: Context): BuildingUniformsType => ({
2223
'u_matrix': new UniformMatrix4f(context),
@@ -28,9 +29,10 @@ const buildingUniforms = (context: Context): BuildingUniformsType => ({
2829
'u_facade_emissive_chance': new Uniform1f(context),
2930
'u_flood_light_color': new Uniform3f(context),
3031
'u_flood_light_intensity': new Uniform1f(context),
32+
'u_front_cutoff_params': new Uniform3f(context),
3133
});
3234

33-
const buildingUniformValues = (matrix: mat4, normalMatrix: mat4, opacity: number, aoIntensity: number, cameraPos: [number, number, number], tileToMeter: number, emissiveChance: number, floodLightColor: [number, number, number], floodLightIntensity: number): UniformValues<BuildingUniformsType> => {
35+
const buildingUniformValues = (matrix: mat4, normalMatrix: mat4, opacity: number, aoIntensity: number, cameraPos: [number, number, number], tileToMeter: number, emissiveChance: number, floodLightColor: [number, number, number], floodLightIntensity: number, frontCutoffParams: [number, number, number] = [0, 0, 1]): UniformValues<BuildingUniformsType> => {
3436
const uniformValues = {
3537
'u_matrix': matrix as Float32Array,
3638
'u_normal_matrix': normalMatrix as Float32Array,
@@ -41,6 +43,7 @@ const buildingUniformValues = (matrix: mat4, normalMatrix: mat4, opacity: number
4143
'u_facade_emissive_chance': emissiveChance,
4244
'u_flood_light_color': floodLightColor,
4345
'u_flood_light_intensity': floodLightIntensity,
46+
'u_front_cutoff_params': frontCutoffParams,
4447
};
4548

4649
return uniformValues;

3d-style/shaders/building.fragment.glsl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ in vec4 v_color;
99
in highp vec3 v_normal;
1010
in highp vec3 v_pos;
1111

12+
#ifdef RENDER_FRONT_CUTOFF
13+
in float v_front_cutoff_opacity;
14+
#endif
15+
16+
#ifdef INDICATOR_CUTOUT
17+
#ifdef FEATURE_CUTOUT
18+
in vec4 v_ground_roof;
19+
#endif
20+
#endif
21+
1222
#ifdef BUILDING_FAUX_FACADE
1323
in lowp float v_faux_facade;
1424
in highp float v_faux_facade_ed;
@@ -226,8 +236,29 @@ void main() {
226236
color *= u_opacity;
227237

228238
#ifdef INDICATOR_CUTOUT
239+
#ifdef FEATURE_CUTOUT
240+
{
241+
float ditherOpacity = cutoutGroundRoofOpacity(v_ground_roof);
242+
if (ditherOpacity < 1.0) {
243+
int index = (int(gl_FragCoord.x) % 4) * 4 + (int(gl_FragCoord.y) % 4);
244+
if (ditherOpacity < DITHER_THRESHOLDS[index]) {
245+
discard;
246+
}
247+
}
248+
}
249+
#else
229250
color = applyCutout(color, v_pos.z);
230251
#endif
252+
#endif
253+
254+
#ifdef RENDER_FRONT_CUTOFF
255+
if (v_front_cutoff_opacity < 1.0) {
256+
int index = (int(gl_FragCoord.x) % 4) * 4 + (int(gl_FragCoord.y) % 4);
257+
if (v_front_cutoff_opacity < DITHER_THRESHOLDS[index]) {
258+
discard;
259+
}
260+
}
261+
#endif
231262

232263
#ifdef FEATURE_CUTOUT
233264
color = apply_feature_cutout(color, gl_FragCoord, get_cutout_factors(gl_FragCoord).x);

3d-style/shaders/building.vertex.glsl

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,22 @@ uniform mat4 u_matrix;
1818
uniform mat4 u_normal_matrix;
1919
uniform highp float u_tile_to_meter;
2020

21+
#ifdef RENDER_FRONT_CUTOFF
22+
uniform vec3 u_front_cutoff_params; // [start, range, opacity]
23+
out float v_front_cutoff_opacity;
24+
#endif
25+
26+
#ifdef INDICATOR_CUTOUT
27+
#ifdef FEATURE_CUTOUT
28+
out vec4 v_ground_roof;
29+
#endif
30+
#endif
31+
2132
out vec4 v_color;
2233
out vec3 v_normal;
2334
out highp vec3 v_pos;
2435

36+
2537
#ifdef BUILDING_FAUX_FACADE
2638
out lowp float v_faux_facade;
2739
out highp float v_faux_facade_ed;
@@ -84,6 +96,12 @@ void main() {
8496

8597
float hidden = 0.0;
8698
float depth_offset = 0.0;
99+
100+
// Decode centroid position and span from packed attribute.
101+
// Encoding: cx_encoded = clamp(cx, 0, 8191) * 4 + spanXbits (2 bits per axis)
102+
vec2 centroid_xy = vec2(a_centroid_3.xy >> 2);
103+
vec2 spanBits = vec2(a_centroid_3.xy & 3);
104+
87105
#ifdef BUILDING_FAUX_FACADE
88106
vec4 faux_facade_data = vec4(a_faux_facade_data);
89107
v_faux_facade = faux_facade_data.x;
@@ -114,8 +132,20 @@ void main() {
114132
#endif
115133
v_pos = a_pos_3f;
116134

135+
#if defined(RENDER_CUTOFF) || defined(RENDER_FRONT_CUTOFF)
136+
float halfSpanX = spanBits.x * 10.0 / u_tile_to_meter;
137+
float halfSpanY = spanBits.y * 10.0 / u_tile_to_meter;
138+
vec2 screenUpInTile = vec2(u_matrix[0][1], u_matrix[1][1]);
139+
vec2 spanOffset = vec2(halfSpanX, halfSpanY) * sign(screenUpInTile);
140+
vec2 cutoff_highestCorner = centroid_xy + spanOffset;
141+
vec2 cutoff_lowestCorner = centroid_xy - spanOffset;
142+
#endif
143+
144+
#if defined(RENDER_CUTOFF) || defined(RENDER_FRONT_CUTOFF)
145+
vec4 ground = u_matrix * vec4(centroid_xy, 0.0, 1.0);
146+
#endif
147+
117148
#ifdef RENDER_CUTOFF
118-
vec4 ground = u_matrix * vec4(a_centroid_3.xyz, 1.0);
119149
v_cutoff_opacity = cutoff_opacity(u_cutoff_params, ground.z);
120150
hidden = float(v_cutoff_opacity == 0.0);
121151
v_pos.z *= v_cutoff_opacity;
@@ -135,6 +165,27 @@ void main() {
135165
v_fog_pos = fog_position(v_pos);
136166
#endif
137167

168+
#ifdef RENDER_FRONT_CUTOFF
169+
v_front_cutoff_opacity = 1.0;
170+
{
171+
hidden = max(hidden, float(ground.w <= 0.0));
172+
float ndc_y = ground.y / max(ground.w, 0.001);
173+
float threshold = u_front_cutoff_params.x * 2.0 - 1.0;
174+
float range_ndc = u_front_cutoff_params.y * 2.0;
175+
hidden = max(hidden, float(ndc_y < threshold - range_ndc));
176+
float t = clamp((ndc_y - (threshold - range_ndc)) / max(range_ndc, 0.001), 0.0, 1.0);
177+
v_front_cutoff_opacity = mix(u_front_cutoff_params.z, 1.0, t);
178+
}
179+
#endif
180+
138181
gl_Position = mix(u_matrix * vec4(v_pos, 1), AWAY, hidden);
139182
gl_Position.z -= depth_offset * gl_Position.w;
183+
184+
#ifdef INDICATOR_CUTOUT
185+
#ifdef FEATURE_CUTOUT
186+
vec4 ic_ground = u_matrix * vec4(v_pos.xy, 0.0, 1.0);
187+
vec4 ic_roof = u_matrix * vec4(v_pos.xy, v_pos.z, 1.0);
188+
v_ground_roof = vec4(ic_ground.xy / ic_ground.w, ic_roof.xy / ic_roof.w);
189+
#endif
190+
#endif
140191
}

3d-style/shaders/fill_extrusion_depth.vertex.glsl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ vec3 pos;
6060
bool is_flat_height = centroid_pos.x != 0.0 && u_height_type == 1;
6161
bool is_flat_base = centroid_pos.x != 0.0 && u_base_type == 1;
6262
float ele = elevation(pos_nx.xy);
63-
float c_ele = is_flat_height || is_flat_base ? (centroid_pos.y == 0.0 ? elevationFromUint16(centroid_pos.x) : flatElevation(centroid_pos)) : ele;
63+
bool is_elevation_encoded = centroid_pos.y == 0.0 || (centroid_pos.y > 0.0 && int(centroid_pos.y) - (int(centroid_pos.y) / 8) * 8 == 7);
64+
float c_ele = is_flat_height || is_flat_base ? (is_elevation_encoded ? elevationFromUint16(centroid_pos.x) : flatElevation(centroid_pos)) : ele;
6465
float h_height = is_flat_height ? max(c_ele + height, ele + base + 2.0) : ele + height;
6566
float h_base = is_flat_base ? max(c_ele + base, ele + base) : ele + (base == 0.0 ? -5.0 : base);
6667
float h = t > 0.0 ? max(h_base, h_height) : h_base;

3d-style/source/tiled_3d_model_source.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class Tiled3DModelSource extends Evented<SourceEvents> implements ISource {
152152
source: this.id,
153153
scope: this.scope,
154154
showCollisionBoxes: this.map.showCollisionBoxes,
155-
isSymbolTile: tile.isSymbolTile,
155+
renderSourceType: tile.renderSourceType,
156156
brightness: this.map.style ? (this.map.style.getBrightness() || 0.0) : 0.0,
157157
pixelRatio: browser.devicePixelRatio,
158158
promoteId: this.promoteId,

0 commit comments

Comments
 (0)