Skip to content

Commit 352bddf

Browse files
feat(layers): add getPixelOffset prop to ScatterplotLayer
Add a getPixelOffset accessor to ScatterplotLayer that allows shifting the rendered circle by a fixed number of screen pixels, independently of zoom level. This is useful for preventing overlap between circles and other layers (e.g. icons, text) without modifying the underlying data positions. The implementation follows the same pattern used by IconLayer and TextLayer: - New instance attribute `instancePixelOffset` (vec2, transition-enabled) - In billboard mode, the pixel offset is added to the screen-space offset before clip-space projection - In non-billboard mode, the pixel offset is converted to common space via project_pixel_size and added to the common-space offset - Both GLSL and WGSL shader variants are updated - Default value is [0, 0] for backward compatibility Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
1 parent 5748b7f commit 352bddf

3 files changed

Lines changed: 28 additions & 8 deletions

File tree

modules/layers/src/scatterplot-layer/scatterplot-layer-vertex.glsl.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ in float instanceLineWidths;
1515
in vec4 instanceFillColors;
1616
in vec4 instanceLineColors;
1717
in vec3 instancePickingColors;
18+
in vec2 instancePixelOffset;
1819
1920
out vec4 vFillColor;
2021
out vec4 vLineColor;
@@ -54,10 +55,12 @@ void main(void) {
5455
gl_Position = project_position_to_clipspace(instancePositions, instancePositions64Low, vec3(0.0), geometry.position);
5556
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
5657
vec3 offset = edgePadding * positions * outerRadiusPixels;
58+
offset.xy += instancePixelOffset;
5759
DECKGL_FILTER_SIZE(offset, geometry);
5860
gl_Position.xy += project_pixel_size_to_clipspace(offset.xy);
5961
} else {
6062
vec3 offset = edgePadding * positions * project_pixel_size(outerRadiusPixels);
63+
offset.xy += project_pixel_size(instancePixelOffset);
6164
DECKGL_FILTER_SIZE(offset, geometry);
6265
gl_Position = project_position_to_clipspace(instancePositions, instancePositions64Low, offset, geometry.position);
6366
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);

modules/layers/src/scatterplot-layer/scatterplot-layer.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ type _ScatterplotLayerProps<DataT> = {
116116
* @default 1
117117
*/
118118
getLineWidth?: Accessor<DataT, number>;
119+
/**
120+
* Pixel offset accessor, [x, y] in pixels.
121+
* @default [0, 0]
122+
*/
123+
getPixelOffset?: Accessor<DataT, Readonly<[number, number]>>;
119124
/**
120125
* @deprecated Use `getLineWidth` instead
121126
*/
@@ -151,6 +156,7 @@ const defaultProps: DefaultProps<ScatterplotLayerProps> = {
151156
getFillColor: {type: 'accessor', value: DEFAULT_COLOR},
152157
getLineColor: {type: 'accessor', value: DEFAULT_COLOR},
153158
getLineWidth: {type: 'accessor', value: 1},
159+
getPixelOffset: {type: 'accessor', value: [0, 0]},
154160

155161
// deprecated
156162
strokeWidth: {deprecatedFor: 'getLineWidth'},
@@ -212,6 +218,11 @@ export default class ScatterplotLayer<DataT = any, ExtraPropsT extends {} = {}>
212218
transition: true,
213219
accessor: 'getLineWidth',
214220
defaultValue: 1
221+
},
222+
instancePixelOffset: {
223+
size: 2,
224+
transition: true,
225+
accessor: 'getPixelOffset'
215226
}
216227
});
217228
}

modules/layers/src/scatterplot-layer/scatterplot-layer.wgsl.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,16 @@ struct ConstantAttributeUniforms {
2828
instanceFillColors: vec4<f32>,
2929
instanceLineColors: vec4<f32>,
3030
instancePickingColors: vec3<f32>,
31+
instancePixelOffset: vec2<f32>,
3132
3233
instancePositionsConstant: i32,
3334
instancePositions64LowConstant: i32,
3435
instanceRadiusConstant: i32,
3536
instanceLineWidthsConstant: i32,
3637
instanceFillColorsConstant: i32,
3738
instanceLineColorsConstant: i32,
38-
instancePickingColorsConstant: i32
39+
instancePickingColorsConstant: i32,
40+
instancePixelOffsetConstant: i32
3941
};
4042
4143
@group(0) @binding(0) var<uniform> scatterplot: ScatterplotUniforms;
@@ -47,7 +49,8 @@ struct ConstantAttributes {
4749
instanceLineWidths: f32,
4850
instanceFillColors: vec4<f32>,
4951
instanceLineColors: vec4<f32>,
50-
instancePickingColors: vec3<f32>
52+
instancePickingColors: vec3<f32>,
53+
instancePixelOffset: vec2<f32>
5154
};
5255
5356
const constants = ConstantAttributes(
@@ -57,7 +60,8 @@ const constants = ConstantAttributes(
5760
0.0,
5861
vec4<f32>(0.0, 0.0, 0.0, 1.0),
5962
vec4<f32>(0.0, 0.0, 0.0, 1.0),
60-
vec3<f32>(0.0)
63+
vec3<f32>(0.0),
64+
vec2<f32>(0.0)
6165
);
6266
6367
struct Attributes {
@@ -70,7 +74,8 @@ struct Attributes {
7074
@location(4) instanceLineWidths: f32,
7175
@location(5) instanceFillColors: vec4<f32>,
7276
@location(6) instanceLineColors: vec4<f32>,
73-
@location(7) instancePickingColors: vec3<f32>
77+
@location(7) instancePickingColors: vec3<f32>,
78+
@location(8) instancePixelOffset: vec2<f32>
7479
};
7580
7681
struct Varyings {
@@ -127,13 +132,14 @@ fn vertexMain(attributes: Attributes) -> Varyings {
127132
if (scatterplot.billboard != 0) {
128133
varyings.position = project_position_to_clipspace(attributes.instancePositions, attributes.instancePositions64Low, vec3<f32>(0.0)); // TODO , geometry.position);
129134
// DECKGL_FILTER_GL_POSITION(varyings.position, geometry);
130-
let offset = attributes.positions; // * edgePadding * varyings.outerRadiusPixels;
135+
var offset = edgePadding * attributes.positions * varyings.outerRadiusPixels;
136+
offset = vec3<f32>(offset.xy + attributes.instancePixelOffset, offset.z);
131137
// DECKGL_FILTER_SIZE(offset, geometry);
132138
let clipPixels = project_pixel_size_to_clipspace(offset.xy);
133-
varyings.position.x = clipPixels.x;
134-
varyings.position.y = clipPixels.y;
139+
varyings.position = vec4<f32>(varyings.position.x + clipPixels.x, varyings.position.y + clipPixels.y, varyings.position.z, varyings.position.w);
135140
} else {
136-
let offset = edgePadding * attributes.positions * project_pixel_size_float(varyings.outerRadiusPixels);
141+
var offset = edgePadding * attributes.positions * project_pixel_size_float(varyings.outerRadiusPixels);
142+
offset = vec3<f32>(offset.xy + project_pixel_size_vec2(attributes.instancePixelOffset), offset.z);
137143
// DECKGL_FILTER_SIZE(offset, geometry);
138144
varyings.position = project_position_to_clipspace(attributes.instancePositions, attributes.instancePositions64Low, offset); // TODO , geometry.position);
139145
// DECKGL_FILTER_GL_POSITION(varyings.position, geometry);

0 commit comments

Comments
 (0)