@npm9912/v-map 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/cjs/_commonjsHelpers-B83fTs8d.js +36 -0
- package/dist/cjs/app-globals-V2Kpy_OQ.js +5 -0
- package/dist/cjs/cesium-provider-BiFFyAl9.js +2598 -0
- package/dist/cjs/deck-provider-Ctq3Q8a1.js +47824 -0
- package/dist/cjs/geotiff-CEwvF9cG.js +47 -0
- package/dist/cjs/geotiff-source-RaNzzWkC.js +1522 -0
- package/dist/cjs/index-B1oGO1g-.js +10658 -0
- package/dist/cjs/index-B8LHqjyg.js +1765 -0
- package/dist/cjs/index-BIL4VsgP.js +310 -0
- package/dist/cjs/index-Blku2QY8.js +167 -0
- package/dist/cjs/index-CJvvX4yx.js +21 -0
- package/dist/cjs/index-CbVT-Con.js +699 -0
- package/dist/cjs/index-ISOEpMC3.js +20478 -0
- package/dist/cjs/index-JSwBbvGA.js +1621 -0
- package/dist/cjs/index.browser-DQhD8Jwl.js +6873 -0
- package/dist/cjs/index.cjs.js +2 -0
- package/dist/cjs/layer-extension-B_olS0rc.js +65 -0
- package/dist/cjs/leaflet-provider-DOqfs7g5.js +1815 -0
- package/dist/cjs/loader.cjs.js +13 -0
- package/dist/cjs/main-dist-7TykwFci.js +2655 -0
- package/dist/cjs/messages-D7h4m8Tx.js +186 -0
- package/dist/cjs/openlayers-provider-Dfeg6L4n.js +1604 -0
- package/dist/cjs/polygon-layer-B9PrN7vr.js +1300 -0
- package/dist/cjs/scenegraph-layer-DwNoxQdi.js +2530 -0
- package/dist/cjs/styleconfig-CVRqArk-.js +23 -0
- package/dist/cjs/v-map-builder.cjs.entry.js +3786 -0
- package/dist/cjs/v-map-layer-geojson_12.cjs.entry.js +40894 -0
- package/dist/cjs/v-map-layer-helper-iAzxAg9I.js +285 -0
- package/dist/cjs/v-map-layer-terrain-geotiff.cjs.entry.js +258 -0
- package/dist/cjs/v-map-layercontrol.cjs.entry.js +247 -0
- package/dist/cjs/v-map.cjs.js +25 -0
- package/dist/cjs/v-map.v-map-layer-osm.v-map-layergroup-BsXp3BoL.js +582 -0
- package/dist/cjs/v-map_3.cjs.entry.js +12 -0
- package/dist/collection/collection-manifest.json +30 -0
- package/dist/collection/components/v-map/v-map.css +3 -0
- package/dist/collection/components/v-map/v-map.js +467 -0
- package/dist/collection/components/v-map/v-map.test.js +33 -0
- package/dist/collection/components/v-map-builder/v-map-builder.css +1 -0
- package/dist/collection/components/v-map-builder/v-map-builder.js +913 -0
- package/dist/collection/components/v-map-builder/v-map-builder.test.js +56 -0
- package/dist/collection/components/v-map-layer-geojson/v-map-layer-geojson.js +862 -0
- package/dist/collection/components/v-map-layer-geojson/v-map-layer-geojson.test.js +42 -0
- package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.css +4 -0
- package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.js +500 -0
- package/dist/collection/components/v-map-layer-geotiff/v-map-layer-geotiff.test.js +38 -0
- package/dist/collection/components/v-map-layer-google/v-map-layer-google.css +1 -0
- package/dist/collection/components/v-map-layer-google/v-map-layer-google.js +442 -0
- package/dist/collection/components/v-map-layer-osm/error-api.test.js +108 -0
- package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.css +4 -0
- package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.js +311 -0
- package/dist/collection/components/v-map-layer-osm/v-map-layer-osm.test.js +36 -0
- package/dist/collection/components/v-map-layer-scatterplot/v-map-layer-scatterplot.css +1 -0
- package/dist/collection/components/v-map-layer-scatterplot/v-map-layer-scatterplot.js +305 -0
- package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.css +3 -0
- package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.js +548 -0
- package/dist/collection/components/v-map-layer-terrain/v-map-layer-terrain.test.js +36 -0
- package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.css +3 -0
- package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.js +735 -0
- package/dist/collection/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.test.js +42 -0
- package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.css +3 -0
- package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.js +449 -0
- package/dist/collection/components/v-map-layer-tile3d/v-map-layer-tile3d.test.js +50 -0
- package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.css +1 -0
- package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.js +448 -0
- package/dist/collection/components/v-map-layer-wcs/v-map-layer-wcs.test.js +39 -0
- package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.css +1 -0
- package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.js +489 -0
- package/dist/collection/components/v-map-layer-wfs/v-map-layer-wfs.test.js +43 -0
- package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.css +1 -0
- package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.js +811 -0
- package/dist/collection/components/v-map-layer-wkt/v-map-layer-wkt.test.js +34 -0
- package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.css +1 -0
- package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.js +453 -0
- package/dist/collection/components/v-map-layer-wms/v-map-layer-wms.test.js +36 -0
- package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.css +1 -0
- package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.js +331 -0
- package/dist/collection/components/v-map-layer-xyz/v-map-layer-xyz.test.js +28 -0
- package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.css +74 -0
- package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.js +277 -0
- package/dist/collection/components/v-map-layercontrol/v-map-layercontrol.test.js +134 -0
- package/dist/collection/components/v-map-layergroup/v-map-layergroup.css +4 -0
- package/dist/collection/components/v-map-layergroup/v-map-layergroup.js +212 -0
- package/dist/collection/components/v-map-layergroup/v-map-layergroup.test.js +39 -0
- package/dist/collection/components/v-map-style/v-map-style.css +38 -0
- package/dist/collection/components/v-map-style/v-map-style.js +492 -0
- package/dist/collection/components/v-map-style/v-map-style.unit.js +62 -0
- package/dist/collection/index.js +1 -0
- package/dist/collection/layer/v-map-layer-helper.js +281 -0
- package/dist/collection/layer/v-map-layer-helper.unit.js +234 -0
- package/dist/collection/lib/cesium-loader.js +58 -0
- package/dist/collection/lib/ensure-importmap.js +12 -0
- package/dist/collection/lib/ensure-importmap.unit.js +57 -0
- package/dist/collection/lib/versions.gen.js +6 -0
- package/dist/collection/lib/vstyle.js +8 -0
- package/dist/collection/map-provider/cesium/CesiumGeoTIFFTerrainProvider.js +285 -0
- package/dist/collection/map-provider/cesium/CesiumLayerGroups.js +159 -0
- package/dist/collection/map-provider/cesium/GeoTIFFImageryProvider.js +192 -0
- package/dist/collection/map-provider/cesium/GeoTIFFImageryProvider.test.js +57 -0
- package/dist/collection/map-provider/cesium/cesium-provider.js +1408 -0
- package/dist/collection/map-provider/cesium/i-layer.js +1 -0
- package/dist/collection/map-provider/cesium/layer-manager.js +467 -0
- package/dist/collection/map-provider/deck/DeckGLGeoTIFFLayer.js +483 -0
- package/dist/collection/map-provider/deck/DeckGLGeoTIFFTerrainLayer.js +410 -0
- package/dist/collection/map-provider/deck/LayerGroupWithModel.js +169 -0
- package/dist/collection/map-provider/deck/LayerGroups.js +192 -0
- package/dist/collection/map-provider/deck/LayerModel.js +1 -0
- package/dist/collection/map-provider/deck/RenderableGroup.js +1 -0
- package/dist/collection/map-provider/deck/deck-provider.js +1563 -0
- package/dist/collection/map-provider/geotiff/geotiff-source.js +172 -0
- package/dist/collection/map-provider/geotiff/utils/AABB2D.js +24 -0
- package/dist/collection/map-provider/geotiff/utils/BVHNode2D.js +166 -0
- package/dist/collection/map-provider/geotiff/utils/GeoTIFFTileProcessor.js +484 -0
- package/dist/collection/map-provider/geotiff/utils/Triangle.js +1 -0
- package/dist/collection/map-provider/geotiff/utils/Triangulation.js +321 -0
- package/dist/collection/map-provider/geotiff/utils/colormap-utils.js +190 -0
- package/dist/collection/map-provider/geotiff/utils/normalization-utils.js +122 -0
- package/dist/collection/map-provider/geotiff/utils/sampling-utils.js +108 -0
- package/dist/collection/map-provider/leaflet/GeoTIFFGridLayer.js +147 -0
- package/dist/collection/map-provider/leaflet/WCSGridLayer.js +124 -0
- package/dist/collection/map-provider/leaflet/google-map-tiles-layer.js +352 -0
- package/dist/collection/map-provider/leaflet/leaflet-helpers.js +94 -0
- package/dist/collection/map-provider/leaflet/leaflet-provider.js +1095 -0
- package/dist/collection/map-provider/ol/CustomGeoTiff.js +145 -0
- package/dist/collection/map-provider/ol/openlayers-helper.js +26 -0
- package/dist/collection/map-provider/ol/openlayers-provider.js +1427 -0
- package/dist/collection/map-provider/provider-factory.js +44 -0
- package/dist/collection/map-provider/provider-factory.unit.js +66 -0
- package/dist/collection/testing/browser-test-utils.js +49 -0
- package/dist/collection/testing/e2e-testing.js +122 -0
- package/dist/collection/testing/e2e-utils.js +70 -0
- package/dist/collection/testing/geotiff-test-server.js +100 -0
- package/dist/collection/testing/mocks/geostyler-lyrx-parser.js +12 -0
- package/dist/collection/testing/mocks/geostyler-mapbox-parser.js +12 -0
- package/dist/collection/testing/mocks/geostyler-qgis-parser.js +12 -0
- package/dist/collection/testing/mocks/geostyler-sld-parser.js +13 -0
- package/dist/collection/testing/mocks/geostyler-style.js +5 -0
- package/dist/collection/testing/setupTests.browser.js +1 -0
- package/dist/collection/testing/setupTests.stencil.js +20 -0
- package/dist/collection/testing/setupTests.vitest.js +59 -0
- package/dist/collection/testing/stencil-testing-wrapper.js +43 -0
- package/dist/collection/testing/styleMock.js +1 -0
- package/dist/collection/types/color.js +1 -0
- package/dist/collection/types/cssmode.js +1 -0
- package/dist/collection/types/flavour.js +1 -0
- package/dist/collection/types/layerconfig.js +1 -0
- package/dist/collection/types/lonlat.js +1 -0
- package/dist/collection/types/mapinitoptions.js +1 -0
- package/dist/collection/types/mapprovider.js +1 -0
- package/dist/collection/types/provideroptions.js +1 -0
- package/dist/collection/types/styleconfig.js +19 -0
- package/dist/collection/types/styling.js +13 -0
- package/dist/collection/types/styling.unit.js +37 -0
- package/dist/collection/types/vmaplayer.js +1 -0
- package/dist/collection/utils/async-mutex.js +28 -0
- package/dist/collection/utils/diff.js +142 -0
- package/dist/collection/utils/diff.unit.js +59 -0
- package/dist/collection/utils/dom-env.js +43 -0
- package/dist/collection/utils/dom-env.unit.js +92 -0
- package/dist/collection/utils/events.js +8 -0
- package/dist/collection/utils/logger.js +183 -0
- package/dist/collection/utils/logger.unit.js +98 -0
- package/dist/collection/utils/messages.js +12 -0
- package/dist/collection/utils/spatial-utils.js +27 -0
- package/dist/collection/utils/spatial-utils.unit.js +24 -0
- package/dist/components/_commonjsHelpers.js +1 -0
- package/dist/components/cesium-provider.js +1 -0
- package/dist/components/deck-provider.js +1 -0
- package/dist/components/events.js +1 -0
- package/dist/components/geotiff-source.js +1 -0
- package/dist/components/geotiff.js +4 -0
- package/dist/components/index.browser.js +15 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +1 -0
- package/dist/components/index2.js +1 -0
- package/dist/components/index3.js +1 -0
- package/dist/components/index4.js +1 -0
- package/dist/components/index5.js +1 -0
- package/dist/components/index6.js +1 -0
- package/dist/components/index7.js +1 -0
- package/dist/components/index8.js +7 -0
- package/dist/components/layer-extension.js +1 -0
- package/dist/components/leaflet-provider.js +1 -0
- package/dist/components/main-dist.js +1 -0
- package/dist/components/messages.js +1 -0
- package/dist/components/openlayers-provider.js +1 -0
- package/dist/components/polygon-layer.js +1 -0
- package/dist/components/scenegraph-layer.js +1 -0
- package/dist/components/styleconfig.js +1 -0
- package/dist/components/styling.js +1 -0
- package/dist/components/v-map-builder.d.ts +11 -0
- package/dist/components/v-map-builder.js +2 -0
- package/dist/components/v-map-layer-geojson.d.ts +11 -0
- package/dist/components/v-map-layer-geojson.js +1 -0
- package/dist/components/v-map-layer-geojson2.js +1 -0
- package/dist/components/v-map-layer-geotiff.d.ts +11 -0
- package/dist/components/v-map-layer-geotiff.js +1 -0
- package/dist/components/v-map-layer-geotiff2.js +1 -0
- package/dist/components/v-map-layer-google.d.ts +11 -0
- package/dist/components/v-map-layer-google.js +1 -0
- package/dist/components/v-map-layer-google2.js +1 -0
- package/dist/components/v-map-layer-helper.js +1 -0
- package/dist/components/v-map-layer-osm.d.ts +11 -0
- package/dist/components/v-map-layer-osm.js +1 -0
- package/dist/components/v-map-layer-osm2.js +1 -0
- package/dist/components/v-map-layer-scatterplot.d.ts +11 -0
- package/dist/components/v-map-layer-scatterplot.js +1 -0
- package/dist/components/v-map-layer-scatterplot2.js +1 -0
- package/dist/components/v-map-layer-terrain-geotiff.d.ts +11 -0
- package/dist/components/v-map-layer-terrain-geotiff.js +1 -0
- package/dist/components/v-map-layer-terrain.d.ts +11 -0
- package/dist/components/v-map-layer-terrain.js +1 -0
- package/dist/components/v-map-layer-terrain2.js +1 -0
- package/dist/components/v-map-layer-tile3d.d.ts +11 -0
- package/dist/components/v-map-layer-tile3d.js +1 -0
- package/dist/components/v-map-layer-tile3d2.js +1 -0
- package/dist/components/v-map-layer-wcs.d.ts +11 -0
- package/dist/components/v-map-layer-wcs.js +1 -0
- package/dist/components/v-map-layer-wcs2.js +1 -0
- package/dist/components/v-map-layer-wfs.d.ts +11 -0
- package/dist/components/v-map-layer-wfs.js +1 -0
- package/dist/components/v-map-layer-wfs2.js +1 -0
- package/dist/components/v-map-layer-wkt.d.ts +11 -0
- package/dist/components/v-map-layer-wkt.js +1 -0
- package/dist/components/v-map-layer-wkt2.js +1 -0
- package/dist/components/v-map-layer-wms.d.ts +11 -0
- package/dist/components/v-map-layer-wms.js +1 -0
- package/dist/components/v-map-layer-wms2.js +1 -0
- package/dist/components/v-map-layer-xyz.d.ts +11 -0
- package/dist/components/v-map-layer-xyz.js +1 -0
- package/dist/components/v-map-layer-xyz2.js +1 -0
- package/dist/components/v-map-layercontrol.d.ts +11 -0
- package/dist/components/v-map-layercontrol.js +1 -0
- package/dist/components/v-map-layergroup.d.ts +11 -0
- package/dist/components/v-map-layergroup.js +1 -0
- package/dist/components/v-map-layergroup2.js +1 -0
- package/dist/components/v-map-style.d.ts +11 -0
- package/dist/components/v-map-style.js +1 -0
- package/dist/components/v-map-style2.js +10 -0
- package/dist/components/v-map.d.ts +11 -0
- package/dist/components/v-map.js +1 -0
- package/dist/components/v-map2.js +1 -0
- package/dist/esm/_commonjsHelpers-E-ZsRS8r.js +32 -0
- package/dist/esm/app-globals-DQuL1Twl.js +3 -0
- package/dist/esm/cesium-provider-BJfAup3w.js +2596 -0
- package/dist/esm/deck-provider-C7U9VDEq.js +47709 -0
- package/dist/esm/geotiff-BEWxTIfH.js +45 -0
- package/dist/esm/geotiff-source-esnDnC-u.js +1516 -0
- package/dist/esm/index-B1zwA4IC.js +685 -0
- package/dist/esm/index-BBpiaTpT.js +165 -0
- package/dist/esm/index-BIEmlzCf.js +1697 -0
- package/dist/esm/index-BUHa4Jj0.js +307 -0
- package/dist/esm/index-DbSdn93t.js +20461 -0
- package/dist/esm/index-RpJarvr_.js +10656 -0
- package/dist/esm/index-jN06TXUp.js +14 -0
- package/dist/esm/index-jzneDarq.js +1613 -0
- package/dist/esm/index.browser-DhQAXuA7.js +6860 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/layer-extension-CZXK5goK.js +63 -0
- package/dist/esm/leaflet-provider-Q41TB6ku.js +1794 -0
- package/dist/esm/loader.js +11 -0
- package/dist/esm/main-dist-CwnA7_Xn.js +2652 -0
- package/dist/esm/messages-CMKJzsgL.js +180 -0
- package/dist/esm/openlayers-provider-CMsDsQTQ.js +1602 -0
- package/dist/esm/polygon-layer-ByhxGhWC.js +1295 -0
- package/dist/esm/scenegraph-layer-09K_B6DT.js +2526 -0
- package/dist/esm/styleconfig-B-bAcABs.js +21 -0
- package/dist/esm/v-map-builder.entry.js +3784 -0
- package/dist/esm/v-map-layer-geojson_12.entry.js +40881 -0
- package/dist/esm/v-map-layer-helper-Dys44Cgo.js +283 -0
- package/dist/esm/v-map-layer-terrain-geotiff.entry.js +256 -0
- package/dist/esm/v-map-layercontrol.entry.js +245 -0
- package/dist/esm/v-map.js +21 -0
- package/dist/esm/v-map.v-map-layer-osm.v-map-layergroup-B4pFHuSf.js +572 -0
- package/dist/esm/v-map_3.entry.js +4 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/types/cesium-augment.d.ts +5 -0
- package/dist/types/components/v-map/v-map.d.ts +70 -0
- package/dist/types/components/v-map/v-map.test.d.ts +1 -0
- package/dist/types/components/v-map-builder/v-map-builder.d.ts +48 -0
- package/dist/types/components/v-map-builder/v-map-builder.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-geojson/v-map-layer-geojson.d.ts +129 -0
- package/dist/types/components/v-map-layer-geojson/v-map-layer-geojson.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-geotiff/v-map-layer-geotiff.d.ts +74 -0
- package/dist/types/components/v-map-layer-geotiff/v-map-layer-geotiff.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-google/v-map-layer-google.d.ts +78 -0
- package/dist/types/components/v-map-layer-osm/error-api.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-osm/v-map-layer-osm.d.ts +50 -0
- package/dist/types/components/v-map-layer-osm/v-map-layer-osm.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-scatterplot/v-map-layer-scatterplot.d.ts +54 -0
- package/dist/types/components/v-map-layer-terrain/v-map-layer-terrain.d.ts +74 -0
- package/dist/types/components/v-map-layer-terrain/v-map-layer-terrain.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.d.ts +117 -0
- package/dist/types/components/v-map-layer-terrain-geotiff/v-map-layer-terrain-geotiff.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-tile3d/v-map-layer-tile3d.d.ts +69 -0
- package/dist/types/components/v-map-layer-tile3d/v-map-layer-tile3d.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-wcs/v-map-layer-wcs.d.ts +47 -0
- package/dist/types/components/v-map-layer-wcs/v-map-layer-wcs.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-wfs/v-map-layer-wfs.d.ts +59 -0
- package/dist/types/components/v-map-layer-wfs/v-map-layer-wfs.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-wkt/v-map-layer-wkt.d.ts +132 -0
- package/dist/types/components/v-map-layer-wkt/v-map-layer-wkt.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-wms/v-map-layer-wms.d.ts +76 -0
- package/dist/types/components/v-map-layer-wms/v-map-layer-wms.test.d.ts +1 -0
- package/dist/types/components/v-map-layer-xyz/v-map-layer-xyz.d.ts +59 -0
- package/dist/types/components/v-map-layer-xyz/v-map-layer-xyz.test.d.ts +1 -0
- package/dist/types/components/v-map-layercontrol/v-map-layercontrol.d.ts +44 -0
- package/dist/types/components/v-map-layercontrol/v-map-layercontrol.test.d.ts +1 -0
- package/dist/types/components/v-map-layergroup/v-map-layergroup.d.ts +31 -0
- package/dist/types/components/v-map-layergroup/v-map-layergroup.test.d.ts +1 -0
- package/dist/types/components/v-map-style/v-map-style.d.ts +75 -0
- package/dist/types/components/v-map-style/v-map-style.unit.d.ts +1 -0
- package/dist/types/components.d.ts +2391 -0
- package/dist/types/globals.d.ts +16 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/layer/v-map-layer-helper.d.ts +45 -0
- package/dist/types/layer/v-map-layer-helper.unit.d.ts +1 -0
- package/dist/types/leaflet-augment.d.ts +15 -0
- package/dist/types/lib/cesium-loader.d.ts +3 -0
- package/dist/types/lib/ensure-importmap.d.ts +3 -0
- package/dist/types/lib/ensure-importmap.unit.d.ts +1 -0
- package/dist/types/lib/versions.gen.d.ts +5 -0
- package/dist/types/lib/vstyle.d.ts +44 -0
- package/dist/types/map-provider/cesium/CesiumGeoTIFFTerrainProvider.d.ts +92 -0
- package/dist/types/map-provider/cesium/CesiumLayerGroups.d.ts +64 -0
- package/dist/types/map-provider/cesium/GeoTIFFImageryProvider.d.ts +75 -0
- package/dist/types/map-provider/cesium/GeoTIFFImageryProvider.test.d.ts +1 -0
- package/dist/types/map-provider/cesium/cesium-provider.d.ts +87 -0
- package/dist/types/map-provider/cesium/i-layer.d.ts +11 -0
- package/dist/types/map-provider/cesium/layer-manager.d.ts +31 -0
- package/dist/types/map-provider/deck/DeckGLGeoTIFFLayer.d.ts +91 -0
- package/dist/types/map-provider/deck/DeckGLGeoTIFFTerrainLayer.d.ts +82 -0
- package/dist/types/map-provider/deck/LayerGroupWithModel.d.ts +55 -0
- package/dist/types/map-provider/deck/LayerGroups.d.ts +63 -0
- package/dist/types/map-provider/deck/LayerModel.d.ts +8 -0
- package/dist/types/map-provider/deck/RenderableGroup.d.ts +20 -0
- package/dist/types/map-provider/deck/deck-provider.d.ts +92 -0
- package/dist/types/map-provider/geotiff/geotiff-source.d.ts +30 -0
- package/dist/types/map-provider/geotiff/utils/AABB2D.d.ts +28 -0
- package/dist/types/map-provider/geotiff/utils/BVHNode2D.d.ts +36 -0
- package/dist/types/map-provider/geotiff/utils/GeoTIFFTileProcessor.d.ts +116 -0
- package/dist/types/map-provider/geotiff/utils/Triangle.d.ts +5 -0
- package/dist/types/map-provider/geotiff/utils/Triangulation.d.ts +94 -0
- package/dist/types/map-provider/geotiff/utils/colormap-utils.d.ts +47 -0
- package/dist/types/map-provider/geotiff/utils/normalization-utils.d.ts +39 -0
- package/dist/types/map-provider/geotiff/utils/sampling-utils.d.ts +13 -0
- package/dist/types/map-provider/leaflet/GeoTIFFGridLayer.d.ts +34 -0
- package/dist/types/map-provider/leaflet/WCSGridLayer.d.ts +38 -0
- package/dist/types/map-provider/leaflet/google-map-tiles-layer.d.ts +73 -0
- package/dist/types/map-provider/leaflet/leaflet-helpers.d.ts +6 -0
- package/dist/types/map-provider/leaflet/leaflet-provider.d.ts +73 -0
- package/dist/types/map-provider/ol/CustomGeoTiff.d.ts +14 -0
- package/dist/types/map-provider/ol/openlayers-helper.d.ts +2 -0
- package/dist/types/map-provider/ol/openlayers-provider.d.ts +80 -0
- package/dist/types/map-provider/provider-factory.d.ts +12 -0
- package/dist/types/map-provider/provider-factory.unit.d.ts +1 -0
- package/dist/types/namespaces.d.ts +3 -0
- package/dist/types/ol-augment.d.ts +3 -0
- package/dist/types/ol-override.d.ts +7 -0
- package/dist/types/ol.d.ts +10 -0
- package/dist/types/stencil-public-runtime.d.ts +1860 -0
- package/dist/types/testing/browser-test-utils.d.ts +6 -0
- package/dist/types/testing/e2e-testing.d.ts +5 -0
- package/dist/types/testing/e2e-utils.d.ts +4 -0
- package/dist/types/testing/geotiff-test-server.d.ts +5 -0
- package/dist/types/testing/mocks/geostyler-lyrx-parser.d.ts +11 -0
- package/dist/types/testing/mocks/geostyler-mapbox-parser.d.ts +11 -0
- package/dist/types/testing/mocks/geostyler-qgis-parser.d.ts +11 -0
- package/dist/types/testing/mocks/geostyler-sld-parser.d.ts +11 -0
- package/dist/types/testing/mocks/geostyler-style.d.ts +5 -0
- package/dist/types/testing/setupTests.browser.d.ts +1 -0
- package/dist/types/testing/setupTests.stencil.d.ts +1 -0
- package/dist/types/testing/setupTests.vitest.d.ts +1 -0
- package/dist/types/testing/stencil-testing-wrapper.d.ts +3 -0
- package/dist/types/types/color.d.ts +1 -0
- package/dist/types/types/cssmode.d.ts +1 -0
- package/dist/types/types/flavour.d.ts +1 -0
- package/dist/types/types/layerconfig.d.ts +207 -0
- package/dist/types/types/lonlat.d.ts +1 -0
- package/dist/types/types/mapinitoptions.d.ts +4 -0
- package/dist/types/types/mapprovider.d.ts +46 -0
- package/dist/types/types/provideroptions.d.ts +8 -0
- package/dist/types/types/styleconfig.d.ts +27 -0
- package/dist/types/types/styling.d.ts +24 -0
- package/dist/types/types/styling.unit.d.ts +1 -0
- package/dist/types/types/vmaplayer.d.ts +10 -0
- package/dist/types/utils/async-mutex.d.ts +7 -0
- package/dist/types/utils/diff.d.ts +64 -0
- package/dist/types/utils/diff.unit.d.ts +1 -0
- package/dist/types/utils/dom-env.d.ts +5 -0
- package/dist/types/utils/dom-env.unit.d.ts +1 -0
- package/dist/types/utils/events.d.ts +29 -0
- package/dist/types/utils/logger.d.ts +47 -0
- package/dist/types/utils/logger.unit.d.ts +1 -0
- package/dist/types/utils/messages.d.ts +12 -0
- package/dist/types/utils/spatial-utils.d.ts +6 -0
- package/dist/types/utils/spatial-utils.unit.d.ts +1 -0
- package/dist/types/versions.d.ts +7 -0
- package/dist/v-map/index.esm.js +0 -0
- package/dist/v-map/p--vVleK-M.js +1 -0
- package/dist/v-map/p-09d10db0.entry.js +1 -0
- package/dist/v-map/p-5eba6058.entry.js +10 -0
- package/dist/v-map/p-6b102336.entry.js +1 -0
- package/dist/v-map/p-B-bAcABs.js +1 -0
- package/dist/v-map/p-BBpiaTpT.js +1 -0
- package/dist/v-map/p-BdijL4Av.js +1 -0
- package/dist/v-map/p-Be3r33VF.js +4 -0
- package/dist/v-map/p-BeFu0ap4.js +1 -0
- package/dist/v-map/p-BxFJezdK.js +1 -0
- package/dist/v-map/p-CMKJzsgL.js +1 -0
- package/dist/v-map/p-CXfA_q8m.js +1 -0
- package/dist/v-map/p-CZqY0yW4.js +1 -0
- package/dist/v-map/p-CafTHT9i.js +1 -0
- package/dist/v-map/p-DCTHyf58.js +1 -0
- package/dist/v-map/p-DQuL1Twl.js +1 -0
- package/dist/v-map/p-DR9McdNX.js +1 -0
- package/dist/v-map/p-Dckgonw8.js +1 -0
- package/dist/v-map/p-DhQAXuA7.js +15 -0
- package/dist/v-map/p-DmICdG34.js +7 -0
- package/dist/v-map/p-DrOQ9V4h.js +1 -0
- package/dist/v-map/p-DvHXtWUg.js +1 -0
- package/dist/v-map/p-E-ZsRS8r.js +1 -0
- package/dist/v-map/p-MyTSFnEk.js +1 -0
- package/dist/v-map/p-RpJarvr_.js +1 -0
- package/dist/v-map/p-WaMDUuAz.js +1 -0
- package/dist/v-map/p-aa410e64.entry.js +2 -0
- package/dist/v-map/p-c21c93fe.entry.js +1 -0
- package/dist/v-map/p-jzneDarq.js +2 -0
- package/dist/v-map/p-uiIP-taz.js +1 -0
- package/dist/v-map/v-map.esm.js +1 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +193 -0
|
@@ -0,0 +1,2526 @@
|
|
|
1
|
+
import { postProcessGLTF, GLTFLoader } from '@loaders.gl/gltf';
|
|
2
|
+
import { aK as lighting, a0 as Matrix4, V as Vector3, u as uid, aL as log, M as Model, G as Geometry, aM as Quaternion, L as Layer, p as project32, a as picking, aN as MATRIX_ATTRIBUTES, j as defaultLogger, aO as shouldComposeModelMatrix } from './deck-provider-C7U9VDEq.js';
|
|
3
|
+
|
|
4
|
+
// luma.gl
|
|
5
|
+
// SPDX-License-Identifier: MIT
|
|
6
|
+
// Copyright (c) vis.gl contributors
|
|
7
|
+
// Attribution:
|
|
8
|
+
// MIT license, Copyright (c) 2016-2017 Mohamad Moneimne and Contributors
|
|
9
|
+
// This fragment shader defines a reference implementation for Physically Based Shading of
|
|
10
|
+
// a microfacet surface material defined by a glTF model.
|
|
11
|
+
// TODO - better do the checks outside of shader
|
|
12
|
+
const vs$2 = /* glsl */ `\
|
|
13
|
+
out vec3 pbr_vPosition;
|
|
14
|
+
out vec2 pbr_vUV;
|
|
15
|
+
|
|
16
|
+
#ifdef HAS_NORMALS
|
|
17
|
+
# ifdef HAS_TANGENTS
|
|
18
|
+
out mat3 pbr_vTBN;
|
|
19
|
+
# else
|
|
20
|
+
out vec3 pbr_vNormal;
|
|
21
|
+
# endif
|
|
22
|
+
#endif
|
|
23
|
+
|
|
24
|
+
void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv)
|
|
25
|
+
{
|
|
26
|
+
vec4 pos = pbrProjection.modelMatrix * position;
|
|
27
|
+
pbr_vPosition = vec3(pos.xyz) / pos.w;
|
|
28
|
+
|
|
29
|
+
#ifdef HAS_NORMALS
|
|
30
|
+
#ifdef HAS_TANGENTS
|
|
31
|
+
vec3 normalW = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));
|
|
32
|
+
vec3 tangentW = normalize(vec3(pbrProjection.modelMatrix * vec4(tangent.xyz, 0.0)));
|
|
33
|
+
vec3 bitangentW = cross(normalW, tangentW) * tangent.w;
|
|
34
|
+
pbr_vTBN = mat3(tangentW, bitangentW, normalW);
|
|
35
|
+
#else // HAS_TANGENTS != 1
|
|
36
|
+
pbr_vNormal = normalize(vec3(pbrProjection.modelMatrix * vec4(normal.xyz, 0.0)));
|
|
37
|
+
#endif
|
|
38
|
+
#endif
|
|
39
|
+
|
|
40
|
+
#ifdef HAS_UV
|
|
41
|
+
pbr_vUV = uv;
|
|
42
|
+
#else
|
|
43
|
+
pbr_vUV = vec2(0.,0.);
|
|
44
|
+
#endif
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
const fs$2 = /* glsl */ `\
|
|
48
|
+
precision highp float;
|
|
49
|
+
|
|
50
|
+
uniform pbrMaterialUniforms {
|
|
51
|
+
// Material is unlit
|
|
52
|
+
bool unlit;
|
|
53
|
+
|
|
54
|
+
// Base color map
|
|
55
|
+
bool baseColorMapEnabled;
|
|
56
|
+
vec4 baseColorFactor;
|
|
57
|
+
|
|
58
|
+
bool normalMapEnabled;
|
|
59
|
+
float normalScale; // #ifdef HAS_NORMALMAP
|
|
60
|
+
|
|
61
|
+
bool emissiveMapEnabled;
|
|
62
|
+
vec3 emissiveFactor; // #ifdef HAS_EMISSIVEMAP
|
|
63
|
+
|
|
64
|
+
vec2 metallicRoughnessValues;
|
|
65
|
+
bool metallicRoughnessMapEnabled;
|
|
66
|
+
|
|
67
|
+
bool occlusionMapEnabled;
|
|
68
|
+
float occlusionStrength; // #ifdef HAS_OCCLUSIONMAP
|
|
69
|
+
|
|
70
|
+
bool alphaCutoffEnabled;
|
|
71
|
+
float alphaCutoff; // #ifdef ALPHA_CUTOFF
|
|
72
|
+
|
|
73
|
+
// IBL
|
|
74
|
+
bool IBLenabled;
|
|
75
|
+
vec2 scaleIBLAmbient; // #ifdef USE_IBL
|
|
76
|
+
|
|
77
|
+
// debugging flags used for shader output of intermediate PBR variables
|
|
78
|
+
// #ifdef PBR_DEBUG
|
|
79
|
+
vec4 scaleDiffBaseMR;
|
|
80
|
+
vec4 scaleFGDSpec;
|
|
81
|
+
// #endif
|
|
82
|
+
} pbrMaterial;
|
|
83
|
+
|
|
84
|
+
// Samplers
|
|
85
|
+
#ifdef HAS_BASECOLORMAP
|
|
86
|
+
uniform sampler2D pbr_baseColorSampler;
|
|
87
|
+
#endif
|
|
88
|
+
#ifdef HAS_NORMALMAP
|
|
89
|
+
uniform sampler2D pbr_normalSampler;
|
|
90
|
+
#endif
|
|
91
|
+
#ifdef HAS_EMISSIVEMAP
|
|
92
|
+
uniform sampler2D pbr_emissiveSampler;
|
|
93
|
+
#endif
|
|
94
|
+
#ifdef HAS_METALROUGHNESSMAP
|
|
95
|
+
uniform sampler2D pbr_metallicRoughnessSampler;
|
|
96
|
+
#endif
|
|
97
|
+
#ifdef HAS_OCCLUSIONMAP
|
|
98
|
+
uniform sampler2D pbr_occlusionSampler;
|
|
99
|
+
#endif
|
|
100
|
+
#ifdef USE_IBL
|
|
101
|
+
uniform samplerCube pbr_diffuseEnvSampler;
|
|
102
|
+
uniform samplerCube pbr_specularEnvSampler;
|
|
103
|
+
uniform sampler2D pbr_brdfLUT;
|
|
104
|
+
#endif
|
|
105
|
+
|
|
106
|
+
// Inputs from vertex shader
|
|
107
|
+
|
|
108
|
+
in vec3 pbr_vPosition;
|
|
109
|
+
in vec2 pbr_vUV;
|
|
110
|
+
|
|
111
|
+
#ifdef HAS_NORMALS
|
|
112
|
+
#ifdef HAS_TANGENTS
|
|
113
|
+
in mat3 pbr_vTBN;
|
|
114
|
+
#else
|
|
115
|
+
in vec3 pbr_vNormal;
|
|
116
|
+
#endif
|
|
117
|
+
#endif
|
|
118
|
+
|
|
119
|
+
// Encapsulate the various inputs used by the various functions in the shading equation
|
|
120
|
+
// We store values in this struct to simplify the integration of alternative implementations
|
|
121
|
+
// of the shading terms, outlined in the Readme.MD Appendix.
|
|
122
|
+
struct PBRInfo {
|
|
123
|
+
float NdotL; // cos angle between normal and light direction
|
|
124
|
+
float NdotV; // cos angle between normal and view direction
|
|
125
|
+
float NdotH; // cos angle between normal and half vector
|
|
126
|
+
float LdotH; // cos angle between light direction and half vector
|
|
127
|
+
float VdotH; // cos angle between view direction and half vector
|
|
128
|
+
float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)
|
|
129
|
+
float metalness; // metallic value at the surface
|
|
130
|
+
vec3 reflectance0; // full reflectance color (normal incidence angle)
|
|
131
|
+
vec3 reflectance90; // reflectance color at grazing angle
|
|
132
|
+
float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])
|
|
133
|
+
vec3 diffuseColor; // color contribution from diffuse lighting
|
|
134
|
+
vec3 specularColor; // color contribution from specular lighting
|
|
135
|
+
vec3 n; // normal at surface point
|
|
136
|
+
vec3 v; // vector from surface point to camera
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const float M_PI = 3.141592653589793;
|
|
140
|
+
const float c_MinRoughness = 0.04;
|
|
141
|
+
|
|
142
|
+
vec4 SRGBtoLINEAR(vec4 srgbIn)
|
|
143
|
+
{
|
|
144
|
+
#ifdef MANUAL_SRGB
|
|
145
|
+
#ifdef SRGB_FAST_APPROXIMATION
|
|
146
|
+
vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
|
|
147
|
+
#else // SRGB_FAST_APPROXIMATION
|
|
148
|
+
vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
|
|
149
|
+
vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
|
|
150
|
+
#endif //SRGB_FAST_APPROXIMATION
|
|
151
|
+
return vec4(linOut,srgbIn.w);;
|
|
152
|
+
#else //MANUAL_SRGB
|
|
153
|
+
return srgbIn;
|
|
154
|
+
#endif //MANUAL_SRGB
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Find the normal for this fragment, pulling either from a predefined normal map
|
|
158
|
+
// or from the interpolated mesh normal and tangent attributes.
|
|
159
|
+
vec3 getNormal()
|
|
160
|
+
{
|
|
161
|
+
// Retrieve the tangent space matrix
|
|
162
|
+
#ifndef HAS_TANGENTS
|
|
163
|
+
vec3 pos_dx = dFdx(pbr_vPosition);
|
|
164
|
+
vec3 pos_dy = dFdy(pbr_vPosition);
|
|
165
|
+
vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0));
|
|
166
|
+
vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0));
|
|
167
|
+
vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
|
|
168
|
+
|
|
169
|
+
#ifdef HAS_NORMALS
|
|
170
|
+
vec3 ng = normalize(pbr_vNormal);
|
|
171
|
+
#else
|
|
172
|
+
vec3 ng = cross(pos_dx, pos_dy);
|
|
173
|
+
#endif
|
|
174
|
+
|
|
175
|
+
t = normalize(t - ng * dot(ng, t));
|
|
176
|
+
vec3 b = normalize(cross(ng, t));
|
|
177
|
+
mat3 tbn = mat3(t, b, ng);
|
|
178
|
+
#else // HAS_TANGENTS
|
|
179
|
+
mat3 tbn = pbr_vTBN;
|
|
180
|
+
#endif
|
|
181
|
+
|
|
182
|
+
#ifdef HAS_NORMALMAP
|
|
183
|
+
vec3 n = texture(pbr_normalSampler, pbr_vUV).rgb;
|
|
184
|
+
n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
|
|
185
|
+
#else
|
|
186
|
+
// The tbn matrix is linearly interpolated, so we need to re-normalize
|
|
187
|
+
vec3 n = normalize(tbn[2].xyz);
|
|
188
|
+
#endif
|
|
189
|
+
|
|
190
|
+
return n;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Calculation of the lighting contribution from an optional Image Based Light source.
|
|
194
|
+
// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
|
|
195
|
+
// See our README.md on Environment Maps [3] for additional discussion.
|
|
196
|
+
#ifdef USE_IBL
|
|
197
|
+
vec3 getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection)
|
|
198
|
+
{
|
|
199
|
+
float mipCount = 9.0; // resolution of 512x512
|
|
200
|
+
float lod = (pbrInfo.perceptualRoughness * mipCount);
|
|
201
|
+
// retrieve a scale and bias to F0. See [1], Figure 3
|
|
202
|
+
vec3 brdf = SRGBtoLINEAR(texture(pbr_brdfLUT,
|
|
203
|
+
vec2(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness))).rgb;
|
|
204
|
+
vec3 diffuseLight = SRGBtoLINEAR(texture(pbr_diffuseEnvSampler, n)).rgb;
|
|
205
|
+
|
|
206
|
+
#ifdef USE_TEX_LOD
|
|
207
|
+
vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection, lod)).rgb;
|
|
208
|
+
#else
|
|
209
|
+
vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection)).rgb;
|
|
210
|
+
#endif
|
|
211
|
+
|
|
212
|
+
vec3 diffuse = diffuseLight * pbrInfo.diffuseColor;
|
|
213
|
+
vec3 specular = specularLight * (pbrInfo.specularColor * brdf.x + brdf.y);
|
|
214
|
+
|
|
215
|
+
// For presentation, this allows us to disable IBL terms
|
|
216
|
+
diffuse *= pbrMaterial.scaleIBLAmbient.x;
|
|
217
|
+
specular *= pbrMaterial.scaleIBLAmbient.y;
|
|
218
|
+
|
|
219
|
+
return diffuse + specular;
|
|
220
|
+
}
|
|
221
|
+
#endif
|
|
222
|
+
|
|
223
|
+
// Basic Lambertian diffuse
|
|
224
|
+
// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
|
|
225
|
+
// See also [1], Equation 1
|
|
226
|
+
vec3 diffuse(PBRInfo pbrInfo)
|
|
227
|
+
{
|
|
228
|
+
return pbrInfo.diffuseColor / M_PI;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// The following equation models the Fresnel reflectance term of the spec equation (aka F())
|
|
232
|
+
// Implementation of fresnel from [4], Equation 15
|
|
233
|
+
vec3 specularReflection(PBRInfo pbrInfo)
|
|
234
|
+
{
|
|
235
|
+
return pbrInfo.reflectance0 +
|
|
236
|
+
(pbrInfo.reflectance90 - pbrInfo.reflectance0) *
|
|
237
|
+
pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// This calculates the specular geometric attenuation (aka G()),
|
|
241
|
+
// where rougher material will reflect less light back to the viewer.
|
|
242
|
+
// This implementation is based on [1] Equation 4, and we adopt their modifications to
|
|
243
|
+
// alphaRoughness as input as originally proposed in [2].
|
|
244
|
+
float geometricOcclusion(PBRInfo pbrInfo)
|
|
245
|
+
{
|
|
246
|
+
float NdotL = pbrInfo.NdotL;
|
|
247
|
+
float NdotV = pbrInfo.NdotV;
|
|
248
|
+
float r = pbrInfo.alphaRoughness;
|
|
249
|
+
|
|
250
|
+
float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
|
|
251
|
+
float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
|
|
252
|
+
return attenuationL * attenuationV;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// The following equation(s) model the distribution of microfacet normals across
|
|
256
|
+
// the area being drawn (aka D())
|
|
257
|
+
// Implementation from "Average Irregularity Representation of a Roughened Surface
|
|
258
|
+
// for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz
|
|
259
|
+
// Follows the distribution function recommended in the SIGGRAPH 2013 course notes
|
|
260
|
+
// from EPIC Games [1], Equation 3.
|
|
261
|
+
float microfacetDistribution(PBRInfo pbrInfo)
|
|
262
|
+
{
|
|
263
|
+
float roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;
|
|
264
|
+
float f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;
|
|
265
|
+
return roughnessSq / (M_PI * f * f);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
void PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) {
|
|
269
|
+
pbrInfo.NdotL = 1.0;
|
|
270
|
+
pbrInfo.NdotH = 0.0;
|
|
271
|
+
pbrInfo.LdotH = 0.0;
|
|
272
|
+
pbrInfo.VdotH = 1.0;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
void PBRInfo_setDirectionalLight(inout PBRInfo pbrInfo, vec3 lightDirection) {
|
|
276
|
+
vec3 n = pbrInfo.n;
|
|
277
|
+
vec3 v = pbrInfo.v;
|
|
278
|
+
vec3 l = normalize(lightDirection); // Vector from surface point to light
|
|
279
|
+
vec3 h = normalize(l+v); // Half vector between both l and v
|
|
280
|
+
|
|
281
|
+
pbrInfo.NdotL = clamp(dot(n, l), 0.001, 1.0);
|
|
282
|
+
pbrInfo.NdotH = clamp(dot(n, h), 0.0, 1.0);
|
|
283
|
+
pbrInfo.LdotH = clamp(dot(l, h), 0.0, 1.0);
|
|
284
|
+
pbrInfo.VdotH = clamp(dot(v, h), 0.0, 1.0);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
void PBRInfo_setPointLight(inout PBRInfo pbrInfo, PointLight pointLight) {
|
|
288
|
+
vec3 light_direction = normalize(pointLight.position - pbr_vPosition);
|
|
289
|
+
PBRInfo_setDirectionalLight(pbrInfo, light_direction);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
|
|
293
|
+
// Calculate the shading terms for the microfacet specular shading model
|
|
294
|
+
vec3 F = specularReflection(pbrInfo);
|
|
295
|
+
float G = geometricOcclusion(pbrInfo);
|
|
296
|
+
float D = microfacetDistribution(pbrInfo);
|
|
297
|
+
|
|
298
|
+
// Calculation of analytical lighting contribution
|
|
299
|
+
vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInfo);
|
|
300
|
+
vec3 specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV);
|
|
301
|
+
// Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
|
|
302
|
+
return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
vec4 pbr_filterColor(vec4 colorUnused)
|
|
306
|
+
{
|
|
307
|
+
// The albedo may be defined from a base texture or a flat color
|
|
308
|
+
#ifdef HAS_BASECOLORMAP
|
|
309
|
+
vec4 baseColor = SRGBtoLINEAR(texture(pbr_baseColorSampler, pbr_vUV)) * pbrMaterial.baseColorFactor;
|
|
310
|
+
#else
|
|
311
|
+
vec4 baseColor = pbrMaterial.baseColorFactor;
|
|
312
|
+
#endif
|
|
313
|
+
|
|
314
|
+
#ifdef ALPHA_CUTOFF
|
|
315
|
+
if (baseColor.a < pbrMaterial.alphaCutoff) {
|
|
316
|
+
discard;
|
|
317
|
+
}
|
|
318
|
+
#endif
|
|
319
|
+
|
|
320
|
+
vec3 color = vec3(0, 0, 0);
|
|
321
|
+
|
|
322
|
+
if(pbrMaterial.unlit){
|
|
323
|
+
color.rgb = baseColor.rgb;
|
|
324
|
+
}
|
|
325
|
+
else{
|
|
326
|
+
// Metallic and Roughness material properties are packed together
|
|
327
|
+
// In glTF, these factors can be specified by fixed scalar values
|
|
328
|
+
// or from a metallic-roughness map
|
|
329
|
+
float perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;
|
|
330
|
+
float metallic = pbrMaterial.metallicRoughnessValues.x;
|
|
331
|
+
#ifdef HAS_METALROUGHNESSMAP
|
|
332
|
+
// Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
|
|
333
|
+
// This layout intentionally reserves the 'r' channel for (optional) occlusion map data
|
|
334
|
+
vec4 mrSample = texture(pbr_metallicRoughnessSampler, pbr_vUV);
|
|
335
|
+
perceptualRoughness = mrSample.g * perceptualRoughness;
|
|
336
|
+
metallic = mrSample.b * metallic;
|
|
337
|
+
#endif
|
|
338
|
+
perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
|
|
339
|
+
metallic = clamp(metallic, 0.0, 1.0);
|
|
340
|
+
// Roughness is authored as perceptual roughness; as is convention,
|
|
341
|
+
// convert to material roughness by squaring the perceptual roughness [2].
|
|
342
|
+
float alphaRoughness = perceptualRoughness * perceptualRoughness;
|
|
343
|
+
|
|
344
|
+
vec3 f0 = vec3(0.04);
|
|
345
|
+
vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
|
|
346
|
+
diffuseColor *= 1.0 - metallic;
|
|
347
|
+
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
|
|
348
|
+
|
|
349
|
+
// Compute reflectance.
|
|
350
|
+
float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
|
|
351
|
+
|
|
352
|
+
// For typical incident reflectance range (between 4% to 100%) set the grazing
|
|
353
|
+
// reflectance to 100% for typical fresnel effect.
|
|
354
|
+
// For very low reflectance range on highly diffuse objects (below 4%),
|
|
355
|
+
// incrementally reduce grazing reflecance to 0%.
|
|
356
|
+
float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
|
|
357
|
+
vec3 specularEnvironmentR0 = specularColor.rgb;
|
|
358
|
+
vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
|
|
359
|
+
|
|
360
|
+
vec3 n = getNormal(); // normal at surface point
|
|
361
|
+
vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
|
|
362
|
+
|
|
363
|
+
float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
|
|
364
|
+
vec3 reflection = -normalize(reflect(v, n));
|
|
365
|
+
|
|
366
|
+
PBRInfo pbrInfo = PBRInfo(
|
|
367
|
+
0.0, // NdotL
|
|
368
|
+
NdotV,
|
|
369
|
+
0.0, // NdotH
|
|
370
|
+
0.0, // LdotH
|
|
371
|
+
0.0, // VdotH
|
|
372
|
+
perceptualRoughness,
|
|
373
|
+
metallic,
|
|
374
|
+
specularEnvironmentR0,
|
|
375
|
+
specularEnvironmentR90,
|
|
376
|
+
alphaRoughness,
|
|
377
|
+
diffuseColor,
|
|
378
|
+
specularColor,
|
|
379
|
+
n,
|
|
380
|
+
v
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
#ifdef USE_LIGHTS
|
|
385
|
+
// Apply ambient light
|
|
386
|
+
PBRInfo_setAmbientLight(pbrInfo);
|
|
387
|
+
color += calculateFinalColor(pbrInfo, lighting.ambientColor);
|
|
388
|
+
|
|
389
|
+
// Apply directional light
|
|
390
|
+
for(int i = 0; i < lighting.directionalLightCount; i++) {
|
|
391
|
+
if (i < lighting.directionalLightCount) {
|
|
392
|
+
PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
|
|
393
|
+
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Apply point light
|
|
398
|
+
for(int i = 0; i < lighting.pointLightCount; i++) {
|
|
399
|
+
if (i < lighting.pointLightCount) {
|
|
400
|
+
PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
|
|
401
|
+
float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
|
|
402
|
+
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
#endif
|
|
406
|
+
|
|
407
|
+
// Calculate lighting contribution from image based lighting source (IBL)
|
|
408
|
+
#ifdef USE_IBL
|
|
409
|
+
if (pbrMaterial.IBLenabled) {
|
|
410
|
+
color += getIBLContribution(pbrInfo, n, reflection);
|
|
411
|
+
}
|
|
412
|
+
#endif
|
|
413
|
+
|
|
414
|
+
// Apply optional PBR terms for additional (optional) shading
|
|
415
|
+
#ifdef HAS_OCCLUSIONMAP
|
|
416
|
+
if (pbrMaterial.occlusionMapEnabled) {
|
|
417
|
+
float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
|
|
418
|
+
color = mix(color, color * ao, pbrMaterial.occlusionStrength);
|
|
419
|
+
}
|
|
420
|
+
#endif
|
|
421
|
+
|
|
422
|
+
#ifdef HAS_EMISSIVEMAP
|
|
423
|
+
if (pbrMaterial.emissiveMapEnabled) {
|
|
424
|
+
vec3 emissive = SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
|
|
425
|
+
color += emissive;
|
|
426
|
+
}
|
|
427
|
+
#endif
|
|
428
|
+
|
|
429
|
+
// This section uses mix to override final color for reference app visualization
|
|
430
|
+
// of various parameters in the lighting equation.
|
|
431
|
+
#ifdef PBR_DEBUG
|
|
432
|
+
// TODO: Figure out how to debug multiple lights
|
|
433
|
+
|
|
434
|
+
// color = mix(color, F, pbr_scaleFGDSpec.x);
|
|
435
|
+
// color = mix(color, vec3(G), pbr_scaleFGDSpec.y);
|
|
436
|
+
// color = mix(color, vec3(D), pbr_scaleFGDSpec.z);
|
|
437
|
+
// color = mix(color, specContrib, pbr_scaleFGDSpec.w);
|
|
438
|
+
|
|
439
|
+
// color = mix(color, diffuseContrib, pbr_scaleDiffBaseMR.x);
|
|
440
|
+
color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
|
|
441
|
+
color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);
|
|
442
|
+
color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
|
|
443
|
+
#endif
|
|
444
|
+
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return vec4(pow(color,vec3(1.0/2.2)), baseColor.a);
|
|
448
|
+
}
|
|
449
|
+
`;
|
|
450
|
+
|
|
451
|
+
// luma.gl
|
|
452
|
+
// SPDX-License-Identifier: MIT
|
|
453
|
+
// Copyright (c) vis.gl contributors
|
|
454
|
+
// Attribution:
|
|
455
|
+
// MIT license, Copyright (c) 2016-2017 Mohamad Moneimne and Contributors
|
|
456
|
+
// This fragment shader defines a reference implementation for Physically Based Shading of
|
|
457
|
+
// a microfacet surface material defined by a glTF model.
|
|
458
|
+
// TODO - better do the checks outside of shader
|
|
459
|
+
const source = /* wgsl */ `\
|
|
460
|
+
struct PBRFragmentInputs {
|
|
461
|
+
pbr_vPosition: vec3f,
|
|
462
|
+
pbr_vUV: vec2f,
|
|
463
|
+
pbr_vTBN: mat3f,
|
|
464
|
+
pbr_vNormal: vec3f
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
var fragmentInputs: PBRFragmentInputs;
|
|
468
|
+
|
|
469
|
+
fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f, uv: vec2f)
|
|
470
|
+
{
|
|
471
|
+
var pos: vec4f = pbrProjection.modelMatrix * position;
|
|
472
|
+
pbr_vPosition = vec3(pos.xyz) / pos.w;
|
|
473
|
+
|
|
474
|
+
#ifdef HAS_NORMALS
|
|
475
|
+
#ifdef HAS_TANGENTS
|
|
476
|
+
let normalW: vec3f = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));
|
|
477
|
+
let tangentW: vec3f = normalize(vec3(pbrProjection.modelMatrix * vec4(tangent.xyz, 0.0)));
|
|
478
|
+
let bitangentW: vec3f = cross(normalW, tangentW) * tangent.w;
|
|
479
|
+
fragmentInputs,pbr_vTBN = mat3(tangentW, bitangentW, normalW);
|
|
480
|
+
#else // HAS_TANGENTS != 1
|
|
481
|
+
fragmentInputs.pbr_vNormal = normalize(vec3(pbrProjection.modelMatrix * vec4(normal.xyz, 0.0)));
|
|
482
|
+
#endif
|
|
483
|
+
#endif
|
|
484
|
+
|
|
485
|
+
#ifdef HAS_UV
|
|
486
|
+
pbr_vUV = uv;
|
|
487
|
+
#else
|
|
488
|
+
pbr_vUV = vec2(0.,0.);
|
|
489
|
+
#endif
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
struct pbrMaterialUniforms {
|
|
493
|
+
// Material is unlit
|
|
494
|
+
unlit: uint32,
|
|
495
|
+
|
|
496
|
+
// Base color map
|
|
497
|
+
baseColorMapEnabled: uint32,
|
|
498
|
+
baseColorFactor: vec4f,
|
|
499
|
+
|
|
500
|
+
normalMapEnabled : uint32,
|
|
501
|
+
normalScale: f32, // #ifdef HAS_NORMALMAP
|
|
502
|
+
|
|
503
|
+
emissiveMapEnabled: uint32,
|
|
504
|
+
emissiveFactor: vec3f, // #ifdef HAS_EMISSIVEMAP
|
|
505
|
+
|
|
506
|
+
metallicRoughnessValues: vec2f,
|
|
507
|
+
metallicRoughnessMapEnabled: uint32,
|
|
508
|
+
|
|
509
|
+
occlusionMapEnabled: i32,
|
|
510
|
+
occlusionStrength: f32, // #ifdef HAS_OCCLUSIONMAP
|
|
511
|
+
|
|
512
|
+
alphaCutoffEnabled: i32,
|
|
513
|
+
alphaCutoff: f32, // #ifdef ALPHA_CUTOFF
|
|
514
|
+
|
|
515
|
+
// IBL
|
|
516
|
+
IBLenabled: i32,
|
|
517
|
+
scaleIBLAmbient: vec2f, // #ifdef USE_IBL
|
|
518
|
+
|
|
519
|
+
// debugging flags used for shader output of intermediate PBR variables
|
|
520
|
+
// #ifdef PBR_DEBUG
|
|
521
|
+
scaleDiffBaseMR: vec4f,
|
|
522
|
+
scaleFGDSpec: vec4f
|
|
523
|
+
// #endif
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
@binding(2) @group(0) var<uniform> material : pbrMaterialUniforms;
|
|
527
|
+
|
|
528
|
+
// Samplers
|
|
529
|
+
#ifdef HAS_BASECOLORMAP
|
|
530
|
+
uniform sampler2D pbr_baseColorSampler;
|
|
531
|
+
#endif
|
|
532
|
+
#ifdef HAS_NORMALMAP
|
|
533
|
+
uniform sampler2D pbr_normalSampler;
|
|
534
|
+
#endif
|
|
535
|
+
#ifdef HAS_EMISSIVEMAP
|
|
536
|
+
uniform sampler2D pbr_emissiveSampler;
|
|
537
|
+
#endif
|
|
538
|
+
#ifdef HAS_METALROUGHNESSMAP
|
|
539
|
+
uniform sampler2D pbr_metallicRoughnessSampler;
|
|
540
|
+
#endif
|
|
541
|
+
#ifdef HAS_OCCLUSIONMAP
|
|
542
|
+
uniform sampler2D pbr_occlusionSampler;
|
|
543
|
+
#endif
|
|
544
|
+
#ifdef USE_IBL
|
|
545
|
+
uniform samplerCube pbr_diffuseEnvSampler;
|
|
546
|
+
uniform samplerCube pbr_specularEnvSampler;
|
|
547
|
+
uniform sampler2D pbr_brdfLUT;
|
|
548
|
+
#endif
|
|
549
|
+
|
|
550
|
+
// Encapsulate the various inputs used by the various functions in the shading equation
|
|
551
|
+
// We store values in this struct to simplify the integration of alternative implementations
|
|
552
|
+
// of the shading terms, outlined in the Readme.MD Appendix.
|
|
553
|
+
struct PBRInfo {
|
|
554
|
+
NdotL: f32, // cos angle between normal and light direction
|
|
555
|
+
NdotV: f32, // cos angle between normal and view direction
|
|
556
|
+
NdotH: f32, // cos angle between normal and half vector
|
|
557
|
+
LdotH: f32, // cos angle between light direction and half vector
|
|
558
|
+
VdotH: f32, // cos angle between view direction and half vector
|
|
559
|
+
perceptualRoughness: f32, // roughness value, as authored by the model creator (input to shader)
|
|
560
|
+
metalness: f32, // metallic value at the surface
|
|
561
|
+
reflectance0: vec3f, // full reflectance color (normal incidence angle)
|
|
562
|
+
reflectance90: vec3f, // reflectance color at grazing angle
|
|
563
|
+
alphaRoughness: f32, // roughness mapped to a more linear change in the roughness (proposed by [2])
|
|
564
|
+
diffuseColor: vec3f, // color contribution from diffuse lighting
|
|
565
|
+
specularColor: vec3f, // color contribution from specular lighting
|
|
566
|
+
n: vec3f, // normal at surface point
|
|
567
|
+
v: vec3f, // vector from surface point to camera
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
const M_PI = 3.141592653589793;
|
|
571
|
+
const c_MinRoughness = 0.04;
|
|
572
|
+
|
|
573
|
+
fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
|
|
574
|
+
{
|
|
575
|
+
#ifdef MANUAL_SRGB
|
|
576
|
+
#ifdef SRGB_FAST_APPROXIMATION
|
|
577
|
+
var linOut: vec3f = pow(srgbIn.xyz,vec3(2.2));
|
|
578
|
+
#else // SRGB_FAST_APPROXIMATION
|
|
579
|
+
var bLess: vec3f = step(vec3(0.04045),srgbIn.xyz);
|
|
580
|
+
var linOut: vec3f = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
|
|
581
|
+
#endif //SRGB_FAST_APPROXIMATION
|
|
582
|
+
return vec4f(linOut,srgbIn.w);;
|
|
583
|
+
#else //MANUAL_SRGB
|
|
584
|
+
return srgbIn;
|
|
585
|
+
#endif //MANUAL_SRGB
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Find the normal for this fragment, pulling either from a predefined normal map
|
|
589
|
+
// or from the interpolated mesh normal and tangent attributes.
|
|
590
|
+
fn getNormal() -> vec3f
|
|
591
|
+
{
|
|
592
|
+
// Retrieve the tangent space matrix
|
|
593
|
+
#ifndef HAS_TANGENTS
|
|
594
|
+
var pos_dx: vec3f = dFdx(pbr_vPosition);
|
|
595
|
+
var pos_dy: vec3f = dFdy(pbr_vPosition);
|
|
596
|
+
var tex_dx: vec3f = dFdx(vec3(pbr_vUV, 0.0));
|
|
597
|
+
var tex_dy: vec3f = dFdy(vec3(pbr_vUV, 0.0));
|
|
598
|
+
var t: vec3f = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
|
|
599
|
+
|
|
600
|
+
#ifdef HAS_NORMALS
|
|
601
|
+
var ng: vec3f = normalize(pbr_vNormal);
|
|
602
|
+
#else
|
|
603
|
+
var ng: vec3f = cross(pos_dx, pos_dy);
|
|
604
|
+
#endif
|
|
605
|
+
|
|
606
|
+
t = normalize(t - ng * dot(ng, t));
|
|
607
|
+
var b: vec3f = normalize(cross(ng, t));
|
|
608
|
+
var tbn: mat3f = mat3f(t, b, ng);
|
|
609
|
+
#else // HAS_TANGENTS
|
|
610
|
+
var tbn: mat3f = pbr_vTBN;
|
|
611
|
+
#endif
|
|
612
|
+
|
|
613
|
+
#ifdef HAS_NORMALMAP
|
|
614
|
+
vec3 n = texture(pbr_normalSampler, pbr_vUV).rgb;
|
|
615
|
+
n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
|
|
616
|
+
#else
|
|
617
|
+
// The tbn matrix is linearly interpolated, so we need to re-normalize
|
|
618
|
+
vec3 n = normalize(tbn[2].xyz);
|
|
619
|
+
#endif
|
|
620
|
+
|
|
621
|
+
return n;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// Calculation of the lighting contribution from an optional Image Based Light source.
|
|
625
|
+
// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
|
|
626
|
+
// See our README.md on Environment Maps [3] for additional discussion.
|
|
627
|
+
#ifdef USE_IBL
|
|
628
|
+
fn getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection) -> vec3f
|
|
629
|
+
{
|
|
630
|
+
float mipCount = 9.0; // resolution of 512x512
|
|
631
|
+
float lod = (pbrInfo.perceptualRoughness * mipCount);
|
|
632
|
+
// retrieve a scale and bias to F0. See [1], Figure 3
|
|
633
|
+
vec3 brdf = SRGBtoLINEAR(texture(pbr_brdfLUT,
|
|
634
|
+
vec2(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness))).rgb;
|
|
635
|
+
vec3 diffuseLight = SRGBtoLINEAR(texture(pbr_diffuseEnvSampler, n)).rgb;
|
|
636
|
+
|
|
637
|
+
#ifdef USE_TEX_LOD
|
|
638
|
+
vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection, lod)).rgb;
|
|
639
|
+
#else
|
|
640
|
+
vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection)).rgb;
|
|
641
|
+
#endif
|
|
642
|
+
|
|
643
|
+
vec3 diffuse = diffuseLight * pbrInfo.diffuseColor;
|
|
644
|
+
vec3 specular = specularLight * (pbrInfo.specularColor * brdf.x + brdf.y);
|
|
645
|
+
|
|
646
|
+
// For presentation, this allows us to disable IBL terms
|
|
647
|
+
diffuse *= pbrMaterial.scaleIBLAmbient.x;
|
|
648
|
+
specular *= pbrMaterial.scaleIBLAmbient.y;
|
|
649
|
+
|
|
650
|
+
return diffuse + specular;
|
|
651
|
+
}
|
|
652
|
+
#endif
|
|
653
|
+
|
|
654
|
+
// Basic Lambertian diffuse
|
|
655
|
+
// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
|
|
656
|
+
// See also [1], Equation 1
|
|
657
|
+
fn diffuse(pbrInfo: PBRInfo) -> vec3<f32> {
|
|
658
|
+
return pbrInfo.diffuseColor / PI;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// The following equation models the Fresnel reflectance term of the spec equation (aka F())
|
|
662
|
+
// Implementation of fresnel from [4], Equation 15
|
|
663
|
+
fn specularReflection(pbrInfo: PBRInfo) -> vec3<f32> {
|
|
664
|
+
return pbrInfo.reflectance0 +
|
|
665
|
+
(pbrInfo.reflectance90 - pbrInfo.reflectance0) *
|
|
666
|
+
pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// This calculates the specular geometric attenuation (aka G()),
|
|
670
|
+
// where rougher material will reflect less light back to the viewer.
|
|
671
|
+
// This implementation is based on [1] Equation 4, and we adopt their modifications to
|
|
672
|
+
// alphaRoughness as input as originally proposed in [2].
|
|
673
|
+
fn geometricOcclusion(pbrInfo: PBRInfo) -> f32 {
|
|
674
|
+
let NdotL: f32 = pbrInfo.NdotL;
|
|
675
|
+
let NdotV: f32 = pbrInfo.NdotV;
|
|
676
|
+
let r: f32 = pbrInfo.alphaRoughness;
|
|
677
|
+
|
|
678
|
+
let attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
|
|
679
|
+
let attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
|
|
680
|
+
return attenuationL * attenuationV;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// The following equation(s) model the distribution of microfacet normals across
|
|
684
|
+
// the area being drawn (aka D())
|
|
685
|
+
// Implementation from "Average Irregularity Representation of a Roughened Surface
|
|
686
|
+
// for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz
|
|
687
|
+
// Follows the distribution function recommended in the SIGGRAPH 2013 course notes
|
|
688
|
+
// from EPIC Games [1], Equation 3.
|
|
689
|
+
fn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {
|
|
690
|
+
let roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;
|
|
691
|
+
let f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;
|
|
692
|
+
return roughnessSq / (PI * f * f);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
fn PBRInfo_setAmbientLight(pbrInfo: ptr<function, PBRInfo>) {
|
|
696
|
+
(*pbrInfo).NdotL = 1.0;
|
|
697
|
+
(*pbrInfo).NdotH = 0.0;
|
|
698
|
+
(*pbrInfo).LdotH = 0.0;
|
|
699
|
+
(*pbrInfo).VdotH = 1.0;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
fn PBRInfo_setDirectionalLight(pbrInfo: ptr<function, PBRInfo>, lightDirection: vec3<f32>) {
|
|
703
|
+
let n = (*pbrInfo).n;
|
|
704
|
+
let v = (*pbrInfo).v;
|
|
705
|
+
let l = normalize(lightDirection); // Vector from surface point to light
|
|
706
|
+
let h = normalize(l + v); // Half vector between both l and v
|
|
707
|
+
|
|
708
|
+
(*pbrInfo).NdotL = clamp(dot(n, l), 0.001, 1.0);
|
|
709
|
+
(*pbrInfo).NdotH = clamp(dot(n, h), 0.0, 1.0);
|
|
710
|
+
(*pbrInfo).LdotH = clamp(dot(l, h), 0.0, 1.0);
|
|
711
|
+
(*pbrInfo).VdotH = clamp(dot(v, h), 0.0, 1.0);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
fn PBRInfo_setPointLight(pbrInfo: ptr<function, PBRInfo>, pointLight: PointLight) {
|
|
715
|
+
let light_direction = normalize(pointLight.position - pbr_vPosition);
|
|
716
|
+
PBRInfo_setDirectionalLight(pbrInfo, light_direction);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
|
|
720
|
+
// Calculate the shading terms for the microfacet specular shading model
|
|
721
|
+
let F = specularReflection(pbrInfo);
|
|
722
|
+
let G = geometricOcclusion(pbrInfo);
|
|
723
|
+
let D = microfacetDistribution(pbrInfo);
|
|
724
|
+
|
|
725
|
+
// Calculation of analytical lighting contribution
|
|
726
|
+
let diffuseContrib = (1.0 - F) * diffuse(pbrInfo);
|
|
727
|
+
let specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV);
|
|
728
|
+
// Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)
|
|
729
|
+
return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
|
|
733
|
+
// The albedo may be defined from a base texture or a flat color
|
|
734
|
+
var baseColor: vec4<f32>;
|
|
735
|
+
#ifdef HAS_BASECOLORMAP
|
|
736
|
+
baseColor = SRGBtoLINEAR(textureSample(pbr_baseColorSampler, pbr_baseColorSampler, pbr_vUV)) * pbrMaterial.baseColorFactor;
|
|
737
|
+
#else
|
|
738
|
+
baseColor = pbrMaterial.baseColorFactor;
|
|
739
|
+
#endif
|
|
740
|
+
|
|
741
|
+
#ifdef ALPHA_CUTOFF
|
|
742
|
+
if (baseColor.a < pbrMaterial.alphaCutoff) {
|
|
743
|
+
discard;
|
|
744
|
+
}
|
|
745
|
+
#endif
|
|
746
|
+
|
|
747
|
+
var color = vec3<f32>(0.0, 0.0, 0.0);
|
|
748
|
+
|
|
749
|
+
if (pbrMaterial.unlit) {
|
|
750
|
+
color = baseColor.rgb;
|
|
751
|
+
} else {
|
|
752
|
+
// Metallic and Roughness material properties are packed together
|
|
753
|
+
// In glTF, these factors can be specified by fixed scalar values
|
|
754
|
+
// or from a metallic-roughness map
|
|
755
|
+
var perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;
|
|
756
|
+
var metallic = pbrMaterial.metallicRoughnessValues.x;
|
|
757
|
+
#ifdef HAS_METALROUGHNESSMAP
|
|
758
|
+
// Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
|
|
759
|
+
// This layout intentionally reserves the 'r' channel for (optional) occlusion map data
|
|
760
|
+
let mrSample = textureSample(pbr_metallicRoughnessSampler, pbr_metallicRoughnessSampler, pbr_vUV);
|
|
761
|
+
perceptualRoughness = mrSample.g * perceptualRoughness;
|
|
762
|
+
metallic = mrSample.b * metallic;
|
|
763
|
+
#endif
|
|
764
|
+
perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
|
|
765
|
+
metallic = clamp(metallic, 0.0, 1.0);
|
|
766
|
+
// Roughness is authored as perceptual roughness; as is convention,
|
|
767
|
+
// convert to material roughness by squaring the perceptual roughness [2].
|
|
768
|
+
let alphaRoughness = perceptualRoughness * perceptualRoughness;
|
|
769
|
+
|
|
770
|
+
let f0 = vec3<f32>(0.04);
|
|
771
|
+
var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);
|
|
772
|
+
diffuseColor *= 1.0 - metallic;
|
|
773
|
+
let specularColor = mix(f0, baseColor.rgb, metallic);
|
|
774
|
+
|
|
775
|
+
// Compute reflectance.
|
|
776
|
+
let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
|
|
777
|
+
|
|
778
|
+
// For typical incident reflectance range (between 4% to 100%) set the grazing
|
|
779
|
+
// reflectance to 100% for typical fresnel effect.
|
|
780
|
+
// For very low reflectance range on highly diffuse objects (below 4%),
|
|
781
|
+
// incrementally reduce grazing reflectance to 0%.
|
|
782
|
+
let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
|
|
783
|
+
let specularEnvironmentR0 = specularColor;
|
|
784
|
+
let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;
|
|
785
|
+
|
|
786
|
+
let n = getNormal(); // normal at surface point
|
|
787
|
+
let v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
|
|
788
|
+
|
|
789
|
+
let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
|
|
790
|
+
let reflection = -normalize(reflect(v, n));
|
|
791
|
+
|
|
792
|
+
var pbrInfo = PBRInfo(
|
|
793
|
+
0.0, // NdotL
|
|
794
|
+
NdotV,
|
|
795
|
+
0.0, // NdotH
|
|
796
|
+
0.0, // LdotH
|
|
797
|
+
0.0, // VdotH
|
|
798
|
+
perceptualRoughness,
|
|
799
|
+
metallic,
|
|
800
|
+
specularEnvironmentR0,
|
|
801
|
+
specularEnvironmentR90,
|
|
802
|
+
alphaRoughness,
|
|
803
|
+
diffuseColor,
|
|
804
|
+
specularColor,
|
|
805
|
+
n,
|
|
806
|
+
v
|
|
807
|
+
);
|
|
808
|
+
|
|
809
|
+
#ifdef USE_LIGHTS
|
|
810
|
+
// Apply ambient light
|
|
811
|
+
PBRInfo_setAmbientLight(&pbrInfo);
|
|
812
|
+
color += calculateFinalColor(pbrInfo, lighting.ambientColor);
|
|
813
|
+
|
|
814
|
+
// Apply directional light
|
|
815
|
+
for (var i = 0; i < lighting.directionalLightCount; i++) {
|
|
816
|
+
if (i < lighting.directionalLightCount) {
|
|
817
|
+
PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
|
|
818
|
+
color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Apply point light
|
|
823
|
+
for (var i = 0; i < lighting.pointLightCount; i++) {
|
|
824
|
+
if (i < lighting.pointLightCount) {
|
|
825
|
+
PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));
|
|
826
|
+
let attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
|
|
827
|
+
color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
#endif
|
|
831
|
+
|
|
832
|
+
// Calculate lighting contribution from image based lighting source (IBL)
|
|
833
|
+
#ifdef USE_IBL
|
|
834
|
+
if (pbrMaterial.IBLenabled) {
|
|
835
|
+
color += getIBLContribution(pbrInfo, n, reflection);
|
|
836
|
+
}
|
|
837
|
+
#endif
|
|
838
|
+
|
|
839
|
+
// Apply optional PBR terms for additional (optional) shading
|
|
840
|
+
#ifdef HAS_OCCLUSIONMAP
|
|
841
|
+
if (pbrMaterial.occlusionMapEnabled) {
|
|
842
|
+
let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSampler, pbr_vUV).r;
|
|
843
|
+
color = mix(color, color * ao, pbrMaterial.occlusionStrength);
|
|
844
|
+
}
|
|
845
|
+
#endif
|
|
846
|
+
|
|
847
|
+
#ifdef HAS_EMISSIVEMAP
|
|
848
|
+
if (pbrMaterial.emissiveMapEnabled) {
|
|
849
|
+
let emissive = SRGBtoLINEAR(textureSample(pbr_emissiveSampler, pbr_emissiveSampler, pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
|
|
850
|
+
color += emissive;
|
|
851
|
+
}
|
|
852
|
+
#endif
|
|
853
|
+
|
|
854
|
+
// This section uses mix to override final color for reference app visualization
|
|
855
|
+
// of various parameters in the lighting equation.
|
|
856
|
+
#ifdef PBR_DEBUG
|
|
857
|
+
// TODO: Figure out how to debug multiple lights
|
|
858
|
+
|
|
859
|
+
// color = mix(color, F, pbr_scaleFGDSpec.x);
|
|
860
|
+
// color = mix(color, vec3(G), pbr_scaleFGDSpec.y);
|
|
861
|
+
// color = mix(color, vec3(D), pbr_scaleFGDSpec.z);
|
|
862
|
+
// color = mix(color, specContrib, pbr_scaleFGDSpec.w);
|
|
863
|
+
|
|
864
|
+
// color = mix(color, diffuseContrib, pbr_scaleDiffBaseMR.x);
|
|
865
|
+
color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
|
|
866
|
+
color = mix(color, vec3<f32>(metallic), pbrMaterial.scaleDiffBaseMR.z);
|
|
867
|
+
color = mix(color, vec3<f32>(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
|
|
868
|
+
#endif
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), baseColor.a);
|
|
872
|
+
}
|
|
873
|
+
`;
|
|
874
|
+
|
|
875
|
+
// luma.gl
|
|
876
|
+
// SPDX-License-Identifier: MIT
|
|
877
|
+
// Copyright (c) vis.gl contributors
|
|
878
|
+
const uniformBlock$1 = /* glsl */ `\
|
|
879
|
+
uniform pbrProjectionUniforms {
|
|
880
|
+
mat4 modelViewProjectionMatrix;
|
|
881
|
+
mat4 modelMatrix;
|
|
882
|
+
mat4 normalMatrix;
|
|
883
|
+
vec3 camera;
|
|
884
|
+
} pbrProjection;
|
|
885
|
+
`;
|
|
886
|
+
const pbrProjection = {
|
|
887
|
+
name: 'pbrProjection',
|
|
888
|
+
vs: uniformBlock$1,
|
|
889
|
+
fs: uniformBlock$1,
|
|
890
|
+
// TODO why is this needed?
|
|
891
|
+
getUniforms: props => props,
|
|
892
|
+
uniformTypes: {
|
|
893
|
+
modelViewProjectionMatrix: 'mat4x4<f32>',
|
|
894
|
+
modelMatrix: 'mat4x4<f32>',
|
|
895
|
+
normalMatrix: 'mat4x4<f32>',
|
|
896
|
+
camera: 'vec3<i32>'
|
|
897
|
+
}
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
// luma.gl
|
|
901
|
+
// SPDX-License-Identifier: MIT
|
|
902
|
+
// Copyright (c) vis.gl contributors
|
|
903
|
+
/**
|
|
904
|
+
* An implementation of PBR (Physically-Based Rendering).
|
|
905
|
+
* Physically Based Shading of a microfacet surface defined by a glTF material.
|
|
906
|
+
*/
|
|
907
|
+
const pbrMaterial = {
|
|
908
|
+
props: {},
|
|
909
|
+
uniforms: {},
|
|
910
|
+
name: 'pbrMaterial',
|
|
911
|
+
dependencies: [lighting, pbrProjection],
|
|
912
|
+
source,
|
|
913
|
+
vs: vs$2,
|
|
914
|
+
fs: fs$2,
|
|
915
|
+
defines: {
|
|
916
|
+
LIGHTING_FRAGMENT: true,
|
|
917
|
+
HAS_NORMALMAP: false,
|
|
918
|
+
HAS_EMISSIVEMAP: false,
|
|
919
|
+
HAS_OCCLUSIONMAP: false,
|
|
920
|
+
HAS_BASECOLORMAP: false,
|
|
921
|
+
HAS_METALROUGHNESSMAP: false,
|
|
922
|
+
ALPHA_CUTOFF: false,
|
|
923
|
+
USE_IBL: false,
|
|
924
|
+
PBR_DEBUG: false
|
|
925
|
+
},
|
|
926
|
+
getUniforms: props => props,
|
|
927
|
+
uniformTypes: {
|
|
928
|
+
// Material is unlit
|
|
929
|
+
unlit: 'i32',
|
|
930
|
+
// Base color map
|
|
931
|
+
baseColorMapEnabled: 'i32',
|
|
932
|
+
baseColorFactor: 'vec4<f32>',
|
|
933
|
+
normalMapEnabled: 'i32',
|
|
934
|
+
normalScale: 'f32', // #ifdef HAS_NORMALMAP
|
|
935
|
+
emissiveMapEnabled: 'i32',
|
|
936
|
+
emissiveFactor: 'vec3<f32>', // #ifdef HAS_EMISSIVEMAP
|
|
937
|
+
metallicRoughnessValues: 'vec2<f32>',
|
|
938
|
+
metallicRoughnessMapEnabled: 'i32',
|
|
939
|
+
occlusionMapEnabled: 'i32',
|
|
940
|
+
occlusionStrength: 'f32', // #ifdef HAS_OCCLUSIONMAP
|
|
941
|
+
alphaCutoffEnabled: 'i32',
|
|
942
|
+
alphaCutoff: 'f32', // #ifdef ALPHA_CUTOFF
|
|
943
|
+
// IBL
|
|
944
|
+
IBLenabled: 'i32',
|
|
945
|
+
scaleIBLAmbient: 'vec2<f32>', // #ifdef USE_IBL
|
|
946
|
+
// debugging flags used for shader output of intermediate PBR variables
|
|
947
|
+
// #ifdef PBR_DEBUG
|
|
948
|
+
scaleDiffBaseMR: 'vec4<f32>',
|
|
949
|
+
scaleFGDSpec: 'vec4<f32>'
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
|
|
953
|
+
// luma.gl
|
|
954
|
+
// SPDX-License-Identifier: MIT
|
|
955
|
+
// Copyright (c) vis.gl contributors
|
|
956
|
+
class ScenegraphNode {
|
|
957
|
+
id;
|
|
958
|
+
matrix = new Matrix4();
|
|
959
|
+
display = true;
|
|
960
|
+
position = new Vector3();
|
|
961
|
+
rotation = new Vector3();
|
|
962
|
+
scale = new Vector3(1, 1, 1);
|
|
963
|
+
userData = {};
|
|
964
|
+
props = {};
|
|
965
|
+
constructor(props = {}) {
|
|
966
|
+
const { id } = props;
|
|
967
|
+
this.id = id || uid(this.constructor.name);
|
|
968
|
+
this._setScenegraphNodeProps(props);
|
|
969
|
+
}
|
|
970
|
+
getBounds() {
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
destroy() { }
|
|
974
|
+
/** @deprecated use .destroy() */
|
|
975
|
+
delete() {
|
|
976
|
+
this.destroy();
|
|
977
|
+
}
|
|
978
|
+
setProps(props) {
|
|
979
|
+
this._setScenegraphNodeProps(props);
|
|
980
|
+
return this;
|
|
981
|
+
}
|
|
982
|
+
toString() {
|
|
983
|
+
return `{type: ScenegraphNode, id: ${this.id})}`;
|
|
984
|
+
}
|
|
985
|
+
setPosition(position) {
|
|
986
|
+
// assert(position.length === 3, 'setPosition requires vector argument');
|
|
987
|
+
this.position = position;
|
|
988
|
+
return this;
|
|
989
|
+
}
|
|
990
|
+
setRotation(rotation) {
|
|
991
|
+
// assert(rotation.length === 3, 'setRotation requires vector argument');
|
|
992
|
+
this.rotation = rotation;
|
|
993
|
+
return this;
|
|
994
|
+
}
|
|
995
|
+
setScale(scale) {
|
|
996
|
+
// assert(scale.length === 3, 'setScale requires vector argument');
|
|
997
|
+
this.scale = scale;
|
|
998
|
+
return this;
|
|
999
|
+
}
|
|
1000
|
+
setMatrix(matrix, copyMatrix = true) {
|
|
1001
|
+
if (copyMatrix) {
|
|
1002
|
+
this.matrix.copy(matrix);
|
|
1003
|
+
}
|
|
1004
|
+
else {
|
|
1005
|
+
this.matrix = matrix;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
setMatrixComponents(components) {
|
|
1009
|
+
const { position, rotation, scale, update = true } = components;
|
|
1010
|
+
if (position) {
|
|
1011
|
+
this.setPosition(position);
|
|
1012
|
+
}
|
|
1013
|
+
if (rotation) {
|
|
1014
|
+
this.setRotation(rotation);
|
|
1015
|
+
}
|
|
1016
|
+
if (scale) {
|
|
1017
|
+
this.setScale(scale);
|
|
1018
|
+
}
|
|
1019
|
+
if (update) {
|
|
1020
|
+
this.updateMatrix();
|
|
1021
|
+
}
|
|
1022
|
+
return this;
|
|
1023
|
+
}
|
|
1024
|
+
updateMatrix() {
|
|
1025
|
+
const pos = this.position;
|
|
1026
|
+
const rot = this.rotation;
|
|
1027
|
+
const scale = this.scale;
|
|
1028
|
+
this.matrix.identity();
|
|
1029
|
+
this.matrix.translate(pos);
|
|
1030
|
+
this.matrix.rotateXYZ(rot);
|
|
1031
|
+
this.matrix.scale(scale);
|
|
1032
|
+
return this;
|
|
1033
|
+
}
|
|
1034
|
+
update(options = {}) {
|
|
1035
|
+
const { position, rotation, scale } = options;
|
|
1036
|
+
if (position) {
|
|
1037
|
+
this.setPosition(position);
|
|
1038
|
+
}
|
|
1039
|
+
if (rotation) {
|
|
1040
|
+
this.setRotation(rotation);
|
|
1041
|
+
}
|
|
1042
|
+
if (scale) {
|
|
1043
|
+
this.setScale(scale);
|
|
1044
|
+
}
|
|
1045
|
+
this.updateMatrix();
|
|
1046
|
+
return this;
|
|
1047
|
+
}
|
|
1048
|
+
getCoordinateUniforms(viewMatrix, modelMatrix) {
|
|
1049
|
+
// TODO - solve multiple class problem
|
|
1050
|
+
// assert(viewMatrix instanceof Matrix4);
|
|
1051
|
+
// assert(viewMatrix);
|
|
1052
|
+
modelMatrix = modelMatrix || this.matrix;
|
|
1053
|
+
const worldMatrix = new Matrix4(viewMatrix).multiplyRight(modelMatrix);
|
|
1054
|
+
const worldInverse = worldMatrix.invert();
|
|
1055
|
+
const worldInverseTranspose = worldInverse.transpose();
|
|
1056
|
+
return {
|
|
1057
|
+
viewMatrix,
|
|
1058
|
+
modelMatrix,
|
|
1059
|
+
objectMatrix: modelMatrix,
|
|
1060
|
+
worldMatrix,
|
|
1061
|
+
worldInverseMatrix: worldInverse,
|
|
1062
|
+
worldInverseTransposeMatrix: worldInverseTranspose
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
// TODO - copied code, not yet vetted
|
|
1066
|
+
/*
|
|
1067
|
+
transform() {
|
|
1068
|
+
if (!this.parent) {
|
|
1069
|
+
this.endPosition.set(this.position);
|
|
1070
|
+
this.endRotation.set(this.rotation);
|
|
1071
|
+
this.endScale.set(this.scale);
|
|
1072
|
+
} else {
|
|
1073
|
+
const parent = this.parent;
|
|
1074
|
+
this.endPosition.set(this.position.add(parent.endPosition));
|
|
1075
|
+
this.endRotation.set(this.rotation.add(parent.endRotation));
|
|
1076
|
+
this.endScale.set(this.scale.add(parent.endScale));
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
const ch = this.children;
|
|
1080
|
+
for (let i = 0; i < ch.length; ++i) {
|
|
1081
|
+
ch[i].transform();
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
return this;
|
|
1085
|
+
}
|
|
1086
|
+
*/
|
|
1087
|
+
_setScenegraphNodeProps(props) {
|
|
1088
|
+
// if ('display' in props) {
|
|
1089
|
+
// this.display = props.display;
|
|
1090
|
+
// }
|
|
1091
|
+
if ('position' in props) {
|
|
1092
|
+
this.setPosition(props.position);
|
|
1093
|
+
}
|
|
1094
|
+
if ('rotation' in props) {
|
|
1095
|
+
this.setRotation(props.rotation);
|
|
1096
|
+
}
|
|
1097
|
+
if ('scale' in props) {
|
|
1098
|
+
this.setScale(props.scale);
|
|
1099
|
+
}
|
|
1100
|
+
// Matrix overwrites other props
|
|
1101
|
+
if ('matrix' in props) {
|
|
1102
|
+
this.setMatrix(props.matrix);
|
|
1103
|
+
}
|
|
1104
|
+
Object.assign(this.props, props);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
// luma.gl
|
|
1109
|
+
// SPDX-License-Identifier: MIT
|
|
1110
|
+
// Copyright (c) vis.gl contributors
|
|
1111
|
+
class GroupNode extends ScenegraphNode {
|
|
1112
|
+
children;
|
|
1113
|
+
constructor(props = {}) {
|
|
1114
|
+
props = Array.isArray(props) ? { children: props } : props;
|
|
1115
|
+
const { children = [] } = props;
|
|
1116
|
+
log.assert(children.every(child => child instanceof ScenegraphNode), 'every child must an instance of ScenegraphNode');
|
|
1117
|
+
super(props);
|
|
1118
|
+
this.children = children;
|
|
1119
|
+
}
|
|
1120
|
+
getBounds() {
|
|
1121
|
+
const result = [
|
|
1122
|
+
[Infinity, Infinity, Infinity],
|
|
1123
|
+
[-Infinity, -Infinity, -Infinity]
|
|
1124
|
+
];
|
|
1125
|
+
this.traverse((node, { worldMatrix }) => {
|
|
1126
|
+
const bounds = node.getBounds();
|
|
1127
|
+
if (!bounds) {
|
|
1128
|
+
return;
|
|
1129
|
+
}
|
|
1130
|
+
const [min, max] = bounds;
|
|
1131
|
+
const center = new Vector3(min).add(max).divide([2, 2, 2]);
|
|
1132
|
+
worldMatrix.transformAsPoint(center, center);
|
|
1133
|
+
const halfSize = new Vector3(max).subtract(min).divide([2, 2, 2]);
|
|
1134
|
+
worldMatrix.transformAsVector(halfSize, halfSize);
|
|
1135
|
+
for (let v = 0; v < 8; v++) {
|
|
1136
|
+
// Test all 8 corners of the box
|
|
1137
|
+
const position = new Vector3(v & 0b001 ? -1 : 1, v & 0b010 ? -1 : 1, v & 0b100 ? -1 : 1)
|
|
1138
|
+
.multiply(halfSize)
|
|
1139
|
+
.add(center);
|
|
1140
|
+
for (let i = 0; i < 3; i++) {
|
|
1141
|
+
result[0][i] = Math.min(result[0][i], position[i]);
|
|
1142
|
+
result[1][i] = Math.max(result[1][i], position[i]);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
});
|
|
1146
|
+
if (!Number.isFinite(result[0][0])) {
|
|
1147
|
+
return null;
|
|
1148
|
+
}
|
|
1149
|
+
return result;
|
|
1150
|
+
}
|
|
1151
|
+
destroy() {
|
|
1152
|
+
this.children.forEach(child => child.destroy());
|
|
1153
|
+
this.removeAll();
|
|
1154
|
+
super.destroy();
|
|
1155
|
+
}
|
|
1156
|
+
// Unpacks arrays and nested arrays of children
|
|
1157
|
+
add(...children) {
|
|
1158
|
+
for (const child of children) {
|
|
1159
|
+
if (Array.isArray(child)) {
|
|
1160
|
+
this.add(...child);
|
|
1161
|
+
}
|
|
1162
|
+
else {
|
|
1163
|
+
this.children.push(child);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
return this;
|
|
1167
|
+
}
|
|
1168
|
+
remove(child) {
|
|
1169
|
+
const children = this.children;
|
|
1170
|
+
const indexOf = children.indexOf(child);
|
|
1171
|
+
if (indexOf > -1) {
|
|
1172
|
+
children.splice(indexOf, 1);
|
|
1173
|
+
}
|
|
1174
|
+
return this;
|
|
1175
|
+
}
|
|
1176
|
+
removeAll() {
|
|
1177
|
+
this.children = [];
|
|
1178
|
+
return this;
|
|
1179
|
+
}
|
|
1180
|
+
traverse(visitor, { worldMatrix = new Matrix4() } = {}) {
|
|
1181
|
+
const modelMatrix = new Matrix4(worldMatrix).multiplyRight(this.matrix);
|
|
1182
|
+
for (const child of this.children) {
|
|
1183
|
+
if (child instanceof GroupNode) {
|
|
1184
|
+
child.traverse(visitor, { worldMatrix: modelMatrix });
|
|
1185
|
+
}
|
|
1186
|
+
else {
|
|
1187
|
+
visitor(child, { worldMatrix: modelMatrix });
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// luma.gl
|
|
1194
|
+
// SPDX-License-Identifier: MIT
|
|
1195
|
+
// Copyright (c) vis.gl contributors
|
|
1196
|
+
class ModelNode extends ScenegraphNode {
|
|
1197
|
+
model;
|
|
1198
|
+
bounds = null;
|
|
1199
|
+
managedResources;
|
|
1200
|
+
// TODO - is this used? override callbacks to make sure we call them with this
|
|
1201
|
+
// onBeforeRender = null;
|
|
1202
|
+
// onAfterRender = null;
|
|
1203
|
+
// AfterRender = null;
|
|
1204
|
+
constructor(props) {
|
|
1205
|
+
super(props);
|
|
1206
|
+
// Create new Model or used supplied Model
|
|
1207
|
+
this.model = props.model;
|
|
1208
|
+
this.managedResources = props.managedResources || [];
|
|
1209
|
+
this.bounds = props.bounds || null;
|
|
1210
|
+
this.setProps(props);
|
|
1211
|
+
}
|
|
1212
|
+
destroy() {
|
|
1213
|
+
if (this.model) {
|
|
1214
|
+
this.model.destroy();
|
|
1215
|
+
// @ts-expect-error
|
|
1216
|
+
this.model = null;
|
|
1217
|
+
}
|
|
1218
|
+
this.managedResources.forEach(resource => resource.destroy());
|
|
1219
|
+
this.managedResources = [];
|
|
1220
|
+
}
|
|
1221
|
+
getBounds() {
|
|
1222
|
+
return this.bounds;
|
|
1223
|
+
}
|
|
1224
|
+
// Expose model methods
|
|
1225
|
+
draw(renderPass) {
|
|
1226
|
+
// Return value indicates if something was actually drawn
|
|
1227
|
+
return this.model.draw(renderPass);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
// luma.gl
|
|
1232
|
+
// SPDX-License-Identifier: MIT
|
|
1233
|
+
// Copyright (c) vis.gl contributors
|
|
1234
|
+
function convertSampler(gltfSampler) {
|
|
1235
|
+
return {
|
|
1236
|
+
addressModeU: convertSamplerWrapMode(gltfSampler.wrapS),
|
|
1237
|
+
addressModeV: convertSamplerWrapMode(gltfSampler.wrapT),
|
|
1238
|
+
magFilter: convertSamplerMagFilter(gltfSampler.magFilter),
|
|
1239
|
+
...convertSamplerMinFilter(gltfSampler.minFilter)
|
|
1240
|
+
};
|
|
1241
|
+
}
|
|
1242
|
+
function convertSamplerWrapMode(mode) {
|
|
1243
|
+
switch (mode) {
|
|
1244
|
+
case 33071:
|
|
1245
|
+
return 'clamp-to-edge';
|
|
1246
|
+
case 10497:
|
|
1247
|
+
return 'repeat';
|
|
1248
|
+
case 33648:
|
|
1249
|
+
return 'mirror-repeat';
|
|
1250
|
+
default:
|
|
1251
|
+
return undefined;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
function convertSamplerMagFilter(mode) {
|
|
1255
|
+
switch (mode) {
|
|
1256
|
+
case 9728:
|
|
1257
|
+
return 'nearest';
|
|
1258
|
+
case 9729:
|
|
1259
|
+
return 'linear';
|
|
1260
|
+
default:
|
|
1261
|
+
return undefined;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
function convertSamplerMinFilter(mode) {
|
|
1265
|
+
switch (mode) {
|
|
1266
|
+
case 9728:
|
|
1267
|
+
return { minFilter: 'nearest' };
|
|
1268
|
+
case 9729:
|
|
1269
|
+
return { minFilter: 'linear' };
|
|
1270
|
+
case 9984:
|
|
1271
|
+
return { minFilter: 'nearest', mipmapFilter: 'nearest' };
|
|
1272
|
+
case 9985:
|
|
1273
|
+
return { minFilter: 'linear', mipmapFilter: 'nearest' };
|
|
1274
|
+
case 9986:
|
|
1275
|
+
return { minFilter: 'nearest', mipmapFilter: 'linear' };
|
|
1276
|
+
case 9987:
|
|
1277
|
+
return { minFilter: 'linear', mipmapFilter: 'linear' };
|
|
1278
|
+
default:
|
|
1279
|
+
return {};
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
// luma.gl
|
|
1284
|
+
// SPDX-License-Identifier: MIT
|
|
1285
|
+
// Copyright (c) vis.gl contributors
|
|
1286
|
+
/**
|
|
1287
|
+
* Parses a GLTF material definition into uniforms and parameters for the PBR shader module
|
|
1288
|
+
*/
|
|
1289
|
+
function parsePBRMaterial(device, material, attributes, options) {
|
|
1290
|
+
const parsedMaterial = {
|
|
1291
|
+
defines: {
|
|
1292
|
+
// TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)
|
|
1293
|
+
MANUAL_SRGB: true,
|
|
1294
|
+
SRGB_FAST_APPROXIMATION: true
|
|
1295
|
+
},
|
|
1296
|
+
bindings: {},
|
|
1297
|
+
uniforms: {
|
|
1298
|
+
// TODO: find better values?
|
|
1299
|
+
camera: [0, 0, 0], // Model should override
|
|
1300
|
+
metallicRoughnessValues: [1, 1] // Default is 1 and 1
|
|
1301
|
+
},
|
|
1302
|
+
parameters: {},
|
|
1303
|
+
glParameters: {},
|
|
1304
|
+
generatedTextures: []
|
|
1305
|
+
};
|
|
1306
|
+
// TODO - always available
|
|
1307
|
+
parsedMaterial.defines['USE_TEX_LOD'] = true;
|
|
1308
|
+
const { imageBasedLightingEnvironment } = options;
|
|
1309
|
+
if (imageBasedLightingEnvironment) {
|
|
1310
|
+
parsedMaterial.bindings.pbr_diffuseEnvSampler =
|
|
1311
|
+
imageBasedLightingEnvironment.diffuseEnvSampler.texture;
|
|
1312
|
+
parsedMaterial.bindings.pbr_specularEnvSampler =
|
|
1313
|
+
imageBasedLightingEnvironment.specularEnvSampler.texture;
|
|
1314
|
+
parsedMaterial.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
|
|
1315
|
+
parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];
|
|
1316
|
+
}
|
|
1317
|
+
if (options?.pbrDebug) {
|
|
1318
|
+
parsedMaterial.defines['PBR_DEBUG'] = true;
|
|
1319
|
+
// Override final color for reference app visualization of various parameters in the lighting equation.
|
|
1320
|
+
parsedMaterial.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];
|
|
1321
|
+
parsedMaterial.uniforms.scaleFGDSpec = [0, 0, 0, 0];
|
|
1322
|
+
}
|
|
1323
|
+
if (attributes['NORMAL'])
|
|
1324
|
+
parsedMaterial.defines['HAS_NORMALS'] = true;
|
|
1325
|
+
if (attributes['TANGENT'] && options?.useTangents)
|
|
1326
|
+
parsedMaterial.defines['HAS_TANGENTS'] = true;
|
|
1327
|
+
if (attributes['TEXCOORD_0'])
|
|
1328
|
+
parsedMaterial.defines['HAS_UV'] = true;
|
|
1329
|
+
if (options?.imageBasedLightingEnvironment)
|
|
1330
|
+
parsedMaterial.defines['USE_IBL'] = true;
|
|
1331
|
+
if (options?.lights)
|
|
1332
|
+
parsedMaterial.defines['USE_LIGHTS'] = true;
|
|
1333
|
+
if (material) {
|
|
1334
|
+
parseMaterial(device, material, parsedMaterial);
|
|
1335
|
+
}
|
|
1336
|
+
return parsedMaterial;
|
|
1337
|
+
}
|
|
1338
|
+
/** Parse GLTF material record */
|
|
1339
|
+
function parseMaterial(device, material, parsedMaterial) {
|
|
1340
|
+
parsedMaterial.uniforms.unlit = Boolean(material.unlit);
|
|
1341
|
+
if (material.pbrMetallicRoughness) {
|
|
1342
|
+
parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);
|
|
1343
|
+
}
|
|
1344
|
+
if (material.normalTexture) {
|
|
1345
|
+
addTexture(device, material.normalTexture, 'pbr_normalSampler', 'HAS_NORMALMAP', parsedMaterial);
|
|
1346
|
+
const { scale = 1 } = material.normalTexture;
|
|
1347
|
+
parsedMaterial.uniforms.normalScale = scale;
|
|
1348
|
+
}
|
|
1349
|
+
if (material.occlusionTexture) {
|
|
1350
|
+
addTexture(device, material.occlusionTexture, 'pbr_occlusionSampler', 'HAS_OCCLUSIONMAP', parsedMaterial);
|
|
1351
|
+
const { strength = 1 } = material.occlusionTexture;
|
|
1352
|
+
parsedMaterial.uniforms.occlusionStrength = strength;
|
|
1353
|
+
}
|
|
1354
|
+
if (material.emissiveTexture) {
|
|
1355
|
+
addTexture(device, material.emissiveTexture, 'pbr_emissiveSampler', 'HAS_EMISSIVEMAP', parsedMaterial);
|
|
1356
|
+
parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
|
|
1357
|
+
}
|
|
1358
|
+
switch (material.alphaMode || 'MASK') {
|
|
1359
|
+
case 'MASK':
|
|
1360
|
+
const { alphaCutoff = 0.5 } = material;
|
|
1361
|
+
parsedMaterial.defines['ALPHA_CUTOFF'] = true;
|
|
1362
|
+
parsedMaterial.uniforms.alphaCutoff = alphaCutoff;
|
|
1363
|
+
break;
|
|
1364
|
+
case 'BLEND':
|
|
1365
|
+
log.warn('glTF BLEND alphaMode might not work well because it requires mesh sorting')();
|
|
1366
|
+
// WebGPU style parameters
|
|
1367
|
+
parsedMaterial.parameters.blend = true;
|
|
1368
|
+
parsedMaterial.parameters.blendColorOperation = 'add';
|
|
1369
|
+
parsedMaterial.parameters.blendColorSrcFactor = 'src-alpha';
|
|
1370
|
+
parsedMaterial.parameters.blendColorDstFactor = 'one-minus-src-alpha';
|
|
1371
|
+
parsedMaterial.parameters.blendAlphaOperation = 'add';
|
|
1372
|
+
parsedMaterial.parameters.blendAlphaSrcFactor = 'one';
|
|
1373
|
+
parsedMaterial.parameters.blendAlphaDstFactor = 'one-minus-src-alpha';
|
|
1374
|
+
// GL parameters
|
|
1375
|
+
// TODO - remove in favor of parameters
|
|
1376
|
+
parsedMaterial.glParameters['blend'] = true;
|
|
1377
|
+
parsedMaterial.glParameters['blendEquation'] = 32774;
|
|
1378
|
+
parsedMaterial.glParameters['blendFunc'] = [
|
|
1379
|
+
770,
|
|
1380
|
+
771,
|
|
1381
|
+
1,
|
|
1382
|
+
771
|
|
1383
|
+
];
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
/** Parse GLTF material sub record */
|
|
1388
|
+
function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial) {
|
|
1389
|
+
if (pbrMetallicRoughness.baseColorTexture) {
|
|
1390
|
+
addTexture(device, pbrMetallicRoughness.baseColorTexture, 'pbr_baseColorSampler', 'HAS_BASECOLORMAP', parsedMaterial);
|
|
1391
|
+
}
|
|
1392
|
+
parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
|
|
1393
|
+
if (pbrMetallicRoughness.metallicRoughnessTexture) {
|
|
1394
|
+
addTexture(device, pbrMetallicRoughness.metallicRoughnessTexture, 'pbr_metallicRoughnessSampler', 'HAS_METALROUGHNESSMAP', parsedMaterial);
|
|
1395
|
+
}
|
|
1396
|
+
const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness;
|
|
1397
|
+
parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
|
|
1398
|
+
}
|
|
1399
|
+
/** Create a texture from a glTF texture/sampler/image combo and add it to bindings */
|
|
1400
|
+
function addTexture(device, gltfTexture, uniformName, define, parsedMaterial) {
|
|
1401
|
+
const image = gltfTexture.texture.source.image;
|
|
1402
|
+
let textureOptions;
|
|
1403
|
+
if (image.compressed) {
|
|
1404
|
+
textureOptions = image;
|
|
1405
|
+
}
|
|
1406
|
+
else {
|
|
1407
|
+
// Texture2D accepts a promise that returns an image as data (Async Textures)
|
|
1408
|
+
textureOptions = { data: image };
|
|
1409
|
+
}
|
|
1410
|
+
const gltfSampler = {
|
|
1411
|
+
wrapS: 10497, // default REPEAT S (U) wrapping mode.
|
|
1412
|
+
wrapT: 10497, // default REPEAT T (V) wrapping mode.
|
|
1413
|
+
...gltfTexture?.texture?.sampler
|
|
1414
|
+
};
|
|
1415
|
+
const texture = device.createTexture({
|
|
1416
|
+
id: gltfTexture.uniformName || gltfTexture.id,
|
|
1417
|
+
sampler: convertSampler(gltfSampler),
|
|
1418
|
+
...textureOptions
|
|
1419
|
+
});
|
|
1420
|
+
parsedMaterial.bindings[uniformName] = texture;
|
|
1421
|
+
if (define)
|
|
1422
|
+
parsedMaterial.defines[define] = true;
|
|
1423
|
+
parsedMaterial.generatedTextures.push(texture);
|
|
1424
|
+
}
|
|
1425
|
+
/*
|
|
1426
|
+
/**
|
|
1427
|
+
* Parses a GLTF material definition into uniforms and parameters for the PBR shader module
|
|
1428
|
+
*
|
|
1429
|
+
export class PBRMaterialParser {
|
|
1430
|
+
readonly device: Device;
|
|
1431
|
+
|
|
1432
|
+
readonly defines: Record<string, boolean>;
|
|
1433
|
+
readonly bindings: Record<string, Binding>;
|
|
1434
|
+
readonly uniforms: Record<string, any>;
|
|
1435
|
+
readonly parameters: Record<string, any>;
|
|
1436
|
+
|
|
1437
|
+
/** Hold on to generated textures, we destroy them in the destroy method *
|
|
1438
|
+
readonly generatedTextures: Texture[];
|
|
1439
|
+
|
|
1440
|
+
constructor(device: Device, props: PBRMaterialParserProps) {
|
|
1441
|
+
const {attributes, material, pbrDebug, imageBasedLightingEnvironment, lights, useTangents} =
|
|
1442
|
+
props;
|
|
1443
|
+
this.device = device;
|
|
1444
|
+
|
|
1445
|
+
this.defines = {
|
|
1446
|
+
// TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)
|
|
1447
|
+
MANUAL_SRGB: true,
|
|
1448
|
+
SRGB_FAST_APPROXIMATION: true
|
|
1449
|
+
};
|
|
1450
|
+
|
|
1451
|
+
if (this.device.features.has('glsl-texture-lod')) {
|
|
1452
|
+
this.defines.USE_TEX_LOD = true;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
this.uniforms = {
|
|
1456
|
+
// TODO: find better values?
|
|
1457
|
+
camera: [0, 0, 0], // Model should override
|
|
1458
|
+
|
|
1459
|
+
metallicRoughnessValues: [1, 1] // Default is 1 and 1
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1462
|
+
this.bindings = {};
|
|
1463
|
+
|
|
1464
|
+
this.parameters = {};
|
|
1465
|
+
this.generatedTextures = [];
|
|
1466
|
+
|
|
1467
|
+
if (imageBasedLightingEnvironment) {
|
|
1468
|
+
this.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.getDiffuseEnvSampler();
|
|
1469
|
+
this.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.getSpecularEnvSampler();
|
|
1470
|
+
this.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.getBrdfTexture();
|
|
1471
|
+
this.uniforms.scaleIBLAmbient = [1, 1];
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
if (pbrDebug) {
|
|
1475
|
+
// Override final color for reference app visualization
|
|
1476
|
+
// of various parameters in the lighting equation.
|
|
1477
|
+
this.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];
|
|
1478
|
+
this.uniforms.scaleFGDSpec = [0, 0, 0, 0];
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
this.defineIfPresent(attributes.NORMAL, 'HAS_NORMALS');
|
|
1482
|
+
this.defineIfPresent(attributes.TANGENT && useTangents, 'HAS_TANGENTS');
|
|
1483
|
+
this.defineIfPresent(attributes.TEXCOORD_0, 'HAS_UV');
|
|
1484
|
+
|
|
1485
|
+
this.defineIfPresent(imageBasedLightingEnvironment, 'USE_IBL');
|
|
1486
|
+
this.defineIfPresent(lights, 'USE_LIGHTS');
|
|
1487
|
+
this.defineIfPresent(pbrDebug, 'PBR_DEBUG');
|
|
1488
|
+
|
|
1489
|
+
if (material) {
|
|
1490
|
+
this.parseMaterial(material);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
/**
|
|
1495
|
+
* Destroy all generated resources to release memory.
|
|
1496
|
+
*
|
|
1497
|
+
destroy(): void {
|
|
1498
|
+
this.generatedTextures.forEach(texture => texture.destroy());
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
/** Add a define if the the value is non-nullish *
|
|
1502
|
+
defineIfPresent(value: unknown, name: string): void {
|
|
1503
|
+
if (value) {
|
|
1504
|
+
this.defines[name] = 1;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
/** Parse GLTF material record *
|
|
1509
|
+
parseMaterial(material) {
|
|
1510
|
+
this.uniforms.unlit = Boolean(material.unlit);
|
|
1511
|
+
|
|
1512
|
+
if (material.pbrMetallicRoughness) {
|
|
1513
|
+
this.parsePbrMetallicRoughness(material.pbrMetallicRoughness);
|
|
1514
|
+
}
|
|
1515
|
+
if (material.normalTexture) {
|
|
1516
|
+
this.addTexture(material.normalTexture, 'pbr_normalSampler', 'HAS_NORMALMAP');
|
|
1517
|
+
|
|
1518
|
+
const {scale = 1} = material.normalTexture;
|
|
1519
|
+
this.uniforms.normalScale = scale;
|
|
1520
|
+
}
|
|
1521
|
+
if (material.occlusionTexture) {
|
|
1522
|
+
this.addTexture(material.occlusionTexture, 'pbr_occlusionSampler', 'HAS_OCCLUSIONMAP');
|
|
1523
|
+
|
|
1524
|
+
const {strength = 1} = material.occlusionTexture;
|
|
1525
|
+
this.uniforms.occlusionStrength = strength;
|
|
1526
|
+
}
|
|
1527
|
+
if (material.emissiveTexture) {
|
|
1528
|
+
this.addTexture(material.emissiveTexture, 'pbr_emissiveSampler', 'HAS_EMISSIVEMAP');
|
|
1529
|
+
this.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
|
|
1530
|
+
}
|
|
1531
|
+
if (material.alphaMode === 'MASK') {
|
|
1532
|
+
const {alphaCutoff = 0.5} = material;
|
|
1533
|
+
this.defines.ALPHA_CUTOFF = true;
|
|
1534
|
+
this.uniforms.u_AlphaCutoff = alphaCutoff;
|
|
1535
|
+
} else if (material.alphaMode === 'BLEND') {
|
|
1536
|
+
log.warn('BLEND alphaMode might not work well because it requires mesh sorting')();
|
|
1537
|
+
Object.assign(this.parameters, {
|
|
1538
|
+
blend: true,
|
|
1539
|
+
blendEquation: GL.FUNC_ADD,
|
|
1540
|
+
blendFunc: [GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.ONE, GL.ONE_MINUS_SRC_ALPHA]
|
|
1541
|
+
});
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
/** Parse GLTF material sub record *
|
|
1546
|
+
parsePbrMetallicRoughness(pbrMetallicRoughness) {
|
|
1547
|
+
if (pbrMetallicRoughness.baseColorTexture) {
|
|
1548
|
+
this.addTexture(
|
|
1549
|
+
pbrMetallicRoughness.baseColorTexture,
|
|
1550
|
+
'pbr_baseColorSampler',
|
|
1551
|
+
'HAS_BASECOLORMAP'
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1554
|
+
this.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
|
|
1555
|
+
|
|
1556
|
+
if (pbrMetallicRoughness.metallicRoughnessTexture) {
|
|
1557
|
+
this.addTexture(
|
|
1558
|
+
pbrMetallicRoughness.metallicRoughnessTexture,
|
|
1559
|
+
'pbr_metallicRoughnessSampler',
|
|
1560
|
+
'HAS_METALROUGHNESSMAP'
|
|
1561
|
+
);
|
|
1562
|
+
}
|
|
1563
|
+
const {metallicFactor = 1, roughnessFactor = 1} = pbrMetallicRoughness;
|
|
1564
|
+
this.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
/** Create a texture from a glTF texture/sampler/image combo and add it to bindings *
|
|
1568
|
+
addTexture(gltfTexture, name, define = null) {
|
|
1569
|
+
const parameters = gltfTexture?.texture?.sampler?.parameters || {};
|
|
1570
|
+
|
|
1571
|
+
const image = gltfTexture.texture.source.image;
|
|
1572
|
+
let textureOptions;
|
|
1573
|
+
let specialTextureParameters = {};
|
|
1574
|
+
if (image.compressed) {
|
|
1575
|
+
textureOptions = image;
|
|
1576
|
+
specialTextureParameters = {
|
|
1577
|
+
[GL.TEXTURE_MIN_FILTER]: image.data.length > 1 ? GL.LINEAR_MIPMAP_NEAREST : GL.LINEAR
|
|
1578
|
+
};
|
|
1579
|
+
} else {
|
|
1580
|
+
// Texture2D accepts a promise that returns an image as data (Async Textures)
|
|
1581
|
+
textureOptions = {data: image};
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
const texture: Texture = this.device.createTexture({
|
|
1585
|
+
id: gltfTexture.name || gltfTexture.id,
|
|
1586
|
+
parameters: {
|
|
1587
|
+
...parameters,
|
|
1588
|
+
...specialTextureParameters
|
|
1589
|
+
},
|
|
1590
|
+
pixelStore: {
|
|
1591
|
+
[GL.UNPACK_FLIP_Y_WEBGL]: false
|
|
1592
|
+
},
|
|
1593
|
+
...textureOptions
|
|
1594
|
+
});
|
|
1595
|
+
this.bindings[name] = texture;
|
|
1596
|
+
this.defineIfPresent(define, define);
|
|
1597
|
+
this.generatedTextures.push(texture);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
*/
|
|
1601
|
+
|
|
1602
|
+
// luma.gl
|
|
1603
|
+
// SPDX-License-Identifier: MIT
|
|
1604
|
+
// Copyright (c) vis.gl contributors
|
|
1605
|
+
// NOTE: Modules other than `@luma.gl/webgl` should not import `GL` from
|
|
1606
|
+
// `@luma.gl/constants`. Locally we use `GLEnum` instead of `GL` to avoid
|
|
1607
|
+
// conflicts with the `babel-plugin-inline-webgl-constants` plugin.
|
|
1608
|
+
// eslint-disable-next-line no-shadow
|
|
1609
|
+
var GLEnum;
|
|
1610
|
+
(function (GLEnum) {
|
|
1611
|
+
GLEnum[GLEnum["POINTS"] = 0] = "POINTS";
|
|
1612
|
+
GLEnum[GLEnum["LINES"] = 1] = "LINES";
|
|
1613
|
+
GLEnum[GLEnum["LINE_LOOP"] = 2] = "LINE_LOOP";
|
|
1614
|
+
GLEnum[GLEnum["LINE_STRIP"] = 3] = "LINE_STRIP";
|
|
1615
|
+
GLEnum[GLEnum["TRIANGLES"] = 4] = "TRIANGLES";
|
|
1616
|
+
GLEnum[GLEnum["TRIANGLE_STRIP"] = 5] = "TRIANGLE_STRIP";
|
|
1617
|
+
GLEnum[GLEnum["TRIANGLE_FAN"] = 6] = "TRIANGLE_FAN";
|
|
1618
|
+
})(GLEnum || (GLEnum = {}));
|
|
1619
|
+
function convertGLDrawModeToTopology(drawMode) {
|
|
1620
|
+
// prettier-ignore
|
|
1621
|
+
switch (drawMode) {
|
|
1622
|
+
case GLEnum.POINTS: return 'point-list';
|
|
1623
|
+
case GLEnum.LINES: return 'line-list';
|
|
1624
|
+
case GLEnum.LINE_STRIP: return 'line-strip';
|
|
1625
|
+
case GLEnum.TRIANGLES: return 'triangle-list';
|
|
1626
|
+
case GLEnum.TRIANGLE_STRIP: return 'triangle-strip';
|
|
1627
|
+
default: throw new Error(String(drawMode));
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
// luma.gl
|
|
1632
|
+
// SPDX-License-Identifier: MIT
|
|
1633
|
+
// Copyright (c) vis.gl contributors
|
|
1634
|
+
const SHADER = /* WGSL */ `
|
|
1635
|
+
layout(0) positions: vec4; // in vec4 POSITION;
|
|
1636
|
+
|
|
1637
|
+
#ifdef HAS_NORMALS
|
|
1638
|
+
in vec4 normals; // in vec4 NORMAL;
|
|
1639
|
+
#endif
|
|
1640
|
+
|
|
1641
|
+
#ifdef HAS_TANGENTS
|
|
1642
|
+
in vec4 TANGENT;
|
|
1643
|
+
#endif
|
|
1644
|
+
|
|
1645
|
+
#ifdef HAS_UV
|
|
1646
|
+
// in vec2 TEXCOORD_0;
|
|
1647
|
+
in vec2 texCoords;
|
|
1648
|
+
#endif
|
|
1649
|
+
|
|
1650
|
+
@vertex
|
|
1651
|
+
void main(void) {
|
|
1652
|
+
vec4 _NORMAL = vec4(0.);
|
|
1653
|
+
vec4 _TANGENT = vec4(0.);
|
|
1654
|
+
vec2 _TEXCOORD_0 = vec2(0.);
|
|
1655
|
+
|
|
1656
|
+
#ifdef HAS_NORMALS
|
|
1657
|
+
_NORMAL = normals;
|
|
1658
|
+
#endif
|
|
1659
|
+
|
|
1660
|
+
#ifdef HAS_TANGENTS
|
|
1661
|
+
_TANGENT = TANGENT;
|
|
1662
|
+
#endif
|
|
1663
|
+
|
|
1664
|
+
#ifdef HAS_UV
|
|
1665
|
+
_TEXCOORD_0 = texCoords;
|
|
1666
|
+
#endif
|
|
1667
|
+
|
|
1668
|
+
pbr_setPositionNormalTangentUV(positions, _NORMAL, _TANGENT, _TEXCOORD_0);
|
|
1669
|
+
gl_Position = u_MVPMatrix * positions;
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
@fragment
|
|
1673
|
+
out vec4 fragmentColor;
|
|
1674
|
+
|
|
1675
|
+
void main(void) {
|
|
1676
|
+
vec3 pos = pbr_vPosition;
|
|
1677
|
+
fragmentColor = pbr_filterColor(vec4(1.0));
|
|
1678
|
+
}
|
|
1679
|
+
`;
|
|
1680
|
+
// TODO rename attributes to POSITION/NORMAL etc
|
|
1681
|
+
// See gpu-geometry.ts: getAttributeBuffersFromGeometry()
|
|
1682
|
+
const vs$1 = /* glsl */ `\
|
|
1683
|
+
#version 300 es
|
|
1684
|
+
|
|
1685
|
+
// in vec4 POSITION;
|
|
1686
|
+
in vec4 positions;
|
|
1687
|
+
|
|
1688
|
+
#ifdef HAS_NORMALS
|
|
1689
|
+
// in vec4 NORMAL;
|
|
1690
|
+
in vec4 normals;
|
|
1691
|
+
#endif
|
|
1692
|
+
|
|
1693
|
+
#ifdef HAS_TANGENTS
|
|
1694
|
+
in vec4 TANGENT;
|
|
1695
|
+
#endif
|
|
1696
|
+
|
|
1697
|
+
#ifdef HAS_UV
|
|
1698
|
+
// in vec2 TEXCOORD_0;
|
|
1699
|
+
in vec2 texCoords;
|
|
1700
|
+
#endif
|
|
1701
|
+
|
|
1702
|
+
void main(void) {
|
|
1703
|
+
vec4 _NORMAL = vec4(0.);
|
|
1704
|
+
vec4 _TANGENT = vec4(0.);
|
|
1705
|
+
vec2 _TEXCOORD_0 = vec2(0.);
|
|
1706
|
+
|
|
1707
|
+
#ifdef HAS_NORMALS
|
|
1708
|
+
_NORMAL = normals;
|
|
1709
|
+
#endif
|
|
1710
|
+
|
|
1711
|
+
#ifdef HAS_TANGENTS
|
|
1712
|
+
_TANGENT = TANGENT;
|
|
1713
|
+
#endif
|
|
1714
|
+
|
|
1715
|
+
#ifdef HAS_UV
|
|
1716
|
+
_TEXCOORD_0 = texCoords;
|
|
1717
|
+
#endif
|
|
1718
|
+
|
|
1719
|
+
pbr_setPositionNormalTangentUV(positions, _NORMAL, _TANGENT, _TEXCOORD_0);
|
|
1720
|
+
gl_Position = pbrProjection.modelViewProjectionMatrix * positions;
|
|
1721
|
+
}
|
|
1722
|
+
`;
|
|
1723
|
+
const fs$1 = /* glsl */ `\
|
|
1724
|
+
#version 300 es
|
|
1725
|
+
out vec4 fragmentColor;
|
|
1726
|
+
|
|
1727
|
+
void main(void) {
|
|
1728
|
+
vec3 pos = pbr_vPosition;
|
|
1729
|
+
fragmentColor = pbr_filterColor(vec4(1.0));
|
|
1730
|
+
}
|
|
1731
|
+
`;
|
|
1732
|
+
/** Creates a luma.gl Model from GLTF data*/
|
|
1733
|
+
function createGLTFModel(device, options) {
|
|
1734
|
+
const { id, geometry, parsedPPBRMaterial, vertexCount, modelOptions = {} } = options;
|
|
1735
|
+
log.info(4, 'createGLTFModel defines: ', parsedPPBRMaterial.defines)();
|
|
1736
|
+
// Calculate managedResources
|
|
1737
|
+
// TODO: Implement resource management logic that will
|
|
1738
|
+
// not deallocate resources/textures/buffers that are shared
|
|
1739
|
+
const managedResources = [];
|
|
1740
|
+
// managedResources.push(...parsedMaterial.generatedTextures);
|
|
1741
|
+
// managedResources.push(...Object.values(attributes).map((attribute) => attribute.buffer));
|
|
1742
|
+
const parameters = {
|
|
1743
|
+
depthWriteEnabled: true,
|
|
1744
|
+
depthCompare: 'less',
|
|
1745
|
+
depthFormat: 'depth24plus',
|
|
1746
|
+
cullMode: 'back'
|
|
1747
|
+
};
|
|
1748
|
+
const modelProps = {
|
|
1749
|
+
id,
|
|
1750
|
+
source: SHADER,
|
|
1751
|
+
vs: vs$1,
|
|
1752
|
+
fs: fs$1,
|
|
1753
|
+
geometry,
|
|
1754
|
+
topology: geometry.topology,
|
|
1755
|
+
vertexCount,
|
|
1756
|
+
modules: [pbrMaterial],
|
|
1757
|
+
...modelOptions,
|
|
1758
|
+
defines: { ...parsedPPBRMaterial.defines, ...modelOptions.defines },
|
|
1759
|
+
parameters: { ...parameters, ...parsedPPBRMaterial.parameters, ...modelOptions.parameters }
|
|
1760
|
+
};
|
|
1761
|
+
const model = new Model(device, modelProps);
|
|
1762
|
+
const { camera, ...pbrMaterialProps } = {
|
|
1763
|
+
...parsedPPBRMaterial.uniforms,
|
|
1764
|
+
...modelOptions.uniforms,
|
|
1765
|
+
...parsedPPBRMaterial.bindings,
|
|
1766
|
+
...modelOptions.bindings
|
|
1767
|
+
};
|
|
1768
|
+
model.shaderInputs.setProps({ pbrMaterial: pbrMaterialProps, pbrProjection: { camera } });
|
|
1769
|
+
return new ModelNode({ managedResources, model });
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
// luma.gl
|
|
1773
|
+
// SPDX-License-Identifier: MIT
|
|
1774
|
+
// Copyright (c) vis.gl contributors
|
|
1775
|
+
const defaultOptions = {
|
|
1776
|
+
modelOptions: {},
|
|
1777
|
+
pbrDebug: false,
|
|
1778
|
+
imageBasedLightingEnvironment: undefined,
|
|
1779
|
+
lights: true,
|
|
1780
|
+
useTangents: false
|
|
1781
|
+
};
|
|
1782
|
+
/**
|
|
1783
|
+
* GLTF instantiator for luma.gl
|
|
1784
|
+
* Walks the parsed and resolved glTF structure and builds a luma.gl scenegraph
|
|
1785
|
+
*/
|
|
1786
|
+
function parseGLTF(device, gltf, options_ = {}) {
|
|
1787
|
+
const options = { ...defaultOptions, ...options_ };
|
|
1788
|
+
const sceneNodes = gltf.scenes.map(gltfScene => createScene(device, gltfScene, gltf.nodes, options));
|
|
1789
|
+
return sceneNodes;
|
|
1790
|
+
}
|
|
1791
|
+
function createScene(device, gltfScene, gltfNodes, options) {
|
|
1792
|
+
const gltfSceneNodes = gltfScene.nodes || [];
|
|
1793
|
+
const nodes = gltfSceneNodes.map(node => createNode(device, node, gltfNodes, options));
|
|
1794
|
+
const sceneNode = new GroupNode({
|
|
1795
|
+
id: gltfScene.name || gltfScene.id,
|
|
1796
|
+
children: nodes
|
|
1797
|
+
});
|
|
1798
|
+
return sceneNode;
|
|
1799
|
+
}
|
|
1800
|
+
function createNode(device, gltfNode, gltfNodes, options) {
|
|
1801
|
+
if (!gltfNode._node) {
|
|
1802
|
+
const gltfChildren = gltfNode.children || [];
|
|
1803
|
+
const children = gltfChildren.map(child => createNode(device, child, gltfNodes, options));
|
|
1804
|
+
// Node can have children nodes and meshes at the same time
|
|
1805
|
+
if (gltfNode.mesh) {
|
|
1806
|
+
children.push(createMesh(device, gltfNode.mesh, options));
|
|
1807
|
+
}
|
|
1808
|
+
const node = new GroupNode({
|
|
1809
|
+
id: gltfNode.name || gltfNode.id,
|
|
1810
|
+
children
|
|
1811
|
+
});
|
|
1812
|
+
if (gltfNode.matrix) {
|
|
1813
|
+
node.setMatrix(gltfNode.matrix);
|
|
1814
|
+
}
|
|
1815
|
+
else {
|
|
1816
|
+
node.matrix.identity();
|
|
1817
|
+
if (gltfNode.translation) {
|
|
1818
|
+
node.matrix.translate(gltfNode.translation);
|
|
1819
|
+
}
|
|
1820
|
+
if (gltfNode.rotation) {
|
|
1821
|
+
const rotationMatrix = new Matrix4().fromQuaternion(gltfNode.rotation);
|
|
1822
|
+
node.matrix.multiplyRight(rotationMatrix);
|
|
1823
|
+
}
|
|
1824
|
+
if (gltfNode.scale) {
|
|
1825
|
+
node.matrix.scale(gltfNode.scale);
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
gltfNode._node = node;
|
|
1829
|
+
}
|
|
1830
|
+
// Copy _node so that gltf-animator can access
|
|
1831
|
+
const topLevelNode = gltfNodes.find(node => node.id === gltfNode.id);
|
|
1832
|
+
topLevelNode._node = gltfNode._node;
|
|
1833
|
+
return gltfNode._node;
|
|
1834
|
+
}
|
|
1835
|
+
function createMesh(device, gltfMesh, options) {
|
|
1836
|
+
// TODO: avoid changing the gltf
|
|
1837
|
+
if (!gltfMesh._mesh) {
|
|
1838
|
+
const gltfPrimitives = gltfMesh.primitives || [];
|
|
1839
|
+
const primitives = gltfPrimitives.map((gltfPrimitive, i) => createPrimitive(device, gltfPrimitive, i, gltfMesh, options));
|
|
1840
|
+
const mesh = new GroupNode({
|
|
1841
|
+
id: gltfMesh.name || gltfMesh.id,
|
|
1842
|
+
children: primitives
|
|
1843
|
+
});
|
|
1844
|
+
gltfMesh._mesh = mesh;
|
|
1845
|
+
}
|
|
1846
|
+
return gltfMesh._mesh;
|
|
1847
|
+
}
|
|
1848
|
+
function createPrimitive(device, gltfPrimitive, i, gltfMesh, options) {
|
|
1849
|
+
const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${i}`;
|
|
1850
|
+
const topology = convertGLDrawModeToTopology(gltfPrimitive.mode || 4);
|
|
1851
|
+
const vertexCount = gltfPrimitive.indices
|
|
1852
|
+
? gltfPrimitive.indices.count
|
|
1853
|
+
: getVertexCount();
|
|
1854
|
+
const geometry = createGeometry(id, gltfPrimitive, topology);
|
|
1855
|
+
const parsedPPBRMaterial = parsePBRMaterial(device, gltfPrimitive.material, geometry.attributes, options);
|
|
1856
|
+
const modelNode = createGLTFModel(device, {
|
|
1857
|
+
id,
|
|
1858
|
+
geometry: createGeometry(id, gltfPrimitive, topology),
|
|
1859
|
+
parsedPPBRMaterial,
|
|
1860
|
+
modelOptions: options.modelOptions,
|
|
1861
|
+
vertexCount
|
|
1862
|
+
});
|
|
1863
|
+
modelNode.bounds = [gltfPrimitive.attributes.POSITION.min, gltfPrimitive.attributes.POSITION.max];
|
|
1864
|
+
// TODO this holds on to all the CPU side texture and attribute data
|
|
1865
|
+
// modelNode.material = gltfPrimitive.material;
|
|
1866
|
+
return modelNode;
|
|
1867
|
+
}
|
|
1868
|
+
function getVertexCount(attributes) {
|
|
1869
|
+
throw new Error('getVertexCount not implemented');
|
|
1870
|
+
}
|
|
1871
|
+
function createGeometry(id, gltfPrimitive, topology) {
|
|
1872
|
+
const attributes = {};
|
|
1873
|
+
for (const [attributeName, attribute] of Object.entries(gltfPrimitive.attributes)) {
|
|
1874
|
+
const { components, size, value } = attribute;
|
|
1875
|
+
attributes[attributeName] = { size: size ?? components, value };
|
|
1876
|
+
}
|
|
1877
|
+
return new Geometry({
|
|
1878
|
+
id,
|
|
1879
|
+
topology,
|
|
1880
|
+
indices: gltfPrimitive.indices.value,
|
|
1881
|
+
attributes
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
const scratchQuaternion = new Quaternion();
|
|
1886
|
+
function interpolate(time, { input, interpolation, output }, target, path) {
|
|
1887
|
+
const maxTime = input[input.length - 1];
|
|
1888
|
+
const animationTime = time % maxTime;
|
|
1889
|
+
const nextIndex = input.findIndex(t => t >= animationTime);
|
|
1890
|
+
const previousIndex = Math.max(0, nextIndex - 1);
|
|
1891
|
+
if (!Array.isArray(target[path])) {
|
|
1892
|
+
switch (path) {
|
|
1893
|
+
case 'translation':
|
|
1894
|
+
target[path] = [0, 0, 0];
|
|
1895
|
+
break;
|
|
1896
|
+
case 'rotation':
|
|
1897
|
+
target[path] = [0, 0, 0, 1];
|
|
1898
|
+
break;
|
|
1899
|
+
case 'scale':
|
|
1900
|
+
target[path] = [1, 1, 1];
|
|
1901
|
+
break;
|
|
1902
|
+
default:
|
|
1903
|
+
log.warn(`Bad animation path ${path}`)();
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
// assert(target[path].length === output[previousIndex].length);
|
|
1907
|
+
const previousTime = input[previousIndex];
|
|
1908
|
+
const nextTime = input[nextIndex];
|
|
1909
|
+
switch (interpolation) {
|
|
1910
|
+
case 'STEP':
|
|
1911
|
+
stepInterpolate(target, path, output[previousIndex]);
|
|
1912
|
+
break;
|
|
1913
|
+
case 'LINEAR':
|
|
1914
|
+
if (nextTime > previousTime) {
|
|
1915
|
+
const ratio = (animationTime - previousTime) / (nextTime - previousTime);
|
|
1916
|
+
linearInterpolate(target, path, output[previousIndex], output[nextIndex], ratio);
|
|
1917
|
+
}
|
|
1918
|
+
break;
|
|
1919
|
+
case 'CUBICSPLINE':
|
|
1920
|
+
if (nextTime > previousTime) {
|
|
1921
|
+
const ratio = (animationTime - previousTime) / (nextTime - previousTime);
|
|
1922
|
+
const tDiff = nextTime - previousTime;
|
|
1923
|
+
const p0 = output[3 * previousIndex + 1];
|
|
1924
|
+
const outTangent0 = output[3 * previousIndex + 2];
|
|
1925
|
+
const inTangent1 = output[3 * nextIndex + 0];
|
|
1926
|
+
const p1 = output[3 * nextIndex + 1];
|
|
1927
|
+
cubicsplineInterpolate(target, path, { p0, outTangent0, inTangent1, p1, tDiff, ratio });
|
|
1928
|
+
}
|
|
1929
|
+
break;
|
|
1930
|
+
default:
|
|
1931
|
+
log.warn(`Interpolation ${interpolation} not supported`)();
|
|
1932
|
+
break;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
function linearInterpolate(target, path, start, stop, ratio) {
|
|
1936
|
+
if (!target[path]) {
|
|
1937
|
+
throw new Error();
|
|
1938
|
+
}
|
|
1939
|
+
if (path === 'rotation') {
|
|
1940
|
+
// SLERP when path is rotation
|
|
1941
|
+
scratchQuaternion.slerp({ start, target: stop, ratio });
|
|
1942
|
+
for (let i = 0; i < scratchQuaternion.length; i++) {
|
|
1943
|
+
target[path][i] = scratchQuaternion[i];
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
else {
|
|
1947
|
+
// regular interpolation
|
|
1948
|
+
for (let i = 0; i < start.length; i++) {
|
|
1949
|
+
target[path][i] = ratio * stop[i] + (1 - ratio) * start[i];
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
function cubicsplineInterpolate(target, path, { p0, outTangent0, inTangent1, p1, tDiff, ratio: t }) {
|
|
1954
|
+
if (!target[path]) {
|
|
1955
|
+
throw new Error();
|
|
1956
|
+
}
|
|
1957
|
+
// TODO: Quaternion might need normalization
|
|
1958
|
+
for (let i = 0; i < target[path].length; i++) {
|
|
1959
|
+
const m0 = outTangent0[i] * tDiff;
|
|
1960
|
+
const m1 = inTangent1[i] * tDiff;
|
|
1961
|
+
target[path][i] =
|
|
1962
|
+
(2 * Math.pow(t, 3) - 3 * Math.pow(t, 2) + 1) * p0[i] +
|
|
1963
|
+
(Math.pow(t, 3) - 2 * Math.pow(t, 2) + t) * m0 +
|
|
1964
|
+
(-2 * Math.pow(t, 3) + 3 * Math.pow(t, 2)) * p1[i] +
|
|
1965
|
+
(Math.pow(t, 3) - Math.pow(t, 2)) * m1;
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
function stepInterpolate(target, path, value) {
|
|
1969
|
+
if (!target[path]) {
|
|
1970
|
+
throw new Error();
|
|
1971
|
+
}
|
|
1972
|
+
for (let i = 0; i < value.length; i++) {
|
|
1973
|
+
target[path][i] = value[i];
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
// luma.gl
|
|
1978
|
+
// SPDX-License-Identifier: MIT
|
|
1979
|
+
// Copyright (c) vis.gl contributors
|
|
1980
|
+
class GLTFSingleAnimator {
|
|
1981
|
+
animation;
|
|
1982
|
+
startTime = 0;
|
|
1983
|
+
playing = true;
|
|
1984
|
+
speed = 1;
|
|
1985
|
+
constructor(props) {
|
|
1986
|
+
this.animation = props.animation;
|
|
1987
|
+
this.animation.name ||= 'unnamed';
|
|
1988
|
+
Object.assign(this, props);
|
|
1989
|
+
}
|
|
1990
|
+
setTime(timeMs) {
|
|
1991
|
+
if (!this.playing) {
|
|
1992
|
+
return;
|
|
1993
|
+
}
|
|
1994
|
+
const absTime = timeMs / 1000;
|
|
1995
|
+
const time = (absTime - this.startTime) * this.speed;
|
|
1996
|
+
this.animation.channels.forEach(({ sampler, target, path }) => {
|
|
1997
|
+
interpolate(time, sampler, target, path);
|
|
1998
|
+
applyTranslationRotationScale(target, target._node);
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
class GLTFAnimator {
|
|
2003
|
+
animations;
|
|
2004
|
+
constructor(props) {
|
|
2005
|
+
this.animations = props.animations.map((animation, index) => {
|
|
2006
|
+
const name = animation.name || `Animation-${index}`;
|
|
2007
|
+
return new GLTFSingleAnimator({
|
|
2008
|
+
animation: { name, channels: animation.channels }
|
|
2009
|
+
});
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
/** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */
|
|
2013
|
+
animate(time) {
|
|
2014
|
+
log.warn('GLTFAnimator#animate is deprecated. Use GLTFAnimator#setTime instead')();
|
|
2015
|
+
this.setTime(time);
|
|
2016
|
+
}
|
|
2017
|
+
setTime(time) {
|
|
2018
|
+
this.animations.forEach(animation => animation.setTime(time));
|
|
2019
|
+
}
|
|
2020
|
+
getAnimations() {
|
|
2021
|
+
return this.animations;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
// TODO: share with GLTFInstantiator
|
|
2025
|
+
const scratchMatrix = new Matrix4();
|
|
2026
|
+
function applyTranslationRotationScale(gltfNode, node) {
|
|
2027
|
+
node.matrix.identity();
|
|
2028
|
+
if (gltfNode.translation) {
|
|
2029
|
+
node.matrix.translate(gltfNode.translation);
|
|
2030
|
+
}
|
|
2031
|
+
if (gltfNode.rotation) {
|
|
2032
|
+
const rotationMatrix = scratchMatrix.fromQuaternion(gltfNode.rotation);
|
|
2033
|
+
node.matrix.multiplyRight(rotationMatrix);
|
|
2034
|
+
}
|
|
2035
|
+
if (gltfNode.scale) {
|
|
2036
|
+
node.matrix.scale(gltfNode.scale);
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
// luma.gl
|
|
2041
|
+
// SPDX-License-Identifier: MIT
|
|
2042
|
+
// Copyright (c) vis.gl contributors
|
|
2043
|
+
const ATTRIBUTE_TYPE_TO_COMPONENTS = {
|
|
2044
|
+
SCALAR: 1,
|
|
2045
|
+
VEC2: 2,
|
|
2046
|
+
VEC3: 3,
|
|
2047
|
+
VEC4: 4,
|
|
2048
|
+
MAT2: 4,
|
|
2049
|
+
MAT3: 9,
|
|
2050
|
+
MAT4: 16
|
|
2051
|
+
};
|
|
2052
|
+
const ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = {
|
|
2053
|
+
5120: Int8Array,
|
|
2054
|
+
5121: Uint8Array,
|
|
2055
|
+
5122: Int16Array,
|
|
2056
|
+
5123: Uint16Array,
|
|
2057
|
+
5125: Uint32Array,
|
|
2058
|
+
5126: Float32Array
|
|
2059
|
+
};
|
|
2060
|
+
function accessorToTypedArray(accessor) {
|
|
2061
|
+
const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];
|
|
2062
|
+
const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];
|
|
2063
|
+
const length = components * accessor.count;
|
|
2064
|
+
const { buffer, byteOffset = 0 } = accessor.bufferView?.data ?? {};
|
|
2065
|
+
const typedArray = new ArrayType(buffer, byteOffset + (accessor.byteOffset || 0), length);
|
|
2066
|
+
return { typedArray, components };
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// luma.gl
|
|
2070
|
+
// SPDX-License-Identifier: MIT
|
|
2071
|
+
// Copyright (c) vis.gl contributors
|
|
2072
|
+
function parseGLTFAnimations(gltf) {
|
|
2073
|
+
const gltfAnimations = gltf.animations || [];
|
|
2074
|
+
return gltfAnimations.map((animation, index) => {
|
|
2075
|
+
const name = animation.name || `Animation-${index}`;
|
|
2076
|
+
const samplers = animation.samplers.map(({ input, interpolation = 'LINEAR', output }) => ({
|
|
2077
|
+
input: accessorToJsArray(gltf.accessors[input]),
|
|
2078
|
+
interpolation,
|
|
2079
|
+
output: accessorToJsArray(gltf.accessors[output])
|
|
2080
|
+
}));
|
|
2081
|
+
const channels = animation.channels.map(({ sampler, target }) => ({
|
|
2082
|
+
sampler: samplers[sampler],
|
|
2083
|
+
target: gltf.nodes[target.node ?? 0],
|
|
2084
|
+
path: target.path
|
|
2085
|
+
}));
|
|
2086
|
+
return { name, channels };
|
|
2087
|
+
});
|
|
2088
|
+
}
|
|
2089
|
+
//
|
|
2090
|
+
function accessorToJsArray(accessor) {
|
|
2091
|
+
if (!accessor._animation) {
|
|
2092
|
+
const { typedArray: array, components } = accessorToTypedArray(accessor);
|
|
2093
|
+
if (components === 1) {
|
|
2094
|
+
accessor._animation = Array.from(array);
|
|
2095
|
+
}
|
|
2096
|
+
else {
|
|
2097
|
+
// Slice array
|
|
2098
|
+
const slicedArray = [];
|
|
2099
|
+
for (let i = 0; i < array.length; i += components) {
|
|
2100
|
+
slicedArray.push(Array.from(array.slice(i, i + components)));
|
|
2101
|
+
}
|
|
2102
|
+
accessor._animation = slicedArray;
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
return accessor._animation;
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
/** Deeply copies a JS data structure */
|
|
2109
|
+
function deepCopy(object) {
|
|
2110
|
+
// don't copy binary data
|
|
2111
|
+
if (ArrayBuffer.isView(object) ||
|
|
2112
|
+
object instanceof ArrayBuffer ||
|
|
2113
|
+
object instanceof ImageBitmap) {
|
|
2114
|
+
return object;
|
|
2115
|
+
}
|
|
2116
|
+
if (Array.isArray(object)) {
|
|
2117
|
+
return object.map(deepCopy);
|
|
2118
|
+
}
|
|
2119
|
+
if (object && typeof object === 'object') {
|
|
2120
|
+
const result = {};
|
|
2121
|
+
for (const key in object) {
|
|
2122
|
+
result[key] = deepCopy(object[key]);
|
|
2123
|
+
}
|
|
2124
|
+
return result;
|
|
2125
|
+
}
|
|
2126
|
+
return object;
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
// luma.gl
|
|
2130
|
+
// SPDX-License-Identifier: MIT
|
|
2131
|
+
// Copyright (c) vis.gl contributors
|
|
2132
|
+
function createScenegraphsFromGLTF(device, gltf, options) {
|
|
2133
|
+
gltf = deepCopy(gltf);
|
|
2134
|
+
const scenes = parseGLTF(device, gltf, options);
|
|
2135
|
+
// Note: There is a nasty dependency on injected nodes in the glTF
|
|
2136
|
+
const animations = parseGLTFAnimations(gltf);
|
|
2137
|
+
const animator = new GLTFAnimator({ animations });
|
|
2138
|
+
return { scenes, animator };
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
// deck.gl
|
|
2142
|
+
// SPDX-License-Identifier: MIT
|
|
2143
|
+
// Copyright (c) vis.gl contributors
|
|
2144
|
+
async function waitForGLTFAssets(gltfObjects) {
|
|
2145
|
+
const remaining = [];
|
|
2146
|
+
gltfObjects.scenes.forEach(scene => {
|
|
2147
|
+
scene.traverse((modelNode) => {
|
|
2148
|
+
// Not really clear how we can access the uniforms?
|
|
2149
|
+
// TODO v9 getUnforms() was removed, hack it with props.uniforms
|
|
2150
|
+
// Object.values((modelNode as ModelNode).model.uniforms).forEach((uniform: any) => {
|
|
2151
|
+
// if (uniform.loaded === false) {
|
|
2152
|
+
// remaining.push(uniform);
|
|
2153
|
+
// }
|
|
2154
|
+
// });
|
|
2155
|
+
});
|
|
2156
|
+
});
|
|
2157
|
+
return await waitWhileCondition(() => remaining.some(uniform => !uniform.loaded));
|
|
2158
|
+
}
|
|
2159
|
+
async function waitWhileCondition(condition) {
|
|
2160
|
+
while (condition()) {
|
|
2161
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
// deck.gl
|
|
2166
|
+
// SPDX-License-Identifier: MIT
|
|
2167
|
+
// Copyright (c) vis.gl contributors
|
|
2168
|
+
const uniformBlock = `\
|
|
2169
|
+
uniform scenegraphUniforms {
|
|
2170
|
+
float sizeScale;
|
|
2171
|
+
float sizeMinPixels;
|
|
2172
|
+
float sizeMaxPixels;
|
|
2173
|
+
mat4 sceneModelMatrix;
|
|
2174
|
+
bool composeModelMatrix;
|
|
2175
|
+
} scenegraph;
|
|
2176
|
+
`;
|
|
2177
|
+
const scenegraphUniforms = {
|
|
2178
|
+
name: 'scenegraph',
|
|
2179
|
+
vs: uniformBlock,
|
|
2180
|
+
fs: uniformBlock,
|
|
2181
|
+
uniformTypes: {
|
|
2182
|
+
sizeScale: 'f32',
|
|
2183
|
+
sizeMinPixels: 'f32',
|
|
2184
|
+
sizeMaxPixels: 'f32',
|
|
2185
|
+
sceneModelMatrix: 'mat4x4<f32>',
|
|
2186
|
+
composeModelMatrix: 'f32'
|
|
2187
|
+
}
|
|
2188
|
+
};
|
|
2189
|
+
|
|
2190
|
+
// deck.gl
|
|
2191
|
+
// SPDX-License-Identifier: MIT
|
|
2192
|
+
// Copyright (c) vis.gl contributors
|
|
2193
|
+
var vs = `\
|
|
2194
|
+
#version 300 es
|
|
2195
|
+
#define SHADER_NAME scenegraph-layer-vertex-shader
|
|
2196
|
+
in vec3 instancePositions;
|
|
2197
|
+
in vec3 instancePositions64Low;
|
|
2198
|
+
in vec4 instanceColors;
|
|
2199
|
+
in vec3 instancePickingColors;
|
|
2200
|
+
in vec3 instanceModelMatrixCol0;
|
|
2201
|
+
in vec3 instanceModelMatrixCol1;
|
|
2202
|
+
in vec3 instanceModelMatrixCol2;
|
|
2203
|
+
in vec3 instanceTranslation;
|
|
2204
|
+
in vec3 positions;
|
|
2205
|
+
#ifdef HAS_UV
|
|
2206
|
+
in vec2 texCoords;
|
|
2207
|
+
#endif
|
|
2208
|
+
#ifdef LIGHTING_PBR
|
|
2209
|
+
#ifdef HAS_NORMALS
|
|
2210
|
+
in vec3 normals;
|
|
2211
|
+
#endif
|
|
2212
|
+
#endif
|
|
2213
|
+
out vec4 vColor;
|
|
2214
|
+
#ifndef LIGHTING_PBR
|
|
2215
|
+
#ifdef HAS_UV
|
|
2216
|
+
out vec2 vTEXCOORD_0;
|
|
2217
|
+
#endif
|
|
2218
|
+
#endif
|
|
2219
|
+
void main(void) {
|
|
2220
|
+
#if defined(HAS_UV) && !defined(LIGHTING_PBR)
|
|
2221
|
+
vTEXCOORD_0 = texCoords;
|
|
2222
|
+
geometry.uv = texCoords;
|
|
2223
|
+
#endif
|
|
2224
|
+
geometry.worldPosition = instancePositions;
|
|
2225
|
+
geometry.pickingColor = instancePickingColors;
|
|
2226
|
+
mat3 instanceModelMatrix = mat3(instanceModelMatrixCol0, instanceModelMatrixCol1, instanceModelMatrixCol2);
|
|
2227
|
+
vec3 normal = vec3(0.0, 0.0, 1.0);
|
|
2228
|
+
#ifdef LIGHTING_PBR
|
|
2229
|
+
#ifdef HAS_NORMALS
|
|
2230
|
+
normal = instanceModelMatrix * (scenegraph.sceneModelMatrix * vec4(normals, 0.0)).xyz;
|
|
2231
|
+
#endif
|
|
2232
|
+
#endif
|
|
2233
|
+
float originalSize = project_size_to_pixel(scenegraph.sizeScale);
|
|
2234
|
+
float clampedSize = clamp(originalSize, scenegraph.sizeMinPixels, scenegraph.sizeMaxPixels);
|
|
2235
|
+
vec3 pos = (instanceModelMatrix * (scenegraph.sceneModelMatrix * vec4(positions, 1.0)).xyz) * scenegraph.sizeScale * (clampedSize / originalSize) + instanceTranslation;
|
|
2236
|
+
if(scenegraph.composeModelMatrix) {
|
|
2237
|
+
DECKGL_FILTER_SIZE(pos, geometry);
|
|
2238
|
+
geometry.normal = project_normal(normal);
|
|
2239
|
+
geometry.worldPosition += pos;
|
|
2240
|
+
gl_Position = project_position_to_clipspace(pos + instancePositions, instancePositions64Low, vec3(0.0), geometry.position);
|
|
2241
|
+
}
|
|
2242
|
+
else {
|
|
2243
|
+
pos = project_size(pos);
|
|
2244
|
+
DECKGL_FILTER_SIZE(pos, geometry);
|
|
2245
|
+
gl_Position = project_position_to_clipspace(instancePositions, instancePositions64Low, pos, geometry.position);
|
|
2246
|
+
geometry.normal = project_normal(normal);
|
|
2247
|
+
}
|
|
2248
|
+
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
|
|
2249
|
+
#ifdef LIGHTING_PBR
|
|
2250
|
+
pbr_vPosition = geometry.position.xyz;
|
|
2251
|
+
#ifdef HAS_NORMALS
|
|
2252
|
+
pbr_vNormal = geometry.normal;
|
|
2253
|
+
#endif
|
|
2254
|
+
#ifdef HAS_UV
|
|
2255
|
+
pbr_vUV = texCoords;
|
|
2256
|
+
#else
|
|
2257
|
+
pbr_vUV = vec2(0., 0.);
|
|
2258
|
+
#endif
|
|
2259
|
+
geometry.uv = pbr_vUV;
|
|
2260
|
+
#endif
|
|
2261
|
+
vColor = instanceColors;
|
|
2262
|
+
DECKGL_FILTER_COLOR(vColor, geometry);
|
|
2263
|
+
}
|
|
2264
|
+
`;
|
|
2265
|
+
|
|
2266
|
+
// deck.gl
|
|
2267
|
+
// SPDX-License-Identifier: MIT
|
|
2268
|
+
// Copyright (c) vis.gl contributors
|
|
2269
|
+
var fs = `\
|
|
2270
|
+
#version 300 es
|
|
2271
|
+
#define SHADER_NAME scenegraph-layer-fragment-shader
|
|
2272
|
+
in vec4 vColor;
|
|
2273
|
+
out vec4 fragColor;
|
|
2274
|
+
#ifndef LIGHTING_PBR
|
|
2275
|
+
#if defined(HAS_UV) && defined(HAS_BASECOLORMAP)
|
|
2276
|
+
in vec2 vTEXCOORD_0;
|
|
2277
|
+
uniform sampler2D pbr_baseColorSampler;
|
|
2278
|
+
#endif
|
|
2279
|
+
#endif
|
|
2280
|
+
void main(void) {
|
|
2281
|
+
#ifdef LIGHTING_PBR
|
|
2282
|
+
fragColor = vColor * pbr_filterColor(vec4(0));
|
|
2283
|
+
geometry.uv = pbr_vUV;
|
|
2284
|
+
#else
|
|
2285
|
+
#if defined(HAS_UV) && defined(HAS_BASECOLORMAP)
|
|
2286
|
+
fragColor = vColor * texture(pbr_baseColorSampler, vTEXCOORD_0);
|
|
2287
|
+
geometry.uv = vTEXCOORD_0;
|
|
2288
|
+
#else
|
|
2289
|
+
fragColor = vColor;
|
|
2290
|
+
#endif
|
|
2291
|
+
#endif
|
|
2292
|
+
fragColor.a *= layer.opacity;
|
|
2293
|
+
DECKGL_FILTER_COLOR(fragColor, geometry);
|
|
2294
|
+
}
|
|
2295
|
+
`;
|
|
2296
|
+
|
|
2297
|
+
// deck.gl
|
|
2298
|
+
// SPDX-License-Identifier: MIT
|
|
2299
|
+
// Copyright (c) vis.gl contributors
|
|
2300
|
+
const DEFAULT_COLOR = [255, 255, 255, 255];
|
|
2301
|
+
const defaultProps = {
|
|
2302
|
+
scenegraph: { type: 'object', value: null, async: true },
|
|
2303
|
+
getScene: gltf => {
|
|
2304
|
+
if (gltf && gltf.scenes) {
|
|
2305
|
+
// gltf post processor replaces `gltf.scene` number with the scene `object`
|
|
2306
|
+
return typeof gltf.scene === 'object' ? gltf.scene : gltf.scenes[gltf.scene || 0];
|
|
2307
|
+
}
|
|
2308
|
+
return gltf;
|
|
2309
|
+
},
|
|
2310
|
+
getAnimator: scenegraph => scenegraph && scenegraph.animator,
|
|
2311
|
+
_animations: null,
|
|
2312
|
+
sizeScale: { type: 'number', value: 1, min: 0 },
|
|
2313
|
+
sizeMinPixels: { type: 'number', min: 0, value: 0 },
|
|
2314
|
+
sizeMaxPixels: { type: 'number', min: 0, value: Number.MAX_SAFE_INTEGER },
|
|
2315
|
+
getPosition: { type: 'accessor', value: (x) => x.position },
|
|
2316
|
+
getColor: { type: 'accessor', value: DEFAULT_COLOR },
|
|
2317
|
+
// flat or pbr
|
|
2318
|
+
_lighting: 'flat',
|
|
2319
|
+
// _lighting must be pbr for this to work
|
|
2320
|
+
_imageBasedLightingEnvironment: undefined,
|
|
2321
|
+
// yaw, pitch and roll are in degrees
|
|
2322
|
+
// https://en.wikipedia.org/wiki/Euler_angles
|
|
2323
|
+
// [pitch, yaw, roll]
|
|
2324
|
+
getOrientation: { type: 'accessor', value: [0, 0, 0] },
|
|
2325
|
+
getScale: { type: 'accessor', value: [1, 1, 1] },
|
|
2326
|
+
getTranslation: { type: 'accessor', value: [0, 0, 0] },
|
|
2327
|
+
// 4x4 matrix
|
|
2328
|
+
getTransformMatrix: { type: 'accessor', value: [] },
|
|
2329
|
+
loaders: [GLTFLoader]
|
|
2330
|
+
};
|
|
2331
|
+
/** Render a number of instances of a complete glTF scenegraph. */
|
|
2332
|
+
class ScenegraphLayer extends Layer {
|
|
2333
|
+
getShaders() {
|
|
2334
|
+
const defines = {};
|
|
2335
|
+
let pbr;
|
|
2336
|
+
if (this.props._lighting === 'pbr') {
|
|
2337
|
+
pbr = pbrMaterial;
|
|
2338
|
+
defines.LIGHTING_PBR = 1;
|
|
2339
|
+
}
|
|
2340
|
+
else {
|
|
2341
|
+
// Dummy shader module needed to handle
|
|
2342
|
+
// pbrMaterial.pbr_baseColorSampler binding
|
|
2343
|
+
pbr = { name: 'pbrMaterial' };
|
|
2344
|
+
}
|
|
2345
|
+
const modules = [project32, picking, scenegraphUniforms, pbr];
|
|
2346
|
+
return super.getShaders({ defines, vs, fs, modules });
|
|
2347
|
+
}
|
|
2348
|
+
initializeState() {
|
|
2349
|
+
const attributeManager = this.getAttributeManager();
|
|
2350
|
+
// attributeManager is always defined for primitive layers
|
|
2351
|
+
attributeManager.addInstanced({
|
|
2352
|
+
instancePositions: {
|
|
2353
|
+
size: 3,
|
|
2354
|
+
type: 'float64',
|
|
2355
|
+
fp64: this.use64bitPositions(),
|
|
2356
|
+
accessor: 'getPosition',
|
|
2357
|
+
transition: true
|
|
2358
|
+
},
|
|
2359
|
+
instanceColors: {
|
|
2360
|
+
type: 'unorm8',
|
|
2361
|
+
size: this.props.colorFormat.length,
|
|
2362
|
+
accessor: 'getColor',
|
|
2363
|
+
defaultValue: DEFAULT_COLOR,
|
|
2364
|
+
transition: true
|
|
2365
|
+
},
|
|
2366
|
+
instanceModelMatrix: MATRIX_ATTRIBUTES
|
|
2367
|
+
});
|
|
2368
|
+
}
|
|
2369
|
+
updateState(params) {
|
|
2370
|
+
super.updateState(params);
|
|
2371
|
+
const { props, oldProps } = params;
|
|
2372
|
+
if (props.scenegraph !== oldProps.scenegraph) {
|
|
2373
|
+
this._updateScenegraph();
|
|
2374
|
+
}
|
|
2375
|
+
else if (props._animations !== oldProps._animations) {
|
|
2376
|
+
this._applyAnimationsProp(this.state.animator, props._animations);
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
finalizeState(context) {
|
|
2380
|
+
super.finalizeState(context);
|
|
2381
|
+
this.state.scenegraph?.destroy();
|
|
2382
|
+
}
|
|
2383
|
+
get isLoaded() {
|
|
2384
|
+
return Boolean(this.state?.scenegraph && super.isLoaded);
|
|
2385
|
+
}
|
|
2386
|
+
_updateScenegraph() {
|
|
2387
|
+
const props = this.props;
|
|
2388
|
+
const { device } = this.context;
|
|
2389
|
+
let scenegraphData = null;
|
|
2390
|
+
if (props.scenegraph instanceof ScenegraphNode) {
|
|
2391
|
+
// Signature 1: props.scenegraph is a proper luma.gl Scenegraph
|
|
2392
|
+
scenegraphData = { scenes: [props.scenegraph] };
|
|
2393
|
+
}
|
|
2394
|
+
else if (props.scenegraph && typeof props.scenegraph === 'object') {
|
|
2395
|
+
// Converts loaders.gl gltf to luma.gl scenegraph using the undocumented @luma.gl/experimental function
|
|
2396
|
+
const gltf = props.scenegraph;
|
|
2397
|
+
// Tiles3DLoader already processes GLTF
|
|
2398
|
+
const processedGLTF = gltf.json ? postProcessGLTF(gltf) : gltf;
|
|
2399
|
+
const gltfObjects = createScenegraphsFromGLTF(device, processedGLTF, this._getModelOptions());
|
|
2400
|
+
scenegraphData = { gltf: processedGLTF, ...gltfObjects };
|
|
2401
|
+
waitForGLTFAssets(gltfObjects)
|
|
2402
|
+
.then(() => {
|
|
2403
|
+
this.setNeedsRedraw();
|
|
2404
|
+
})
|
|
2405
|
+
.catch(ex => {
|
|
2406
|
+
this.raiseError(ex, 'loading glTF');
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
const options = { layer: this, device: this.context.device };
|
|
2410
|
+
const scenegraph = props.getScene(scenegraphData, options);
|
|
2411
|
+
const animator = props.getAnimator(scenegraphData, options);
|
|
2412
|
+
if (scenegraph instanceof GroupNode) {
|
|
2413
|
+
this.state.scenegraph?.destroy();
|
|
2414
|
+
this._applyAnimationsProp(animator, props._animations);
|
|
2415
|
+
const models = [];
|
|
2416
|
+
scenegraph.traverse(node => {
|
|
2417
|
+
if (node instanceof ModelNode) {
|
|
2418
|
+
models.push(node.model);
|
|
2419
|
+
}
|
|
2420
|
+
});
|
|
2421
|
+
this.setState({ scenegraph, animator, models });
|
|
2422
|
+
this.getAttributeManager().invalidateAll();
|
|
2423
|
+
}
|
|
2424
|
+
else if (scenegraph !== null) {
|
|
2425
|
+
defaultLogger.warn('invalid scenegraph:', scenegraph)();
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
_applyAnimationsProp(animator, animationsProp) {
|
|
2429
|
+
if (!animator || !animationsProp) {
|
|
2430
|
+
return;
|
|
2431
|
+
}
|
|
2432
|
+
const animations = animator.getAnimations();
|
|
2433
|
+
// sort() to ensure '*' comes first so that other values can override
|
|
2434
|
+
Object.keys(animationsProp)
|
|
2435
|
+
.sort()
|
|
2436
|
+
.forEach(key => {
|
|
2437
|
+
// Key can be:
|
|
2438
|
+
// - number for index number
|
|
2439
|
+
// - name for animation name
|
|
2440
|
+
// - * to affect all animations
|
|
2441
|
+
const value = animationsProp[key];
|
|
2442
|
+
if (key === '*') {
|
|
2443
|
+
animations.forEach(animation => {
|
|
2444
|
+
Object.assign(animation, value);
|
|
2445
|
+
});
|
|
2446
|
+
}
|
|
2447
|
+
else if (Number.isFinite(Number(key))) {
|
|
2448
|
+
const number = Number(key);
|
|
2449
|
+
if (number >= 0 && number < animations.length) {
|
|
2450
|
+
Object.assign(animations[number], value);
|
|
2451
|
+
}
|
|
2452
|
+
else {
|
|
2453
|
+
defaultLogger.warn(`animation ${key} not found`)();
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
else {
|
|
2457
|
+
const findResult = animations.find(({ animation }) => animation.name === key);
|
|
2458
|
+
if (findResult) {
|
|
2459
|
+
Object.assign(findResult, value);
|
|
2460
|
+
}
|
|
2461
|
+
else {
|
|
2462
|
+
defaultLogger.warn(`animation ${key} not found`)();
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
});
|
|
2466
|
+
}
|
|
2467
|
+
_getModelOptions() {
|
|
2468
|
+
const { _imageBasedLightingEnvironment } = this.props;
|
|
2469
|
+
let env;
|
|
2470
|
+
if (_imageBasedLightingEnvironment) {
|
|
2471
|
+
if (typeof _imageBasedLightingEnvironment === 'function') {
|
|
2472
|
+
env = _imageBasedLightingEnvironment({ gl: this.context.gl, layer: this });
|
|
2473
|
+
}
|
|
2474
|
+
else {
|
|
2475
|
+
env = _imageBasedLightingEnvironment;
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
return {
|
|
2479
|
+
imageBasedLightingEnvironment: env,
|
|
2480
|
+
modelOptions: {
|
|
2481
|
+
id: this.props.id,
|
|
2482
|
+
isInstanced: true,
|
|
2483
|
+
bufferLayout: this.getAttributeManager().getBufferLayouts(),
|
|
2484
|
+
...this.getShaders()
|
|
2485
|
+
},
|
|
2486
|
+
// tangents are not supported
|
|
2487
|
+
useTangents: false
|
|
2488
|
+
};
|
|
2489
|
+
}
|
|
2490
|
+
draw({ context }) {
|
|
2491
|
+
if (!this.state.scenegraph)
|
|
2492
|
+
return;
|
|
2493
|
+
if (this.props._animations && this.state.animator) {
|
|
2494
|
+
this.state.animator.animate(context.timeline.getTime());
|
|
2495
|
+
this.setNeedsRedraw();
|
|
2496
|
+
}
|
|
2497
|
+
const { viewport, renderPass } = this.context;
|
|
2498
|
+
const { sizeScale, sizeMinPixels, sizeMaxPixels, coordinateSystem } = this.props;
|
|
2499
|
+
const pbrProjectionProps = {
|
|
2500
|
+
camera: viewport.cameraPosition
|
|
2501
|
+
};
|
|
2502
|
+
const numInstances = this.getNumInstances();
|
|
2503
|
+
this.state.scenegraph.traverse((node, { worldMatrix }) => {
|
|
2504
|
+
if (node instanceof ModelNode) {
|
|
2505
|
+
const { model } = node;
|
|
2506
|
+
model.setInstanceCount(numInstances);
|
|
2507
|
+
const scenegraphProps = {
|
|
2508
|
+
sizeScale,
|
|
2509
|
+
sizeMinPixels,
|
|
2510
|
+
sizeMaxPixels,
|
|
2511
|
+
composeModelMatrix: shouldComposeModelMatrix(viewport, coordinateSystem),
|
|
2512
|
+
sceneModelMatrix: worldMatrix
|
|
2513
|
+
};
|
|
2514
|
+
model.shaderInputs.setProps({
|
|
2515
|
+
pbrProjection: pbrProjectionProps,
|
|
2516
|
+
scenegraph: scenegraphProps
|
|
2517
|
+
});
|
|
2518
|
+
model.draw(renderPass);
|
|
2519
|
+
}
|
|
2520
|
+
});
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
ScenegraphLayer.defaultProps = defaultProps;
|
|
2524
|
+
ScenegraphLayer.layerName = 'ScenegraphLayer';
|
|
2525
|
+
|
|
2526
|
+
export { ScenegraphLayer as S, parsePBRMaterial as a, pbrMaterial as p };
|