Skip to content

Commit

Permalink
Add maskInverted prop to MaskExtension (visgl#7440)
Browse files Browse the repository at this point in the history
  • Loading branch information
felixpalmer authored Nov 22, 2022
1 parent 1342a96 commit 3ffdc5e
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 10 deletions.
4 changes: 4 additions & 0 deletions docs/api-reference/extensions/mask-extension.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ Id of the layer that defines the mask. The mask layer must use the prop `operati

![maskByInstance](https://raw.githubusercontent.com/visgl/deck.gl-data/master/images/docs/mask-by-instance.png)

##### `maskInverted` (Boolean, optional)

When `maskInverted` is true the result of the masking operation is inverted. Inversion is applied when reading the mask, thus it is possible to use the same mask normally on some layers and inverted on other layers. Defaults to `false`.

## Limitations

- The current implementation supports up to 4 masks at the same time.
Expand Down
10 changes: 8 additions & 2 deletions modules/extensions/src/mask/mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import type {Layer} from '@deck.gl/core';

const defaultProps = {
maskId: '',
maskByInstance: undefined
maskByInstance: undefined,
maskInverted: false
};

export type MaskExtensionProps = {
Expand All @@ -19,6 +20,10 @@ export type MaskExtensionProps = {
* If not specified, it is automatically deduced from the layer.
*/
maskByInstance?: boolean;
/**
* Inverts the masking operation
*/
maskInverted?: boolean;
};

/** Allows layers to show/hide objects by a geofence. */
Expand All @@ -43,14 +48,15 @@ export default class MaskExtension extends LayerExtension {
/* eslint-disable camelcase */
draw(this: Layer<MaskExtensionProps>, {uniforms, context, moduleParameters}: any) {
uniforms.mask_maskByInstance = this.state.maskByInstance;
const {maskId = ''} = this.props;
const {maskId = '', maskInverted = false} = this.props;
const {maskChannels} = moduleParameters;
const {viewport} = context;
if (maskChannels && maskChannels[maskId]) {
const {index, bounds, coordinateOrigin: fromCoordinateOrigin} = maskChannels[maskId];
let {coordinateSystem: fromCoordinateSystem} = maskChannels[maskId];
uniforms.mask_enabled = true;
uniforms.mask_channel = index;
uniforms.mask_inverted = maskInverted;

if (fromCoordinateSystem === COORDINATE_SYSTEM.DEFAULT) {
fromCoordinateSystem = viewport.isGeospatial
Expand Down
8 changes: 7 additions & 1 deletion modules/extensions/src/mask/shader-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const fs = `
uniform sampler2D mask_texture;
uniform int mask_channel;
uniform bool mask_enabled;
uniform bool mask_inverted;
bool mask_isInBounds(vec2 texCoords) {
if (!mask_enabled) {
return true;
Expand All @@ -29,7 +30,12 @@ bool mask_isInBounds(vec2 texCoords) {
} else if (mask_channel == 3) {
maskValue = maskColor.a;
}
return maskValue < 0.5;
if (mask_inverted) {
return maskValue >= 0.5;
} else {
return maskValue < 0.5;
}
}
`;

Expand Down
18 changes: 15 additions & 3 deletions test/apps/mask/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ function getLayerData(data) {
export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) {
const {arcs, targets, sources} = useMemo(() => getLayerData(data), [data]);
const [maskEnabled, setMaskEnabled] = useState(true);
const [maskInverted, setMaskInverted] = useState(false);
const [showLayers, setShowLayers] = useState(true);
const [selectedCounty, selectCounty] = useState(null);
const [selectedCounty2, selectCounty2] = useState(null);
Expand Down Expand Up @@ -202,15 +203,17 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) {
parameters: {depthTest: false},
extensions: [new MaskExtension()],
maskId: maskEnabled && 'mask2',
maskByInstance: false
maskByInstance: false,
maskInverted
}),
new ScatterplotLayer({
id: 'sources',
data: sources,
radiusScale: 3000,
getFillColor: d => (d.gain > 0 ? TARGET_COLOR : SOURCE_COLOR),
extensions: [new MaskExtension()],
maskId: maskEnabled && 'mask2'
maskId: maskEnabled && 'mask2',
maskInverted
}),
new ScatterplotLayer({
id: 'targets',
Expand All @@ -224,7 +227,8 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) {
radiusScale: 3000,
getFillColor: d => (d.net > 0 ? TARGET_COLOR : SOURCE_COLOR),
extensions: [new MaskExtension()],
maskId: maskEnabled && 'mask2'
maskId: maskEnabled && 'mask2',
maskInverted
}),
new ArcLayer({
id: 'arc',
Expand Down Expand Up @@ -259,6 +263,14 @@ export default function App({data, strokeWidth = 1, mapStyle = MAP_STYLE}) {
/>
Use mask
</label>
<label>
<input
type="checkbox"
checked={maskInverted}
onChange={() => setMaskInverted(!maskInverted)}
/>
Invert mask
</label>
<label>
<input type="checkbox" checked={showLayers} onChange={() => setShowLayers(!showLayers)} />
Show layers
Expand Down
10 changes: 10 additions & 0 deletions test/modules/extensions/mask.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,20 @@ test('MaskExtension', t => {
onAfterUpdate: ({layer}) => {
const uniforms = layer.getModels()[0].getUniforms();
t.ok(uniforms.mask_enabled, 'mask_enabled in uniforms');
t.equal(uniforms.mask_inverted, false, 'mask_inverted defaults to false in uniforms');
t.ok(uniforms.mask_maskByInstance, 'mask_maskByInstance in uniforms');
t.ok(uniforms.mask_bounds.every(Number.isFinite), 'mask_bounds in uniforms');
}
},
{
updateProps: {
maskInverted: true
},
onAfterUpdate: ({layer}) => {
const uniforms = layer.getModels()[0].getUniforms();
t.ok(uniforms.mask_inverted, 'mask_inverted true in uniforms');
}
},
{
updateProps: {
maskId: 'mask2'
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 6 additions & 4 deletions test/render/test-cases/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ export default [
goldenImage: './test/render/golden-images/shadow-effect.png'
},

{
name: 'mask-effect',
...[true, false].map(maskInverted => ({
name: `mask-effect${maskInverted ? '-inverted' : ''}`,
viewState: {
latitude: 37.751537058389985,
longitude: -122.42694203247012,
Expand All @@ -98,6 +98,7 @@ export default [
new SolidPolygonLayer({
id: 'polygon-masked',
maskId: 'mask-layer',
maskInverted,
extensions: [new MaskExtension()],
data: polygons,
getPolygon: f => f,
Expand All @@ -106,6 +107,7 @@ export default [
new ScatterplotLayer({
id: 'points',
maskId: 'mask-layer',
maskInverted,
extensions: [new MaskExtension()],
data: points,
getPosition: d => d.COORDINATES,
Expand All @@ -119,8 +121,8 @@ export default [
imageDiffOptions: {
threshold: 0.985
},
goldenImage: './test/render/golden-images/mask-effect.png'
},
goldenImage: `./test/render/golden-images/mask-effect${maskInverted ? '-inverted' : ''}.png`
})),

{
name: 'post-process-effects',
Expand Down

0 comments on commit 3ffdc5e

Please sign in to comment.