@deck.gl/extensions
Version:
Plug-and-play functionalities for deck.gl layers
130 lines (113 loc) • 2.7 kB
text/typescript
// deck.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import type {ShaderModule} from '@luma.gl/shadertools';
import {project} from '@deck.gl/core';
import type {Texture} from '@luma.gl/core';
const uniformBlock = /* glsl */ `\
uniform maskUniforms {
vec4 bounds;
highp int channel;
bool enabled;
bool inverted;
bool maskByInstance;
} mask;
`;
const vertex = /* glsl */ `
vec2 mask_getCoords(vec4 position) {
return (position.xy - mask.bounds.xy) / (mask.bounds.zw - mask.bounds.xy);
}
`;
const vs = `
${uniformBlock}
${vertex}
`;
const fragment = /* glsl */ `
uniform sampler2D mask_texture;
bool mask_isInBounds(vec2 texCoords) {
if (!mask.enabled) {
return true;
}
vec4 maskColor = texture(mask_texture, texCoords);
float maskValue = 1.0;
if (mask.channel == 0) {
maskValue = maskColor.r;
} else if (mask.channel == 1) {
maskValue = maskColor.g;
} else if (mask.channel == 2) {
maskValue = maskColor.b;
} else if (mask.channel == 3) {
maskValue = maskColor.a;
}
if (mask.inverted) {
return maskValue >= 0.5;
} else {
return maskValue < 0.5;
}
}
`;
const fs = `
${uniformBlock}
${fragment}
`;
const inject = {
'vs:#decl': /* glsl */ `
out vec2 mask_texCoords;
`,
'vs:#main-end': /* glsl */ `
vec4 mask_common_position;
if (mask.maskByInstance) {
mask_common_position = project_position(vec4(geometry.worldPosition, 1.0));
} else {
mask_common_position = geometry.position;
}
mask_texCoords = mask_getCoords(mask_common_position);
`,
'fs:#decl': /* glsl */ `
in vec2 mask_texCoords;
`,
'fs:#main-start': /* glsl */ `
if (mask.enabled) {
bool mask = mask_isInBounds(mask_texCoords);
// Debug: show extent of render target
// fragColor = vec4(mask_texCoords, 0.0, 1.0);
// fragColor = texture(mask_texture, mask_texCoords);
if (!mask) discard;
}
`
};
type MaskBindingProps = {
maskMap?: Texture;
};
type MaskUniformProps = {
bounds: [number, number, number, number];
channel: number;
enabled: boolean;
inverted: boolean;
maskByInstance: boolean;
};
export type MaskProps = MaskBindingProps & MaskUniformProps;
/* eslint-disable camelcase */
const getMaskUniforms = (opts?: MaskProps | {}): Record<string, any> => {
if (opts && 'maskMap' in opts) {
return {
mask_texture: opts.maskMap
};
}
return opts || {};
};
export default {
name: 'mask',
dependencies: [project],
vs,
fs,
inject,
getUniforms: getMaskUniforms,
uniformTypes: {
bounds: 'vec4<f32>',
channel: 'i32',
enabled: 'i32',
inverted: 'i32',
maskByInstance: 'i32'
}
} as const satisfies ShaderModule<MaskProps>;