Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move ScatterplotLayer & BitmapLayer to UBOs #8875

Merged
merged 33 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7b9bbf3
Hack in opacity via UBO
felixpalmer May 7, 2024
e5df579
Move scatterplot.vertex to UBO
felixpalmer May 7, 2024
dc1d66d
Port fragment shader
felixpalmer May 7, 2024
1454cb3
Extract uniforms
felixpalmer May 7, 2024
2325150
Move module definition
felixpalmer May 7, 2024
ed05d4c
Rename
felixpalmer May 7, 2024
9c8aac4
Type settings
felixpalmer May 7, 2024
089eada
Tidy
felixpalmer May 7, 2024
ed9343e
Test fixes
felixpalmer May 7, 2024
f2503f2
Cross check types
felixpalmer Jun 19, 2024
c39df33
Clearer naming
felixpalmer Jun 19, 2024
4a7c5e6
Use ShaderUniformType
felixpalmer Jun 21, 2024
9b09e75
Merge branch 'master' into felix/layer-ubo
felixpalmer Jun 21, 2024
6b28d9c
Bump luma to 9.0.15
felixpalmer Jun 21, 2024
fa9b9ee
bitmap-layer-uniforms
felixpalmer Jun 21, 2024
bc5a22d
Port bitmap shader
felixpalmer Jun 21, 2024
2598ae7
setProps
felixpalmer Jun 21, 2024
816731f
Bind bitmapTexture via module
felixpalmer Jun 21, 2024
2b6f7a9
Move out types
felixpalmer Jun 21, 2024
b356981
Uniform-types
felixpalmer Jun 21, 2024
7704e09
PoC opacity via module
felixpalmer Jun 21, 2024
229b570
Tidy
felixpalmer Jun 21, 2024
c3c3af9
Use layerUniforms in BitmapLayer
felixpalmer Jun 21, 2024
6773ecb
Move layerUniforms to shaderlib
felixpalmer Jun 21, 2024
970b761
Tidy
felixpalmer Jun 21, 2024
b59d840
Re-export layerUniforms
felixpalmer Jun 21, 2024
a1c12dc
Merge branch 'master' into felix/layer-ubo
felixpalmer Jul 1, 2024
c498560
Move layerUniforms to defaultShaderModules
felixpalmer Jul 1, 2024
fd49e29
Tidy
felixpalmer Jul 1, 2024
c60a28c
UBO in mask module
felixpalmer Jul 1, 2024
7675399
MaskProps types
felixpalmer Jul 1, 2024
b2066ef
Tidy
felixpalmer Jul 1, 2024
723ea05
Re-enable setUniforms for now
felixpalmer Jul 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export type {PickingInfo, GetPickingInfoParams} from './lib/picking/pick-info';
export type {ConstructorOf as _ConstructorOf} from './types/types';
export type {BinaryAttribute} from './lib/attribute/attribute';
export type {Effect, EffectContext, PreRenderOptions, PostRenderOptions} from './lib/effect';
export type {PickingUniforms, ProjectUniforms} from './shaderlib/index';
export type {PickingUniforms, ProjectUniforms, UniformTypes} from './shaderlib/index';
export type {DefaultProps} from './lifecycle/prop-types';
export type {LayersPassRenderOptions} from './passes/layers-pass';
export type {Widget, WidgetPlacement} from './lib/widget-manager';
Expand Down
4 changes: 2 additions & 2 deletions modules/core/src/lib/layer-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import type {Device, RenderPass} from '@luma.gl/core';
import {Timeline} from '@luma.gl/engine';
import type {ShaderAssembler, ShaderModule} from '@luma.gl/shadertools';
import {getShaderAssembler} from '../shaderlib/index';
import {getShaderAssembler, layerUniforms} from '../shaderlib/index';
import {LIFECYCLE} from '../lifecycle/constants';
import log from '../utils/log';
import debug from '../debug/index';
Expand Down Expand Up @@ -106,7 +106,7 @@ export default class LayerManager {
gl: device?.gl,
deck,
shaderAssembler: getShaderAssembler(),
defaultShaderModules: [],
defaultShaderModules: [layerUniforms],
renderPass: undefined!,
stats: stats || new Stats({id: 'deck.gl'}),
// Make sure context.viewport is not empty on the first layer initialization
Expand Down
16 changes: 12 additions & 4 deletions modules/core/src/lib/layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import type {LayerContext} from './layer-manager';
import type {BinaryAttribute} from './attribute/attribute';
import {RenderPass} from '@luma.gl/core';
import {PickingProps} from '@luma.gl/shadertools';
import {ProjectModuleSettings} from '../shaderlib/project/viewport-uniforms';

const TRACE_CHANGE_FLAG = 'layer.changeFlag';
const TRACE_INITIALIZE = 'layer.initialize';
Expand Down Expand Up @@ -1066,9 +1067,9 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
// @ts-ignore (TS2339) internalState is alwasy defined when this method is called
this.props = this.internalState.propsInTransition || currentProps;

const opacity = this.props.opacity;
// apply gamma to opacity to make it visually "linear"
uniforms.opacity = Math.pow(opacity, 1 / 2.2);
const opacity = Math.pow(this.props.opacity, 1 / 2.2);
uniforms.opacity = opacity; // TODO remove once layers ported to UBO
felixpalmer marked this conversation as resolved.
Show resolved Hide resolved

try {
// TODO/ib - hack move to luma Model.draw
Expand All @@ -1078,8 +1079,15 @@ export default abstract class Layer<PropsT extends {} = {}> extends Component<
const {modelMatrix} = this.props;
this.setModuleParameters(moduleParameters);
this.setShaderModuleProps({
picking: {isActive, isAttribute},
project: {viewport, devicePixelRatio, modelMatrix, coordinateSystem, coordinateOrigin}
layer: {opacity},
picking: {isActive, isAttribute} as PickingProps,
project: {
viewport,
devicePixelRatio,
modelMatrix,
coordinateSystem,
coordinateOrigin
} as ProjectModuleSettings
});
}

Expand Down
4 changes: 3 additions & 1 deletion modules/core/src/shaderlib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import {ShaderAssembler} from '@luma.gl/shadertools';

import {gouraudLighting, phongLighting} from '@luma.gl/shadertools';
import {layerUniforms} from './misc/layer-uniforms';
import geometry from './misc/geometry';
import project from './project/project';
import project32 from './project32/project32';
Expand Down Expand Up @@ -49,10 +50,11 @@ export function getShaderAssembler() {
return shaderAssembler;
}

export {picking, project, project32, gouraudLighting, phongLighting, shadow};
export {layerUniforms, picking, project, project32, gouraudLighting, phongLighting, shadow};

// Useful for custom shader modules
export type {ProjectUniforms} from './project/viewport-uniforms';
export type {UniformTypes} from './misc/uniform-types';

// TODO - these should be imported from luma.gl
/* eslint-disable camelcase */
Expand Down
21 changes: 21 additions & 0 deletions modules/core/src/shaderlib/misc/layer-uniforms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {ShaderModule} from '@luma.gl/shadertools';
import {UniformTypes} from './uniform-types';

const uniformBlock = `\
uniform layerUniforms {
uniform float opacity;
} layer;
`;

export type LayerProps = {
opacity?: number;
};

export const layerUniforms = {
name: 'layer',
vs: uniformBlock,
fs: uniformBlock,
uniformTypes: {
opacity: 'f32'
} as const satisfies UniformTypes<LayerProps>
} as const satisfies ShaderModule<LayerProps>;
66 changes: 66 additions & 0 deletions modules/core/src/shaderlib/misc/uniform-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
type UniformProps = {
[name: string]: number | boolean | number[];
};

type NumArray2 = [number, number];
type NumArray3 = [number, number, number];
type NumArray4 = [number, number, number, number];
type NumArray6 = [number, number, number, number, number, number];
type NumArray8 = [number, number, number, number, number, number, number, number];
type NumArray9 = [number, number, number, number, number, number, number, number, number];
type NumArray12 = [
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number
];
type NumArray16 = [
felixpalmer marked this conversation as resolved.
Show resolved Hide resolved
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number,
number
];

type UniformType<ValueT extends number | boolean | number[]> = ValueT extends number | boolean
? 'f32' | 'i32' | 'u32'
: ValueT extends NumArray2
? 'vec2<f32>' | 'vec2<i32>' | 'vec2<u32>'
: ValueT extends NumArray3
? 'vec3<f32>' | 'vec3<i32>' | 'vec3<u32>'
: ValueT extends NumArray4
? 'vec4<f32>' | 'vec4<i32>' | 'vec4<u32>' | 'mat2x2<f32>'
: ValueT extends NumArray6
? 'mat2x3<f32>' | 'mat3x2<f32>'
: ValueT extends NumArray8
? 'mat2x4<f32>' | 'mat4x2<f32>'
: ValueT extends NumArray9
? 'mat3x3<f32>'
: ValueT extends NumArray12
? 'mat3x4<f32>' | 'mat4x3<f32>'
: ValueT extends NumArray16
? 'mat4x4<f32>'
: never;

export type UniformTypes<PropsT extends UniformProps> = {
[name in keyof PropsT]: UniformType<PropsT[name]>;
};
19 changes: 11 additions & 8 deletions modules/extensions/src/mask/mask-extension.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {COORDINATE_SYSTEM, Layer, LayerExtension, log} from '@deck.gl/core';
import mask from './shader-module';
import mask, {MaskProps} from './shader-module';
import MaskEffect from './mask-effect';

const defaultProps = {
Expand Down Expand Up @@ -49,17 +49,18 @@ export default class MaskExtension extends LayerExtension {
}

/* eslint-disable camelcase */
draw(this: Layer<Required<MaskExtensionProps>>, {uniforms, context, moduleParameters}: any) {
uniforms.mask_maskByInstance = this.state.maskByInstance;
draw(this: Layer<Required<MaskExtensionProps>>, {context, moduleParameters}: any) {
const maskProps = {} as MaskProps;
maskProps.maskByInstance = Boolean(this.state.maskByInstance);
const {maskId, maskInverted} = 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;
maskProps.enabled = true;
maskProps.channel = index;
maskProps.inverted = maskInverted;

if (fromCoordinateSystem === COORDINATE_SYSTEM.DEFAULT) {
fromCoordinateSystem = viewport.isGeospatial
Expand All @@ -69,12 +70,14 @@ export default class MaskExtension extends LayerExtension {
const opts = {modelMatrix: null, fromCoordinateOrigin, fromCoordinateSystem};
const bl = this.projectPosition([bounds[0], bounds[1], 0], opts);
const tr = this.projectPosition([bounds[2], bounds[3], 0], opts);
uniforms.mask_bounds = [bl[0], bl[1], tr[0], tr[1]];
maskProps.bounds = [bl[0], bl[1], tr[0], tr[1]];
} else {
if (maskId) {
log.warn(`Could not find a mask layer with id: ${maskId}`)();
}
uniforms.mask_enabled = false;
maskProps.enabled = false;
}

this.setShaderModuleProps({mask: maskProps});
}
}
77 changes: 55 additions & 22 deletions modules/extensions/src/mask/shader-module.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,68 @@
import type {ShaderModule} from '@luma.gl/shadertools';
import {project} from '@deck.gl/core';
import {project, UniformTypes} from '@deck.gl/core';
import type {Texture} from '@luma.gl/core';
import {glsl} from '../utils/syntax-tags';

const vs = glsl`
uniform vec4 mask_bounds;
uniform bool mask_maskByInstance;
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);
return (position.xy - mask.bounds.xy) / (mask.bounds.zw - mask.bounds.xy);
}
`;

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

const fragment = glsl`
uniform sampler2D mask_texture;
uniform int mask_channel;
uniform bool mask_enabled;
uniform bool mask_inverted;

bool mask_isInBounds(vec2 texCoords) {
if (!mask_enabled) {
if (!mask.enabled) {
return true;
}
vec4 maskColor = texture(mask_texture, texCoords);
float maskValue = 1.0;
if (mask_channel == 0) {
if (mask.channel == 0) {
maskValue = maskColor.r;
} else if (mask_channel == 1) {
} else if (mask.channel == 1) {
maskValue = maskColor.g;
} else if (mask_channel == 2) {
} else if (mask.channel == 2) {
maskValue = maskColor.b;
} else if (mask_channel == 3) {
} else if (mask.channel == 3) {
maskValue = maskColor.a;
}

if (mask_inverted) {
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) {
if (mask.maskByInstance) {
mask_common_position = project_position(vec4(geometry.worldPosition, 1.0));
} else {
mask_common_position = geometry.position;
Expand All @@ -57,7 +73,7 @@ out vec2 mask_texCoords;
in vec2 mask_texCoords;
`,
'fs:#main-start': glsl`
if (mask_enabled) {
if (mask.enabled) {
bool mask = mask_isInBounds(mask_texCoords);

// Debug: show extent of render target
Expand All @@ -69,18 +85,28 @@ in vec2 mask_texCoords;
`
};

type MaskModuleSettings = {
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?: MaskModuleSettings | {}): Record<string, any> => {
const getMaskUniforms = (opts?: MaskProps | {}): Record<string, any> => {
if (opts && 'maskMap' in opts) {
return {
mask_texture: opts.maskMap
};
}
return {};
return opts || {};
};

export default {
Expand All @@ -89,5 +115,12 @@ export default {
vs,
fs,
inject,
getUniforms: getMaskUniforms
} as ShaderModule<MaskModuleSettings>;
getUniforms: getMaskUniforms,
uniformTypes: {
bounds: 'vec4<f32>',
channel: 'i32',
enabled: 'i32',
inverted: 'i32',
maskByInstance: 'i32'
} as const satisfies UniformTypes<MaskUniformProps>
} as const satisfies ShaderModule<MaskProps>;
Loading
Loading