Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.0.0-beta.1 (advanced 3D lighting, shadows, nested styles and more) #12829

Merged
merged 201 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
201 commits
Select commit Hold shift + click to select a range
4db3e0b
[MAPS3D-691] line borders: respect lighting and fog (internal-436)
alexey-romanov Jan 26, 2023
dbe8a14
[MAPS3D-693] "emission", immediate mode, circle/fill/line/symbol (int…
alexey-romanov Jan 31, 2023
b1f8524
[MAPS3D-755] Add models style specification (internal-441)
jtorresfabra Feb 3, 2023
42235d1
3D Light specification (internal-438)
karimnaaji Feb 3, 2023
f8fa4ca
Fix x86_64 emulator v30 with different precision uniforms (internal-446)
jtorresfabra Feb 6, 2023
a9c1f0a
Relax restriction of zoom expression for atmosphere properties (inter…
endanke Feb 7, 2023
955506d
Add HSLA expression (internal-448)
endanke Feb 7, 2023
42cc889
Add icon transitioning to symbol shaders (internal-449)
endanke Feb 7, 2023
aceb0af
Allow custom shadow direction to be used (internal-444)
aleksigron Feb 7, 2023
b60b874
Runtime API 3d lights (internal-447)
karimnaaji Feb 7, 2023
b214ae6
Ignore failing tests due to chrome update (internal-453)
alexey-romanov Feb 9, 2023
14172a9
Add 3d lights types (internal-450)
karimnaaji Feb 9, 2023
8ea8d56
[MAPS3D-763] move stars calculation under #ifdef block (internal-451)
alexey-romanov Feb 10, 2023
62c69e6
Add GLTF loader and scaffold structure (internal-452)
jtorresfabra Feb 13, 2023
bcc5816
Add render test for regression (internal-456)
mpulkki-mapbox Feb 14, 2023
246b8ab
[MAPS3D-672] Add styling interpretation and enable 3d lights renderin…
karimnaaji Feb 14, 2023
11e58b5
[MAPS3D-672] Add 3d lights render tests (internal-458)
karimnaaji Feb 16, 2023
e48d6a7
[MAPS3D-672] Enable last 3d lights render tests (internal-460)
karimnaaji Feb 17, 2023
23d1bf1
Apply lighting prelude source separately durign program source constr…
endanke Feb 20, 2023
596f310
Add applyCutout function to fragment shader prelude, call applyCutout…
endanke Feb 20, 2023
817fe63
Raster colorization via "raster-color" (internal-455)
pozdnyakov Feb 20, 2023
6662980
Use colormap function with highp values in raster fragment shader (in…
endanke Feb 21, 2023
aaf87dd
Remove unused fixture data and update some 3d lights render tests (in…
karimnaaji Feb 23, 2023
4e6b533
Model conversion gltf to mapbox (internal-464)
jtorresfabra Feb 23, 2023
733b13c
[MAPS3D-735] Perform 3D lighting computations in linear space (intern…
mpulkki-mapbox Feb 27, 2023
4c8d820
[MAPS3D-777] update tests (internal-468)
alexey-romanov Feb 28, 2023
559bdd1
Port basic shadow support from native (internal-469)
aleksigron Mar 7, 2023
9c0306c
[MAPS3D-487] Enable flood lighting for walls of the extruded building…
akoylasar Mar 14, 2023
f45eebf
Initial PBR model rendering (internal-484)
jtorresfabra Mar 14, 2023
cc237e3
[MAPS3D-775] Support ground shadows in non-draped mode (internal-487)
aleksigron Mar 15, 2023
188a414
Update lighting specific baselines (internal-488)
karimnaaji Mar 15, 2023
e68429d
[MAPS3D-715] Measure light brightness expression (internal-486)
karimnaaji Mar 15, 2023
325bc76
Apply 3d lighting in globe and terrain shaders (internal-492)
mpulkki-mapbox Mar 16, 2023
ea538ea
[MAPS3D-716] Add measure-light to atmosphere properties (internal-489)
karimnaaji Mar 16, 2023
d0cadb1
Add new render test for emissive layers (internal-495)
mpulkki-mapbox Mar 20, 2023
826b23a
Fix attribute regex for Safari (internal-498)
jtorresfabra Mar 20, 2023
2cd4ba9
Update render test expectations (internal-499)
mpulkki-mapbox Mar 20, 2023
41b1c2f
Flood light walls hot fix (internal-491)
akoylasar Mar 20, 2023
d17bfaf
3D lighting fixes (internal-501)
mpulkki-mapbox Mar 21, 2023
ea40b4c
[MAPS3D-487] Fix subtle difference in AO when flood light is enabled.…
akoylasar Mar 21, 2023
b665557
Fix vertical scale with shadows enabled (internal-504)
akoylasar Mar 22, 2023
8160b39
Do no apply image filtering for displaying render test results (inter…
alexey-romanov Mar 22, 2023
9be405d
[MAPS3D-763] stars & atmosphere performance improvements (internal-490)
alexey-romanov Mar 24, 2023
e4d0dfb
Add support for globe, terrain and fog in model layer (internal-496)
jtorresfabra Mar 24, 2023
f10e84c
[MAPS3D-701] Instanced models (trees) (without GL instancing support)…
astojilj Mar 25, 2023
7d93277
Backport icon-image-cross-fade property and icon variant support (int…
endanke Mar 28, 2023
768ca79
[MAPS3D-697] support emission strength for 2d layers (internal-506)
alexey-romanov Mar 29, 2023
7293e7e
Add suport for shadows and new lighting 3d mode in model-layer (inter…
jtorresfabra Mar 29, 2023
da9a4d8
Remove unused attributes from lines shader (internal-512)
alexey-romanov Mar 30, 2023
8aea324
Add random expression (internal-509)
endanke Mar 30, 2023
a23fc1f
[MAPS3D-824] add zoom/measure-light to text/icon-emissive strength sp…
alexey-romanov Apr 3, 2023
2e1578b
Backport line border properties (internal-510)
endanke Apr 3, 2023
bba337c
Upgrade Flow to v0.188.0
stepankuzmin Apr 3, 2023
46142f1
Port model shader changes for height-based emissive strength (interna…
aleksigron Apr 4, 2023
8e925d3
[MAPS3D-707] emissive strength for draped mode (internal-519)
alexey-romanov Apr 12, 2023
0cef0e7
Fix code generator inputs (internal-520)
endanke Apr 14, 2023
5d0a54e
Flood light and AO contribution on the ground (internal-502)
akoylasar Apr 15, 2023
50eb994
Evaluate expressions in array members (internal-518)
endanke Apr 17, 2023
091ec37
Shader change related to textureGather usage for shadows on Android a…
astojilj Apr 17, 2023
c196743
Make icon-text-fit and icon-text-fit-padding data-driven (internal-521)
endanke Apr 18, 2023
f285c4a
Make the names of the new properties for flood light and AO consisten…
akoylasar Apr 18, 2023
278a5d5
[MAPS3D-819] background layer emissive strength (internal-526)
alexey-romanov Apr 19, 2023
ad70d4b
Globe wireframe test (internal-442)
alexey-romanov Apr 25, 2023
7662646
[MAPS3D-792] facelift 3d-playground debug page (internal-528)
alexey-romanov Apr 25, 2023
a8e4690
[MAPS3D-849] Shadow only affects directional light (internal-529)
aleksigron May 2, 2023
8b1b307
First iteration of landmark parsing and rendering (internal-522)
jtorresfabra May 3, 2023
19df9f1
Add support fot mapbox style url's for landmark sources (internal-536)
jtorresfabra May 4, 2023
cfc8979
Add expression tests for non-Latin characters (internal-537) (interna…
alexshalamov May 4, 2023
1e0c16e
[MAPS3D-711] Add emission height based parameters to landmarks and pa…
jtorresfabra May 5, 2023
a5ebbbc
[MAPS3D-804] GL-JS Camera Projection root property (internal-538)
alexey-romanov May 8, 2023
3cc3d1e
Model shader uses anisotropic ambient light (internal-541)
aleksigron May 8, 2023
17a3e98
[MAPS3D-847] Add support for landmark shadows (internal-534)
jtorresfabra May 9, 2023
22030bc
[MAPS3D-831] Shadows: tree shadows and shadow map frustum optimizatio…
astojilj May 9, 2023
1ab39ea
Add CI job to verify codegen output (internal-547)
endanke May 10, 2023
207257c
[MAPS3D-856] Fix fill-extrusion flat roof and flood light shading (in…
aleksigron May 10, 2023
3e71edb
[MAPS3D-792] - move main debugging features from terrain-debug to 3d-…
alexey-romanov May 10, 2023
04a0911
Enable ground shadows for camera-projection/with-shadows render tests…
astojilj May 11, 2023
0193492
fix shader compilation issue when 3d lighting is disabled (internal-548)
akoylasar May 11, 2023
ac2d6b8
Fix terrain shadow lighting regression (internal-551)
aleksigron May 11, 2023
9441a5d
Fix Flow function argument annotations (internal-553)
stepankuzmin May 12, 2023
8ce0e17
Fix fill extrusion flat roof rendering
aleksigron May 12, 2023
24bef2a
Fix lint
aleksigron May 15, 2023
1d14363
Ignore flaky render test for now
aleksigron May 15, 2023
423f555
Try fix WebGL 2 detection on CI
aleksigron May 15, 2023
eb69aed
[MAPS3D-668] Port landmark conflation (internal-543)
mpulkki-mapbox May 16, 2023
840c238
[MAPSNAT-1103] do not render atmosphere/stars in overdraw mode (inter…
alexey-romanov May 18, 2023
59a36a2
Fix typing and lint errors
aleksigron May 19, 2023
75a7cc8
Resolve Flow annotation issues (internal-561)
stepankuzmin May 19, 2023
d88a2dc
Add support for landmark doorlights and fix operation updates (intern…
jtorresfabra May 19, 2023
cb602da
After removing sleep in previous commit, it was needed to add wait so…
astojilj May 19, 2023
773cc43
Resolve Flow annotation issues (internal-562)
stepankuzmin May 19, 2023
02cbabe
Ignore globe wireframe test on Safari
aleksigron May 19, 2023
4d0d1c2
Try fix timeout on render test
aleksigron May 19, 2023
1499f8a
Fix fixture builders (internal-556)
stepankuzmin May 19, 2023
f5c39e2
Ignore tests that are timing out
aleksigron May 19, 2023
9279e1c
skip timing out tests on linux chrome
astojilj May 19, 2023
3872bbd
Remove duplicated landmark models (internal-563)
jtorresfabra May 22, 2023
e21b94d
Hide fully transparent symbols (internal-554)
endanke May 22, 2023
2c36ab7
Add shader flag to disable dithering in fog (internal-542)
endanke May 23, 2023
03ce654
[MAPS3D-806] Allow measure-light only for landmarks and zoom based on…
astojilj May 24, 2023
3058eb6
Introduce material-wide wireframe debug rendering support (internal-557)
alexey-romanov May 25, 2023
be5a5c6
Text halo with instanced rendering (internal-531)
endanke May 25, 2023
ac1408c
Add fix for Swiftshader shader error (internal-569)
endanke May 25, 2023
9118f5d
[MAPS3D-779] Globe support for iOS & Android to the spec (internal-540)
tjukanovt May 27, 2023
cab0250
Fixes constant tile reparse causing flickering and handles http 204 r…
jtorresfabra May 29, 2023
d20bd6b
Add terrain support for landmarks (internal-567)
jtorresfabra May 29, 2023
99a5f88
model-roughness spec remove zoom based interpolation (internal-573)
astojilj May 29, 2023
78472d6
Lazy-load GLTF loader libraries from a CDN (internal-535)
mourner May 30, 2023
22fd587
Add `mapboxgl.loadersUrl` to allow overriding loaders bundle URL (int…
stepankuzmin May 30, 2023
611e01d
Fix flickering on loading landmark tiles for the first time (internal…
jtorresfabra May 31, 2023
f5abb7d
[MAPS3D-837] use 'highp' for terrain dem sampling (internal-580)
alexey-romanov May 31, 2023
7160b93
Fix a corner case when updating PBR buffers that caused flickering (i…
jtorresfabra May 31, 2023
13cd942
Render door light after shadows (internal-579)
astojilj May 31, 2023
d14f271
fix regression on door lights: render when no shadows (internal-582)
astojilj May 31, 2023
34984a0
flood light affected by shadows on extruded walls
akoylasar May 26, 2023
0242fa6
update expectation image
akoylasar May 29, 2023
39e523d
[WIP] Proposal
mpulkki-mapbox May 30, 2023
9efc6de
add small epsilon to avoid NaN on corner case when ambient and direct…
akoylasar May 31, 2023
ca0cbe0
highp to avoid nan on mobile as well. remaining review remarks
akoylasar May 31, 2023
a355c70
remove apastrophe from comment leading to unit test failures
akoylasar May 31, 2023
e90ea1c
use higher zoom level for render test to avoid flaky behaviour that c…
akoylasar May 31, 2023
96de6a2
add some more render tests covering corner cases
akoylasar May 31, 2023
3051ed3
fix typo in webgl1 ignore paths name (internal-584)
akoylasar Jun 2, 2023
d057ba6
Update landmark render-tests expected images as they are outdated (in…
jtorresfabra Jun 6, 2023
ca2be5a
Fix for incorrect buffer size for index array in model loader (intern…
jtorresfabra Jun 6, 2023
1732223
Use mbx-3dbuildings-v1 tileset as landmarks source (internal-589)
aleksigron Jun 7, 2023
0cbb19e
Reduce memory footprint by trimming the arrays used by models (intern…
jtorresfabra Jun 7, 2023
961b7ac
fix uv precision for shadow texture gather branch (internal-591)
astojilj Jun 8, 2023
4b1013e
Simplify linearTosRGB(sRGBToLinear(srgbIn) * k) (internal-592)
astojilj Jun 8, 2023
c6b612f
[MAPS3D-869, 870] Refactor conflation and add support for new footpri…
mpulkki-mapbox Jun 8, 2023
7ebe0d0
[MAPS3D-916] reduce shader instruction count in fill-extrusion walls …
akoylasar Jun 9, 2023
790e17c
[MAPS3D-916] [MAPS3D-917] Simplfy fog calculations in ground flood li…
akoylasar Jun 12, 2023
28e718c
[MAPS3D-918] enable measure-light expression for flood light color an…
akoylasar Jun 12, 2023
f322ee2
Fix issue with model-receive-shadows (internal-597)
aleksigron Jun 13, 2023
ffebd14
Fixes missing terrain tiles in cache in gl-native by pointing to the …
jtorresfabra Jun 13, 2023
14ef3bd
Evolving Basemap: Style spec changes
kkaefer May 24, 2023
d415604
Implement better validation for imports and options
stepankuzmin Jun 13, 2023
6f05d3c
[MAPS3D-912] reduce fragment shader instruction count in 3d lighting …
akoylasar Jun 14, 2023
ee8a724
[MAPS3D-888] Fill extrusion and model layer shadow normal offset (int…
astojilj Jun 15, 2023
6d1d8be
[MAPS3D-841][MAPS3D-923] Add ground flood lighting and AO in draped …
akoylasar Jun 15, 2023
85e9f43
[MAPS3D-912] when rendering ground shadows it is not necessary to wri…
akoylasar Jun 16, 2023
6e015da
Add documentation for measure-light (internal-600)
endanke Jun 19, 2023
792a2f8
door light fix https://mapbox.atlassian.net/browse/MAPS3D-892 (intern…
astojilj Jun 20, 2023
2d283ad
[MAPS3D-901][MAPS3D-909] Hide the ground flood light and ground AO wh…
akoylasar Jun 20, 2023
36a3dff
[MAPS3D-929] Backport conflation render tests from gl-native (interna…
mpulkki-mapbox Jun 21, 2023
2e3e355
[MAPS3D-890] Add model runtime API (internal-606)
jtorresfabra Jun 21, 2023
260bb53
Add examples for update/remove models using runtime API (internal-609)
jtorresfabra Jun 22, 2023
fa93dc0
Update `models` Style-Spec (internal-608)
stepankuzmin Jun 22, 2023
44af303
Fix Loaders URL in Workers (internal-612)
stepankuzmin Jun 28, 2023
2816fdb
Add style imports support (internal-583)
stepankuzmin Jun 28, 2023
64d074a
Fix empty 3D tiles not ending up in the `loaded` state (internal-616)
stepankuzmin Jun 30, 2023
64a6db1
[MAPS3D-916] Reduce segment overlap in ground flood light to improve …
akoylasar Jul 4, 2023
1153190
[MAPS3D-952] use uint16 for secondary icon texture coordinates (inter…
alexey-romanov Jul 5, 2023
16d1c4a
Use Standard Style if no style is set (internal-619)
stepankuzmin Jul 6, 2023
b871533
Render sky on globe with disabled atmosphere, update sky transition l…
endanke Jul 6, 2023
a2c3cc0
Move `mulberry32` to the `style-spec` package (internal-623)
stepankuzmin Jul 10, 2023
05d551d
Port precise intersections between frustum and tile aabbs to further …
jtorresfabra Jul 11, 2023
1584cee
Remove static fields from `PartData` (internal-626)
stepankuzmin Jul 11, 2023
6ca2be2
fix eslint import warnings (internal-625)
mourner Jul 11, 2023
6bc331c
Add missing version numbers to style spec (internal-627)
endanke Jul 12, 2023
6e429ec
Fix frustum constructor call (internal-630)
jtorresfabra Jul 13, 2023
ee66a54
Avoid to use shadow normal offset when the models have no normals (in…
jtorresfabra Jul 13, 2023
71363e3
Evaluate tree lod based on distance of tile to camera and reduce dens…
astojilj Jul 14, 2023
ade37b7
Revert "[MAPS3D-916] Reduce segment overlap in ground flood light to …
astojilj Jul 14, 2023
8a6e1e7
Fix emissive factor not being honored in model shader (internal-634)
jtorresfabra Jul 14, 2023
eae5faa
Revert unintentionally submitted z14 when calculating near plane. (in…
astojilj Jul 17, 2023
5de5954
[GLJS-433] test large icons with secondary image (internal-632)
alexey-romanov Jul 17, 2023
d0f748f
Evolving Basemap: configuration options (internal-622)
mourner Jul 19, 2023
ea892e1
Log errors in render test immediately (internal-638)
aleksigron Jul 20, 2023
40659c3
Fix crash in shaders when model has textures but no UVs (internal-641)
jtorresfabra Jul 21, 2023
c5e5e76
[MAPS3D-976] fix 3d model shading (saturate directLight contribution)…
alexey-romanov Jul 22, 2023
09ddc97
Complete 3D style documentation (internal-644)
jtorresfabra Jul 24, 2023
5443388
Move "light" to "lights" API (internal-640)
endanke Jul 24, 2023
82d61fc
[MAPS3D-968] take into account DEM while clipping instanced models ag…
alexey-romanov Jul 24, 2023
59722e9
[GLJS-419] Introduce `distance`expression (internal-614)
zmiao Jul 24, 2023
f79e766
Update paint arrays in buckets on brightness change (internal-649)
endanke Jul 26, 2023
004d3d2
[MAPS3D-983] instanced models shadows high altitude test (internal-652)
alexey-romanov Jul 27, 2023
54cd2ba
Disable timeout of unit tests (internal-651)
endanke Jul 27, 2023
f6a4ed6
Refactor Style imports (internal-637)
stepankuzmin Jul 27, 2023
849edfb
Enable `WebGL2` by default (internal-653)
stepankuzmin Jul 27, 2023
721aead
Move `EXTENT` constant to the Style-Spec package (internal-655)
stepankuzmin Jul 28, 2023
fcb9462
Store initial brightness value in tile (internal-657)
endanke Jul 28, 2023
4124c5f
Refactor `ModelManager` to support scopes (internal-656)
stepankuzmin Jul 28, 2023
1c73776
Remove unuseful log message (internal-654)
jtorresfabra Jul 28, 2023
2f469a5
Create scope in ImageManager when attaching to a Style (internal-660)
stepankuzmin Jul 31, 2023
d264a9e
Reduce measure-light re-evaluation lag (internal-659)
endanke Jul 31, 2023
ab71548
Temporarily pin ChromeDriver version to fix `test-browser` (internal-…
mourner Jul 31, 2023
8d821f9
Add ability to set config options at runtime (internal-646)
mourner Jul 31, 2023
1ea90b5
[MAPS3D-990] fix globe pole clipping (internal-658)
alexey-romanov Jul 31, 2023
1511bbb
Optimize `FeaturePositionMap` iteration (internal-662)
mourner Jul 31, 2023
eedb72a
Use brightness value for initial evaluation in worker (internal-663)
endanke Jul 31, 2023
f4930e7
iterate over unique ids when updating paint arrays (internal-666)
mourner Aug 1, 2023
e62a1fe
Update brightness through WorkerTileParameters (internal-664)
endanke Aug 1, 2023
343088f
change order of params for setConfigProperty (internal-668)
mourner Aug 1, 2023
f9856fc
Set brightness in EvaluationParameters after updating lights (interna…
endanke Aug 2, 2023
6f6dab6
Add render test for conflation of multiple tiled 3D model sources (in…
mpulkki-mapbox Aug 2, 2023
d527ec1
Prepare for the v3.0.0-beta.1 release (internal-671)
stepankuzmin Aug 2, 2023
6da22bf
post-rebase cleanup
mourner Aug 3, 2023
53bd353
Add sample models attribution
jtorresfabra Aug 4, 2023
42f1729
Add GL JS v3 changelog (#677)
stepankuzmin Aug 7, 2023
3eec46d
Add migration guide
stepankuzmin Aug 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
27 changes: 25 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ workflows:
filters:
tags:
only: /.*/
- verify-codegen:
requires:
- prepare-linux
filters:
tags:
only: /.*/
- collect-stats:
requires:
- build
Expand Down Expand Up @@ -220,6 +226,7 @@ jobs:
- v0-linux-yarn-{{ .Branch }}-
- v0-linux-yarn-
- run: yarn --frozen-lockfile --cache-folder ~/.cache/yarn
- run: yarn run build-loaders
- run: yarn run build-dev
- save_cache:
key: v0-linux-yarn-{{ .Branch }}-{{ checksum "yarn.lock" }}
Expand Down Expand Up @@ -307,7 +314,9 @@ jobs:
steps:
- attach_workspace:
at: ~/
- run: yarn run test-unit
- run:
command: yarn run test-unit
no_output_timeout: 5m

test-query:
<<: *linux-defaults
Expand Down Expand Up @@ -343,6 +352,17 @@ jobs:
at: ~/
- run: yarn run test-style-spec

verify-codegen:
<<: *linux-defaults
steps:
- attach_workspace:
at: ~/
- run:
name: Verify codegen output
command: |
yarn run codegen
git add -A && git diff --staged --exit-code | tee check.patch

collect-stats:
<<: *linux-defaults
steps:
Expand All @@ -362,7 +382,8 @@ jobs:
steps:
- attach_workspace:
at: ~/
- browser-tools/install-browser-tools
- browser-tools/install-browser-tools:
chrome-version: "114.0.5735.90"
- run: yarn run build-token
- run:
name: Test Chrome
Expand Down Expand Up @@ -513,6 +534,7 @@ jobs:
key: v0-mac-yarn-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
- run: yarn run build-loaders
- run: yarn run build-dev
- persist_to_workspace:
root: ~/
Expand Down Expand Up @@ -590,6 +612,7 @@ jobs:
npm install -g yarn
refreshenv
- run: yarn --frozen-lockfile
- run: yarn run build-loaders
- run: yarn run build-dev
- run:
name: Clean up workspace to persist faster
Expand Down
322 changes: 322 additions & 0 deletions 3d-style/data/bucket/model_bucket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,322 @@
// @flow

import EXTENT from '../../../src/style-spec/data/extent.js';
import {register} from '../../../src/util/web_worker_transfer.js';
import loadGeometry from '../../../src/data/load_geometry.js';
import toEvaluationFeature from '../../../src/data/evaluation_feature.js';
import type {EvaluationFeature} from '../../../src/data/evaluation_feature.js';
import EvaluationParameters from '../../../src/style/evaluation_parameters.js';
import Point from '@mapbox/point-geometry';
import type {Mat4} from 'gl-matrix';
import type {CanonicalTileID, OverscaledTileID} from '../../../src/source/tile_id.js';
import type {
Bucket,
BucketParameters,
BucketFeature,
IndexedFeature,
PopulateParameters
} from '../../../src/data/bucket.js';

import type Context from '../../../src/gl/context.js';
import type VertexBuffer from '../../../src/gl/vertex_buffer.js';
import type {FeatureStates} from '../../../src/source/source_state.js';
import type {SpritePositions} from '../../../src/util/image.js';
import type {ProjectionSpecification} from '../../../src/style-spec/types.js';
import type {TileTransform} from '../../../src/geo/projection/tile_transform.js';
import type {IVectorTileLayer} from '@mapbox/vector-tile';
import {InstanceVertexArray} from '../../../src/data/array_types.js';
import assert from 'assert';
import {warnOnce} from '../../../src/util/util.js';
import ModelStyleLayer from '../../style/style_layer/model_style_layer.js';
import {rotationScaleYZFlipMatrix} from '../../util/model_util.js';
import {tileToMeter} from '../../../src/geo/mercator_coordinate.js';

class ModelFeature {
feature: EvaluationFeature;
instancedDataOffset: number;
instancedDataCount: number;

constructor(feature: EvaluationFeature, offset: number) {
this.feature = feature;
this.instancedDataOffset = offset;
this.instancedDataCount = 0;
}
}

class PerModelAttributes {
// If node has meshes, instancedDataArray gets an entry for each feature instance (used for all meshes or the node).
instancedDataArray: InstanceVertexArray;
instancedDataBuffer: VertexBuffer;
instancesEvaluatedElevation: Array<number>; // Gets added to DEM elevation of the instance to produce value in instancedDataArray.

features: Array<ModelFeature>;
idToFeaturesIndex: {[string | number]: number}; // via this.features, enable lookup instancedDataArray based on feature ID.

constructor() {
this.instancedDataArray = new InstanceVertexArray();
this.instancesEvaluatedElevation = [];
this.features = [];
this.idToFeaturesIndex = {};
}
}

class ModelBucket implements Bucket {
zoom: number;
index: number;
canonical: CanonicalTileID;
layers: Array<ModelStyleLayer>;
layerIds: Array<string>;
stateDependentLayers: Array<ModelStyleLayer>;
stateDependentLayerIds: Array<string>;
hasPattern: boolean;

instancesPerModel: {string: PerModelAttributes};

uploaded: boolean;

tileToMeter: number;
projection: ProjectionSpecification;

// elevation is baked into vertex buffer together with evaluated instance translation
validForExaggeration: number;
validForDEMTile: ?OverscaledTileID;
maxVerticalOffset: number; // for tile AABB calculation
maxScale: number; // across all dimensions, for tile AABB calculation
maxHeight: number; // calculated from previous two, during rendering, when models are available.
isInsideFirstShadowMapFrustum: boolean; // evaluated during first shadows pass and cached here for the second shadow pass.
lookup: ?Uint8Array;
lookupDim: number;
instanceCount: number;
// Bucket min/max terrain elevation among instance positions taking exaggeration value into account
terrainElevationMin: number;
terrainElevationMax: number;

/* $FlowIgnore[incompatible-type-arg] Doesn't need to know about all the implementations */
constructor(options: BucketParameters<ModelStyleLayer>) {
this.zoom = options.zoom;
this.canonical = options.canonical;
this.layers = options.layers;
this.layerIds = this.layers.map(layer => layer.id);
this.projection = options.projection;
this.index = options.index;

this.stateDependentLayerIds = this.layers.filter((l) => l.isStateDependent()).map((l) => l.id);
this.hasPattern = false;
this.instancesPerModel = {};
this.validForExaggeration = 0;
this.maxVerticalOffset = 0;
this.maxScale = 0;
this.maxHeight = 0;
// reduce density, more on lower zooms and almost no reduction in overscale range.
// Heuristics is related to trees performance.
this.lookupDim = this.zoom > this.canonical.z ? 256 : this.zoom > 15 ? 75 : 100;
this.instanceCount = 0;

this.terrainElevationMin = 0;
this.terrainElevationMax = 0;
}

populate(features: Array<IndexedFeature>, options: PopulateParameters, canonical: CanonicalTileID, tileTransform: TileTransform) {
this.tileToMeter = tileToMeter(canonical);
const needGeometry = this.layers[0]._featureFilter.needGeometry;
this.lookup = new Uint8Array(this.lookupDim * this.lookupDim);

for (const {feature, id, index, sourceLayerIndex} of features) {
const evaluationFeature = toEvaluationFeature(feature, needGeometry);

// $FlowFixMe[method-unbinding]
if (!this.layers[0]._featureFilter.filter(new EvaluationParameters(this.zoom), evaluationFeature, canonical)) continue;

const bucketFeature: BucketFeature = {
id,
sourceLayerIndex,
index,
geometry: needGeometry ? evaluationFeature.geometry : loadGeometry(feature, canonical, tileTransform),
properties: feature.properties,
type: feature.type,
patterns: {}
};

const modelId = this.addFeature(bucketFeature, bucketFeature.geometry, evaluationFeature);

if (modelId) {
options.featureIndex.insert(feature, bucketFeature.geometry, index, sourceLayerIndex, this.index, this.instancesPerModel[modelId].instancedDataArray.length);
}
}
this.lookup = null;
}

// eslint-disable-next-line no-unused-vars
update(states: FeatureStates, vtLayer: IVectorTileLayer, availableImages: Array<string>, imagePositions: SpritePositions) {
// called when setFeature state API is used
for (const modelId in this.instancesPerModel) {
const instances = this.instancesPerModel[modelId];
for (const id in states) {
if (instances.idToFeaturesIndex.hasOwnProperty(id)) {
const feature = instances.features[instances.idToFeaturesIndex[id]];
this.evaluate(feature, states[id], instances, true);
}
}
}
this.maxHeight = 0; // needs to be recalculated.
}

isEmpty(): boolean {
for (const modelId in this.instancesPerModel) {
const perModelAttributes = this.instancesPerModel[modelId];
if (perModelAttributes.instancedDataArray.length !== 0) return false;
}
return true;
}

uploadPending(): boolean {
return !this.uploaded;
}

upload(context: Context) {
// if buffer size is less than the threshold, do not upload instance buffer.
// if instance buffer is not uploaded, instances are rendered one by one.
const useInstancingThreshold = Number.MAX_SAFE_INTEGER;
if (!this.uploaded) {
for (const modelId in this.instancesPerModel) {
const perModelAttributes = this.instancesPerModel[modelId];
if (perModelAttributes.instancedDataArray.length < useInstancingThreshold || perModelAttributes.instancedDataArray.length === 0) continue;
if (!perModelAttributes.instancedDataBuffer) {
perModelAttributes.instancedDataBuffer = context.createVertexBuffer(perModelAttributes.instancedDataArray, perModelAttributes.instancedDataArray.members, true);
} else {
perModelAttributes.instancedDataBuffer.updateData(perModelAttributes.instancedDataArray);
}
}
}
this.uploaded = true;
}

destroy() {
for (const modelId in this.instancesPerModel) {
const perModelAttributes = this.instancesPerModel[modelId];
if (perModelAttributes.instancedDataArray.length === 0) continue;
if (perModelAttributes.instancedDataBuffer) {
perModelAttributes.instancedDataBuffer.destroy();
}
}
}

addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, evaluationFeature: EvaluationFeature): string {
const layer = this.layers[0];
const modelIdProperty = layer.layout.get('model-id');
assert(modelIdProperty);
const modelId = modelIdProperty.evaluate(evaluationFeature, {}, this.canonical);
if (!modelId) {
warnOnce(`modelId is not evaluated for layer ${layer.id} and it is not going to get rendered.`);
return modelId;
}
if (!this.instancesPerModel[modelId]) {
this.instancesPerModel[modelId] = new PerModelAttributes();
}
const perModelVertexArray = this.instancesPerModel[modelId];
const instancedDataArray = perModelVertexArray.instancedDataArray;

const modelFeature = new ModelFeature(evaluationFeature, instancedDataArray.length);
for (const geometries of geometry) {
for (const point of geometries) {
if (point.x < 0 || point.x >= EXTENT || point.y < 0 || point.y >= EXTENT) {
continue; // Clip on tile borders to prevent duplicates
}
// reduce density
const tileToLookup = (this.lookupDim - 1.0) / EXTENT;
const lookupIndex = this.lookupDim * ((point.y * tileToLookup) | 0) + (point.x * tileToLookup) | 0;
if (this.lookup) {
if (this.lookup[lookupIndex] !== 0) {
continue;
}
this.lookup[lookupIndex] = 1;
}
this.instanceCount++;
const i = instancedDataArray.length;
instancedDataArray.resize(i + 1);
perModelVertexArray.instancesEvaluatedElevation.push(0);
instancedDataArray.float32[i * 16] = point.x;
instancedDataArray.float32[i * 16 + 1] = point.y;
}
}
modelFeature.instancedDataCount = perModelVertexArray.instancedDataArray.length - modelFeature.instancedDataOffset;
if (modelFeature.instancedDataCount > 0) {
if (feature.id) {
perModelVertexArray.idToFeaturesIndex[feature.id] = perModelVertexArray.features.length;
}
perModelVertexArray.features.push(modelFeature);
this.evaluate(modelFeature, {}, perModelVertexArray, false);
}
return modelId;
}

evaluate(feature: ModelFeature, featureState: FeatureStates, perModelVertexArray: PerModelAttributes, update: boolean) {
const layer = this.layers[0];
const evaluationFeature = feature.feature;
const canonical = this.canonical;
const rotation = layer.paint.get('model-rotation').evaluate(evaluationFeature, featureState, canonical);
const scale = layer.paint.get('model-scale').evaluate(evaluationFeature, featureState, canonical);
const translation = layer.paint.get('model-translation').evaluate(evaluationFeature, featureState, canonical);
const color = layer.paint.get('model-color').evaluate(evaluationFeature, featureState, canonical);
color.a = layer.paint.get('model-color-mix-intensity').evaluate(evaluationFeature, featureState, canonical);
const rotationScaleYZFlip: Mat4 = [];
if (this.maxVerticalOffset < translation[2]) this.maxVerticalOffset = translation[2];
this.maxScale = Math.max(Math.max(this.maxScale, scale[0]), Math.max(scale[1], scale[2]));

rotationScaleYZFlipMatrix(rotationScaleYZFlip, (rotation: any), (scale: any));

// https://github.com/mapbox/mapbox-gl-native-internal/blob/c380f9492220906accbdca1f02cca5ee489d97fc/src/mbgl/renderer/layers/render_model_layer.cpp#L1282
const constantTileToMeterAcrossTile = 10;
assert(perModelVertexArray.instancedDataArray.bytesPerElement === 64);

const vaOffset2 = Math.round(100.0 * color.a) + color.b / 1.05;

for (let i = 0; i < feature.instancedDataCount; ++i) {
const instanceOffset = feature.instancedDataOffset + i;
const offset = instanceOffset * 16;

const va = perModelVertexArray.instancedDataArray.float32;
let terrainElevationContribution = 0;
if (update) {
terrainElevationContribution = va[offset + 6] - perModelVertexArray.instancesEvaluatedElevation[instanceOffset];
}

// All per-instance attributes are packed to one 4x4 float matrix. Data is not expected
// to change on every frame when e.g. camera or light changes.
// Column major order. Elements:
// 0 & 1: tile coordinates stored in integer part of float, R and G color components,
// originally in range [0..1], scaled to range [0..0.952(arbitrary, just needs to be
// under 1)].
const pointY = va[offset + 1] | 0; // point.y stored in integer part
va[offset] = (va[offset] | 0) + color.r / 1.05; // point.x stored in integer part
va[offset + 1] = pointY + color.g / 1.05;
// Element 2: packs color's alpha (as integer part) and blue component in fractional part.
va[offset + 2] = vaOffset2;
// tileToMeter is taken at center of tile. Prevent recalculating it over again for
// thousands of trees.
// Element 3: tileUnitsToMeter conversion.
va[offset + 3] = 1.0 / (canonical.z > constantTileToMeterAcrossTile ? this.tileToMeter : tileToMeter(canonical, pointY));
// Elements [4..6]: translation evaluated for the feature.
va[offset + 4] = translation[0];
va[offset + 5] = translation[1];
va[offset + 6] = translation[2] + terrainElevationContribution;
// Elements [7..16] Instance modelMatrix holds combined rotation and scale 3x3,
va[offset + 7] = rotationScaleYZFlip[0];
va[offset + 8] = rotationScaleYZFlip[1];
va[offset + 9] = rotationScaleYZFlip[2];
va[offset + 10] = rotationScaleYZFlip[4];
va[offset + 11] = rotationScaleYZFlip[5];
va[offset + 12] = rotationScaleYZFlip[6];
va[offset + 13] = rotationScaleYZFlip[8];
va[offset + 14] = rotationScaleYZFlip[9];
va[offset + 15] = rotationScaleYZFlip[10];
perModelVertexArray.instancesEvaluatedElevation[instanceOffset] = translation[2];
}
}
}

register(ModelBucket, 'ModelBucket', {omit: ['layers']});
register(PerModelAttributes, 'PerModelAttributes');
register(ModelFeature, 'ModelFeature');

export default ModelBucket;
Loading