// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors import { glsl } from "../../../lib/glsl-utils/highlight.js"; // cyan color const DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1]; const vs = `\ uniform pickingUniforms { float isActive; float isAttribute; float isHighlightActive; float useFloatColors; vec3 highlightedObjectColor; vec4 highlightColor; } picking; out vec4 picking_vRGBcolor_Avalid; vec3 picking_normalizeColor(vec3 color) { return picking.useFloatColors > 0.5 ? color : color / 255.0; } vec4 picking_normalizeColor(vec4 color) { return picking.useFloatColors > 0.5 ? color : color / 255.0; } bool picking_isColorZero(vec3 color) { return dot(color, vec3(1.0)) < 0.00001; } bool picking_isColorValid(vec3 color) { return dot(color, vec3(1.0)) > 0.00001; } bool isVertexHighlighted(vec3 vertexColor) { vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor); return bool(picking.isHighlightActive) && picking_isColorZero(abs(vertexColor - highlightedObjectColor)); } void picking_setPickingColor(vec3 pickingColor) { pickingColor = picking_normalizeColor(pickingColor); if (bool(picking.isActive)) { picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor)); if (!bool(picking.isAttribute)) { picking_vRGBcolor_Avalid.rgb = pickingColor; } } else { picking_vRGBcolor_Avalid.a = float(isVertexHighlighted(pickingColor)); } } void picking_setPickingAttribute(float value) { if (bool(picking.isAttribute)) { picking_vRGBcolor_Avalid.r = value; } } void picking_setPickingAttribute(vec2 value) { if (bool(picking.isAttribute)) { picking_vRGBcolor_Avalid.rg = value; } } void picking_setPickingAttribute(vec3 value) { if (bool(picking.isAttribute)) { picking_vRGBcolor_Avalid.rgb = value; } } `; const fs = `\ uniform pickingUniforms { float isActive; float isAttribute; float isHighlightActive; float useFloatColors; vec3 highlightedObjectColor; vec4 highlightColor; } picking; in vec4 picking_vRGBcolor_Avalid; vec4 picking_filterHighlightColor(vec4 color) { if (picking.isActive > 0.5) { return color; } bool selected = bool(picking_vRGBcolor_Avalid.a); if (selected) { float highLightAlpha = picking.highlightColor.a; float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha); float highLightRatio = highLightAlpha / blendedAlpha; vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio); return vec4(blendedRGB, blendedAlpha); } else { return color; } } vec4 picking_filterPickingColor(vec4 color) { if (bool(picking.isActive)) { if (picking_vRGBcolor_Avalid.a == 0.0) { discard; } return picking_vRGBcolor_Avalid; } return color; } vec4 picking_filterColor(vec4 color) { vec4 highlightColor = picking_filterHighlightColor(color); return picking_filterPickingColor(highlightColor); } `; /** * Provides support for color-coding-based picking and highlighting. * In particular, supports picking a specific instance in an instanced * draw call and highlighting an instance based on its picking color, * and correspondingly, supports picking and highlighting groups of * primitives with the same picking color in non-instanced draw-calls */ export const picking = { name: 'picking', vs, fs, uniformTypes: { isActive: 'f32', isAttribute: 'f32', isHighlightActive: 'f32', useFloatColors: 'f32', highlightedObjectColor: 'vec3', highlightColor: 'vec4' }, defaultUniforms: { isActive: false, isAttribute: false, isHighlightActive: false, useFloatColors: true, highlightedObjectColor: [0, 0, 0], highlightColor: DEFAULT_HIGHLIGHT_COLOR }, getUniforms }; function getUniforms(opts = {}, prevUniforms) { const uniforms = {}; if (opts.highlightedObjectColor === undefined) { // Unless highlightedObjectColor explicitly null or set, do not update state } else if (opts.highlightedObjectColor === null) { uniforms.isHighlightActive = false; } else { uniforms.isHighlightActive = true; const highlightedObjectColor = opts.highlightedObjectColor.slice(0, 3); uniforms.highlightedObjectColor = highlightedObjectColor; } if (opts.highlightColor) { const color = Array.from(opts.highlightColor, x => x / 255); if (!Number.isFinite(color[3])) { color[3] = 1; } uniforms.highlightColor = color; } if (opts.isActive !== undefined) { uniforms.isActive = Boolean(opts.isActive); uniforms.isAttribute = Boolean(opts.isAttribute); } if (opts.useFloatColors !== undefined) { uniforms.useFloatColors = Boolean(opts.useFloatColors); } return uniforms; }