UNPKG

@luma.gl/shadertools

Version:

Shader module system for luma.gl

197 lines (178 loc) 5.78 kB
// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors // cyan color const DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1]; const vs = /* glsl */ `\ uniform pickingUniforms { float isActive; float isAttribute; float isHighlightActive; float useFloatColors; vec3 highlightedObjectColor; vec4 highlightColor; } picking; out vec4 picking_vRGBcolor_Avalid; // Normalize unsigned byte color to 0-1 range vec3 picking_normalizeColor(vec3 color) { return picking.useFloatColors > 0.5 ? color : color / 255.0; } // Normalize unsigned byte color to 0-1 range 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; } // Check if this vertex is highlighted bool isVertexHighlighted(vec3 vertexColor) { vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor); return bool(picking.isHighlightActive) && picking_isColorZero(abs(vertexColor - highlightedObjectColor)); } // Set the current picking color void picking_setPickingColor(vec3 pickingColor) { pickingColor = picking_normalizeColor(pickingColor); if (bool(picking.isActive)) { // Use alpha as the validity flag. If pickingColor is [0, 0, 0] fragment is non-pickable picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor)); if (!bool(picking.isAttribute)) { // Stores the picking color so that the fragment shader can render it during picking picking_vRGBcolor_Avalid.rgb = pickingColor; } } else { // Do the comparison with selected item color in vertex shader as it should mean fewer compares 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 = /* glsl */ `\ uniform pickingUniforms { float isActive; float isAttribute; float isHighlightActive; float useFloatColors; vec3 highlightedObjectColor; vec4 highlightColor; } picking; in vec4 picking_vRGBcolor_Avalid; /* * Returns highlight color if this item is selected. */ vec4 picking_filterHighlightColor(vec4 color) { // If we are still picking, we don't highlight if (picking.isActive > 0.5) { return color; } bool selected = bool(picking_vRGBcolor_Avalid.a); if (selected) { // Blend in highlight color based on its alpha value 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; } } /* * Returns picking color if picking enabled else unmodified argument. */ vec4 picking_filterPickingColor(vec4 color) { if (bool(picking.isActive)) { if (picking_vRGBcolor_Avalid.a == 0.0) { discard; } return picking_vRGBcolor_Avalid; } return color; } /* * Returns picking color if picking is enabled if not * highlight color if this item is selected, otherwise unmodified argument. */ 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 = { props: {}, uniforms: {}, name: 'picking', uniformTypes: { isActive: 'f32', isAttribute: 'f32', isHighlightActive: 'f32', useFloatColors: 'f32', highlightedObjectColor: 'vec3<f32>', highlightColor: 'vec4<f32>' }, defaultUniforms: { isActive: false, isAttribute: false, isHighlightActive: false, useFloatColors: true, highlightedObjectColor: [0, 0, 0], highlightColor: DEFAULT_HIGHLIGHT_COLOR }, vs, fs, 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; } //# sourceMappingURL=picking.js.map