Skip to content

Commit

Permalink
Extensions UBOs (#9001)
Browse files Browse the repository at this point in the history
  • Loading branch information
felixpalmer authored Jul 4, 2024
1 parent 2195b8b commit f8723cb
Show file tree
Hide file tree
Showing 23 changed files with 354 additions and 214 deletions.
23 changes: 23 additions & 0 deletions modules/core/src/lib/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,30 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
const {viewport, devicePixelRatio, coordinateSystem, coordinateOrigin} = moduleParameters;
const {modelMatrix} = this.props;
this.setModuleParameters(moduleParameters);
const {
picking,
heightMap,
heightMapBounds,
dummyHeightMap,
terrainCover,
drawToTerrainHeightMap,
useTerrainHeightMap,
terrainSkipRender
} = moduleParameters;
const terrainProps = {
viewport,
picking,
heightMap,
heightMapBounds,
dummyHeightMap,
terrainCover,
drawToTerrainHeightMap,
useTerrainHeightMap,
terrainSkipRender
};
this.setShaderModuleProps({
// TODO Revisit whether this is necessary once all layers ported to UBO
terrain: terrainProps,
layer: {opacity},
picking: {isActive, isAttribute} as PickingProps,
project: {
Expand Down
15 changes: 14 additions & 1 deletion modules/extensions/src/brushing/brushing-extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// THE SOFTWARE.

import {LayerExtension} from '@deck.gl/core';
import shaderModule from './shader-module';
import shaderModule, {BrushingModuleProps} from './shader-module';

import type {Layer, LayerContext, Accessor} from '@deck.gl/core';

Expand Down Expand Up @@ -101,4 +101,17 @@ export default class BrushingExtension extends LayerExtension {
});
}
}

draw(this: Layer<BrushingExtensionProps>, params: any, extension: this) {
const {viewport, mousePosition} = params.context;
const {brushingEnabled, brushingRadius, brushingTarget} = params.moduleParameters;
const brushingProps: BrushingModuleProps = {
viewport,
mousePosition,
brushingEnabled,
brushingRadius,
brushingTarget
};
this.setShaderModuleProps({brushing: brushingProps});
}
}
65 changes: 41 additions & 24 deletions modules/extensions/src/brushing/shader-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,35 @@ import type {Viewport} from '@deck.gl/core';
import type {BrushingExtensionProps} from './brushing-extension';
import {glsl} from '../utils/syntax-tags';

type BrushingModuleSettings = {
export type BrushingModuleProps = {
// From layer context
viewport: Viewport;
mousePosition?: {x: number; y: number};
} & BrushingExtensionProps;

const vs = glsl`
uniform bool brushing_enabled;
uniform int brushing_target;
uniform vec2 brushing_mousePos;
uniform float brushing_radius;
const uniformBlock = glsl`\
uniform brushingUniforms {
bool enabled;
highp int target;
vec2 mousePos;
float radius;
} brushing;
`;

const vertex = glsl`
in vec2 brushingTargets;
out float brushing_isVisible;
bool brushing_isPointInRange(vec2 position) {
if (!brushing_enabled) {
if (!brushing.enabled) {
return true;
}
vec2 source_commonspace = project_position(position);
vec2 target_commonspace = project_position(brushing_mousePos);
vec2 target_commonspace = project_position(brushing.mousePos);
float distance = length((target_commonspace - source_commonspace) / project.commonUnitsPerMeter.xy);
return distance <= brushing_radius;
return distance <= brushing.radius;
}
bool brushing_arePointsInRange(vec2 sourcePos, vec2 targetPos) {
Expand All @@ -61,11 +65,20 @@ const vs = glsl`
}
`;

const fs = glsl`
uniform bool brushing_enabled;
const vs = `
${uniformBlock}
${vertex}
`;

const fragment = glsl`
in float brushing_isVisible;
`;

const fs = `
${uniformBlock}
${fragment}
`;

const TARGET = {
source: 0,
target: 1,
Expand All @@ -77,18 +90,18 @@ const inject = {
'vs:DECKGL_FILTER_GL_POSITION': glsl`
vec2 brushingTarget;
vec2 brushingSource;
if (brushing_target == 3) {
if (brushing.target == 3) {
brushingTarget = geometry.worldPositionAlt.xy;
brushingSource = geometry.worldPosition.xy;
} else if (brushing_target == 0) {
} else if (brushing.target == 0) {
brushingTarget = geometry.worldPosition.xy;
} else if (brushing_target == 1) {
} else if (brushing.target == 1) {
brushingTarget = geometry.worldPositionAlt.xy;
} else {
brushingTarget = brushingTargets;
}
bool visible;
if (brushing_target == 3) {
if (brushing.target == 3) {
visible = brushing_arePointsInRange(brushingSource, brushingTarget);
} else {
visible = brushing_isPointInRange(brushingTarget);
Expand All @@ -97,7 +110,7 @@ const inject = {
`,

'fs:DECKGL_FILTER_COLOR': `
if (brushing_enabled && brushing_isVisible < 0.5) {
if (brushing.enabled && brushing_isVisible < 0.5) {
discard;
}
`
Expand All @@ -109,7 +122,7 @@ export default {
vs,
fs,
inject,
getUniforms: (opts?: BrushingModuleSettings | {}): Record<string, any> => {
getUniforms: (opts?: BrushingModuleProps | {}): Record<string, any> => {
if (!opts || !('viewport' in opts)) {
return {};
}
Expand All @@ -121,14 +134,18 @@ export default {
viewport
} = opts;
return {
brushing_enabled: Boolean(
brushingEnabled && mousePosition && viewport.containsPixel(mousePosition)
),
brushing_radius: brushingRadius,
brushing_target: TARGET[brushingTarget] || 0,
brushing_mousePos: mousePosition
enabled: Boolean(brushingEnabled && mousePosition && viewport.containsPixel(mousePosition)),
radius: brushingRadius,
target: TARGET[brushingTarget] || 0,
mousePos: mousePosition
? viewport.unproject([mousePosition.x - viewport.x, mousePosition.y - viewport.y])
: [0, 0]
};
},
uniformTypes: {
enabled: 'i32',
target: 'i32',
mousePos: 'vec2<f32>',
radius: 'f32'
}
} as ShaderModule<BrushingModuleSettings>;
} as ShaderModule<BrushingModuleProps>;
39 changes: 27 additions & 12 deletions modules/extensions/src/clip/clip-extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import type {ShaderModule} from '@luma.gl/shadertools';
import {LayerExtension} from '@deck.gl/core';

import type {Layer} from '@deck.gl/core';
import type {Layer, UniformTypes} from '@deck.gl/core';
import {glsl} from '../utils/syntax-tags';

const defaultProps = {
Expand All @@ -42,20 +42,29 @@ export type ClipExtensionProps = {
};

const shaderFunction = glsl`
uniform vec4 clip_bounds;
uniform clipUniforms {
vec4 bounds;
} clip;
bool clip_isInBounds(vec2 position) {
return position.x >= clip_bounds[0] && position.y >= clip_bounds[1] && position.x < clip_bounds[2] && position.y < clip_bounds[3];
return position.x >= clip.bounds[0] && position.y >= clip.bounds[1] && position.x < clip.bounds[2] && position.y < clip.bounds[3];
}
`;

export type ClipModuleProps = {
bounds: [number, number, number, number];
};

/*
* The vertex-shader version clips geometries by their anchor position
* e.g. ScatterplotLayer - show if the center of a circle is within bounds
*/
const shaderModuleVs: ShaderModule = {
name: 'clip-vs',
vs: shaderFunction
const shaderModuleVs: ShaderModule<ClipModuleProps> = {
name: 'clip',
vs: shaderFunction,
uniformTypes: {
bounds: 'vec4<f32>'
} as const satisfies UniformTypes<ClipModuleProps>
};

const injectionVs = {
Expand All @@ -77,9 +86,12 @@ in float clip_isVisible;
* The fragment-shader version clips pixels at the bounds
* e.g. PolygonLayer - show the part of the polygon that intersect with the bounds
*/
const shaderModuleFs: ShaderModule = {
name: 'clip-fs',
fs: shaderFunction
const shaderModuleFs: ShaderModule<ClipModuleProps> = {
name: 'clip',
fs: shaderFunction,
uniformTypes: {
bounds: 'vec4<f32>'
}
};

const injectionFs = {
Expand Down Expand Up @@ -126,20 +138,23 @@ export default class ClipExtension extends LayerExtension {
}

/* eslint-disable camelcase */
draw(this: Layer<Required<ClipExtensionProps>>, {uniforms}: any): void {
draw(this: Layer<Required<ClipExtensionProps>>): void {
const {clipBounds} = this.props;
const clipProps = {} as ClipModuleProps;
if (this.state.clipByInstance) {
uniforms.clip_bounds = clipBounds;
clipProps.bounds = clipBounds;
} else {
const corner0 = this.projectPosition([clipBounds[0], clipBounds[1], 0]);
const corner1 = this.projectPosition([clipBounds[2], clipBounds[3], 0]);

uniforms.clip_bounds = [
clipProps.bounds = [
Math.min(corner0[0], corner1[0]),
Math.min(corner0[1], corner1[1]),
Math.max(corner0[0], corner1[0]),
Math.max(corner0[1], corner1[1])
];
}

this.setShaderModuleProps({clip: clipProps});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Accessor, Layer, LayerContext, LayerExtension} from '@deck.gl/core';
import collision from './shader-module';
import collision, {CollisionModuleProps} from './shader-module';
import CollisionFilterEffect from './collision-filter-effect';

const defaultProps = {
Expand Down Expand Up @@ -42,17 +42,24 @@ export default class CollisionFilterExtension extends LayerExtension {
}

/* eslint-disable camelcase */
draw(this: Layer<CollisionFilterExtensionProps>, {uniforms, context, moduleParameters}: any) {
draw(this: Layer<CollisionFilterExtensionProps>, {moduleParameters}: any) {
const {collisionEnabled} = this.props;
const {collisionFBO, drawToCollisionMap} = moduleParameters;
const {collisionFBO, drawToCollisionMap, dummyCollisionMap} = moduleParameters;
const enabled = collisionEnabled && Boolean(collisionFBO);
uniforms.collision_enabled = enabled;

if (drawToCollisionMap) {
// Override any props with those defined in collisionTestProps
// @ts-ignore
this.props = this.clone(this.props.collisionTestProps).props;
}

const collisionProps: CollisionModuleProps = {
enabled,
collisionFBO,
drawToCollisionMap,
dummyCollisionMap
};
this.setShaderModuleProps({collision: collisionProps});
}

initializeState(
Expand Down
Loading

0 comments on commit f8723cb

Please sign in to comment.