Skip to content

Commit

Permalink
fix(arcgis): remove dependency on @luma.gl/webgl (#8747)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress authored Apr 4, 2024
1 parent e0cefb0 commit 4b2c496
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 54 deletions.
4 changes: 2 additions & 2 deletions examples/gallery/src/boiler-plate-arcgis.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<title>Get Started with deck.gl and ArcGIS</title>
<script src="https://unpkg.com/deck.gl@^9.0.0/dist.min.js"></script>
<script src="https://unpkg.com/@deck.gl/arcgis@^9.0.0/dist.min.js"></script>
<script src="https://js.arcgis.com/4.14/"></script>
<link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/themes/light/main.css"/>
<script src="https://js.arcgis.com/4.29/"></script>
<link rel="stylesheet" href="https://js.arcgis.com/4.29/esri/themes/light/main.css"/>
</head>

<body style="margin:0;">
Expand Down
2 changes: 1 addition & 1 deletion examples/get-started/pure-js/arcgis/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const AIR_PORTS =
'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson';

const layer = new DeckLayer({
effect: 'bloom(1.5, 0.5px, 0.1)',
// effect: 'bloom(1.5, 0.5px, 0.1)',
'deck.getTooltip': info => info.object && info.object.properties.name,
'deck.layers': [
new GeoJsonLayer({
Expand Down
3 changes: 1 addition & 2 deletions modules/arcgis/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@
},
"dependencies": {
"@luma.gl/constants": "^9.0.9",
"@luma.gl/webgl": "^9.0.9",
"esri-loader": "^3.3.0"
"esri-loader": "^3.7.0"
},
"peerDependencies": {
"@arcgis/core": "^4.0.0",
Expand Down
92 changes: 56 additions & 36 deletions modules/arcgis/src/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {GL} from '@luma.gl/constants';
import {Model, Geometry} from '@luma.gl/engine';
import {Deck} from '@deck.gl/core';
import type {Device, Texture, Framebuffer} from '@luma.gl/core';
import type {WebGLDevice} from '@luma.gl/webgl';

interface Renderer {
redraw: () => void;
Expand All @@ -17,7 +16,43 @@ export type RenderResources = {
fbo: Framebuffer;
};

export function initializeResources(this: Renderer, device: Device): RenderResources {
async function createDeckInstance(gl: WebGL2RenderingContext): Promise<{
deckInstance: Deck;
device: Device;
}> {
return new Promise(resolve => {
const deckInstance = new Deck({
// The view state will be set dynamically to track the MapView current extent.
viewState: {},

// Input is handled by the ArcGIS API for JavaScript.
controller: false,

// We use the same WebGL context as the ArcGIS API for JavaScript.
gl,

// We need depth testing in general; we don't know what layers might be added to the deck.
parameters: {
depthCompare: 'less-equal'
},

// To disable canvas resizing, since the FBO is owned by the ArcGIS API for JavaScript.
width: null,
height: null,

onDeviceInitialized: (device: Device) => {
resolve({deckInstance, device});
}
});
});
}

export async function initializeResources(
this: Renderer,
gl: WebGL2RenderingContext
): Promise<RenderResources> {
const {deckInstance, device} = await createDeckInstance(gl);

const texture = device.createTexture({
format: 'rgba8unorm',
width: 1,
Expand Down Expand Up @@ -58,7 +93,13 @@ void main(void) {
},
parameters: {
depthWriteEnabled: true,
depthCompare: 'less-equal'
depthCompare: 'less-equal',
blendColorSrcFactor: 'one',
blendColorDstFactor: 'one-minus-src-alpha',
blendAlphaSrcFactor: 'one',
blendAlphaDstFactor: 'one-minus-src-alpha',
blendColorOperation: 'add',
blendAlphaOperation: 'add'
},
geometry: new Geometry({
topology: 'triangle-strip',
Expand All @@ -73,31 +114,14 @@ void main(void) {
id: 'deckfbo',
width: 1,
height: 1,
colorAttachments: [texture]
colorAttachments: [texture],
depthStencilAttachment: 'depth16unorm'
});

const deckInstance = new Deck({
// The view state will be set dynamically to track the MapView current extent.
viewState: {},

// Input is handled by the ArcGIS API for JavaScript.
controller: false,

// We use the same WebGL context as the ArcGIS API for JavaScript.
device,

// We need depth testing in general; we don't know what layers might be added to the deck.
parameters: {
depthCompare: 'less-equal'
},

deckInstance.setProps({
// This deck renders into an auxiliary framebuffer.
_framebuffer: fbo,

// To disable canvas resizing, since the FBO is owned by the ArcGIS API for JavaScript.
width: null,
height: null,

_customRender: redrawReason => {
if (redrawReason === 'arcgis') {
deckInstance._drawLayers(redrawReason);
Expand Down Expand Up @@ -125,7 +149,8 @@ export function render(
) {
const {model, deck, fbo} = resources;
const device = model.device;
const screenFbo = (device as WebGLDevice).getParametersWebGL(GL.FRAMEBUFFER_BINDING);
// @ts-ignore device.getParametersWebGL should return `any` not `void`?
const screenFbo: Framebuffer = device.getParametersWebGL(GL.FRAMEBUFFER_BINDING);
const {width, height, ...viewState} = viewport;

/* global window */
Expand All @@ -144,19 +169,14 @@ export function render(
const textureToScreenPass = device.beginRenderPass({
framebuffer: screenFbo,
parameters: {viewport: [0, 0, pixelWidth, pixelHeight]},
clearColor: [0, 0, 0, 0],
clearDepth: 1
clearColor: false,
clearDepth: false
});

device.withParametersWebGL(
{
blend: true,
blendFunc: [GL.ONE, GL.ONE_MINUS_SRC_ALPHA]
},
() => {
model.draw(textureToScreenPass);
}
);
try {
model.draw(textureToScreenPass);
} finally {
textureToScreenPass.end();
}
}

export function finalizeResources(resources: RenderResources) {
Expand Down
30 changes: 22 additions & 8 deletions modules/arcgis/src/deck-layer-view-2d.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
import {WebGLDevice} from '@luma.gl/webgl';
import {initializeResources, render, finalizeResources} from './commons';

export default function createDeckLayerView2D(BaseLayerViewGL2D) {
return BaseLayerViewGL2D.createSubclass({
properties: {
cancelInitialization: null,
resources: null
},

// Attach is called as soon as the layer view is ready to start rendering.
attach() {
async attach() {
// We use a full-screen quad and shaders to composite the frame rendered
// with deck.gl on top of the MapView. Composition uses the MapView context.
const gl = this.context;
const device = WebGLDevice.attach(gl);

this.resources = initializeResources.call(this, device);
let cancelled = false;
this.cancelInitialization = () => (cancelled = true);
const resources = await initializeResources.call(this, gl);
// If the layer got detached while awaiting, do not proceed
if (cancelled) {
finalizeResources(resources);
return;
}
this.resources = resources;

// Update deck props
this.layer.deck.on('change', props => this.resources.deck.setProps(props));
this.layer.deck.on('change', props => resources.deck.setProps(props));

// We need to start drawing the deck.gl layer immediately.
this.resources.deck.setProps(this.layer.deck.toJSON());
resources.deck.setProps(this.layer.deck.toJSON());
},

redraw() {
Expand All @@ -29,12 +36,19 @@ export default function createDeckLayerView2D(BaseLayerViewGL2D) {

// Called when the layer must be destroyed.
detach() {
finalizeResources(this.resources);
this.resources = null;
this.cancelInitialization?.();
if (this.resources) {
finalizeResources(this.resources);
this.resources = null;
}
},

// Called every time that the layer view must be rendered.
render(renderParameters) {
if (!this.resources) {
return;
}

const [width, height] = this.view.state.size;
// The view state must be kept in-sync with the MapView of the ArcGIS API.
const state = renderParameters.state;
Expand Down
16 changes: 12 additions & 4 deletions modules/arcgis/src/deck-renderer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable no-invalid-this */
import {WebGLDevice} from '@luma.gl/webgl';
import {initializeResources, render, finalizeResources, RenderResources} from './commons';

import SceneView from '@arcgis/core/views/SceneView';
Expand All @@ -18,16 +17,24 @@ export default function createDeckRenderer(DeckProps, externalRenderers) {
view: SceneView;
deck: any;
resources: RenderResources | null = null;
cancelInitialization: (() => void) | null = null;

constructor(view: SceneView, props: DeckProps) {
this.view = view;
this.deck = new DeckProps(props);
}

setup(context) {
async setup(context) {
const gl = context.gl;
const device = WebGLDevice.attach(gl);
const resources = initializeResources.call(this, device);

let cancelled = false;
this.cancelInitialization = () => (cancelled = true);
const resources = await initializeResources.call(this, gl);
// If the renderer got disposed while awaiting, do not proceed
if (cancelled) {
finalizeResources(resources);
return;
}

this.deck.on('change', props => resources.deck.setProps(props));

Expand All @@ -36,6 +43,7 @@ export default function createDeckRenderer(DeckProps, externalRenderers) {
}

dispose() {
this.cancelInitialization?.();
if (this.resources) {
finalizeResources(this.resources);
}
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5957,7 +5957,7 @@ esrecurse@^4.3.0:
dependencies:
estraverse "^5.2.0"

esri-loader@^3.3.0:
esri-loader@^3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/esri-loader/-/esri-loader-3.7.0.tgz#be2432664f53d4878b34ab903499248bbca3e087"
integrity sha512-cB1Sw9EQjtW4mtT7eFBjn/6VaaIWNTjmTd2asnnEyuZk1xVSFRMCfLZSBSjZM7ZarDcVu5WIjOP0t0MYVu4hVQ==
Expand Down

0 comments on commit 4b2c496

Please sign in to comment.