Skip to content

Commit

Permalink
feat(layers): ScatterplpotLayer uniform buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen committed Sep 25, 2023
1 parent edaf8fa commit 3bfeadc
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 51 deletions.
Expand Up @@ -18,47 +18,66 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

export default `\
import {glsl} from '@luma.gl/core';

export default glsl`\
#version 300 es
#define SHADER_NAME scatterplot-layer-fragment-shader
precision highp float;
uniform bool filled;
uniform float stroked;
uniform bool antialiasing;
precision highp int;
varying vec4 vFillColor;
varying vec4 vLineColor;
varying vec2 unitPosition;
varying float innerUnitRadius;
varying float outerRadiusPixels;
// Needs to be identical to vertex shader uniforms
uniform scatterplotUniforms {
// float opacity;
float radiusScale;
float radiusMinPixels;
float radiusMaxPixels;
float lineWidthScale;
float lineWidthMinPixels;
float lineWidthMaxPixels;
float stroked;
bool filled;
bool antialiasing;
bool billboard;
int radiusUnits;
int lineWidthUnits;
} scatterplot;
uniform float opacity;
void main(void) {
geometry.uv = unitPosition;
float distToCenter = length(unitPosition) * outerRadiusPixels;
float inCircle = antialiasing ?
float inCircle = scatterplot.antialiasing ?
smoothedge(distToCenter, outerRadiusPixels) :
step(distToCenter, outerRadiusPixels);
if (inCircle == 0.0) {
discard;
}
if (stroked > 0.5) {
float isLine = antialiasing ?
if (scatterplot.stroked > 0.5) {
float isLine = scatterplot.antialiasing ?
smoothedge(innerUnitRadius * outerRadiusPixels, distToCenter) :
step(innerUnitRadius * outerRadiusPixels, distToCenter);
if (filled) {
if (scatterplot.filled) {
gl_FragColor = mix(vFillColor, vLineColor, isLine);
} else {
if (isLine == 0.0) {
discard;
}
gl_FragColor = vec4(vLineColor.rgb, vLineColor.a * isLine);
}
} else if (filled) {
} else if (scatterplot.filled) {
gl_FragColor = vFillColor;
} else {
discard;
Expand Down
Expand Up @@ -18,7 +18,46 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

export default `\
import {ShaderUniformType, glsl} from '@luma.gl/core';

export type ScatterplotLayerUniforms = {
// opacity: number;
radiusScale: number;
radiusMinPixels: number;
radiusMaxPixels: number;
lineWidthScale: number;
lineWidthMinPixels: number;
lineWidthMaxPixels: number;
stroked: number;
filled: boolean;
antialiasing: boolean;
billboard: boolean;
radiusUnits: number;
lineWidthUnits: number;
};

export const scatterplot: {uniformTypes: Record<string, ShaderUniformType>} = {
uniformTypes: {
// opacity: 'f32',
radiusScale: 'f32',
radiusMinPixels: 'f32',
radiusMaxPixels: 'f32',
lineWidthScale: 'f32',
lineWidthMinPixels: 'f32',
lineWidthMaxPixels: 'f32',
stroked: 'f32',
filled: 'f32',
antialiasing: 'f32',
billboard: 'f32',
radiusUnits: 'i32',
lineWidthUnits: 'i32'
}
};

const SMOOTH_EDGE_RADIUS = 0.5;

export default glsl`\
#version 300 es
#define SHADER_NAME scatterplot-layer-vertex-shader
attribute vec3 positions;
Expand All @@ -31,56 +70,60 @@ attribute vec4 instanceFillColors;
attribute vec4 instanceLineColors;
attribute vec3 instancePickingColors;
uniform float opacity;
uniform float radiusScale;
uniform float radiusMinPixels;
uniform float radiusMaxPixels;
uniform float lineWidthScale;
uniform float lineWidthMinPixels;
uniform float lineWidthMaxPixels;
uniform float stroked;
uniform bool filled;
uniform bool antialiasing;
uniform bool billboard;
uniform int radiusUnits;
uniform int lineWidthUnits;
varying vec4 vFillColor;
varying vec4 vLineColor;
varying vec2 unitPosition;
varying float innerUnitRadius;
varying float outerRadiusPixels;
// Needs to be identical to fragment shader uniforms
uniform scatterplotUniforms {
// float opacity;
float radiusScale;
float radiusMinPixels;
float radiusMaxPixels;
float lineWidthScale;
float lineWidthMinPixels;
float lineWidthMaxPixels;
float stroked;
bool filled;
bool antialiasing;
bool billboard;
int radiusUnits;
int lineWidthUnits;
} scatterplot;
uniform float opacity;
void main(void) {
geometry.worldPosition = instancePositions;
// Multiply out radius and clamp to limits
outerRadiusPixels = clamp(
project_size_to_pixel(radiusScale * instanceRadius, radiusUnits),
radiusMinPixels, radiusMaxPixels
project_size_to_pixel(scatterplot.radiusScale * instanceRadius, scatterplot.radiusUnits),
scatterplot.radiusMinPixels, scatterplot.radiusMaxPixels
);
// Multiply out line width and clamp to limits
float lineWidthPixels = clamp(
project_size_to_pixel(lineWidthScale * instanceLineWidths, lineWidthUnits),
lineWidthMinPixels, lineWidthMaxPixels
project_size_to_pixel(scatterplot.lineWidthScale * instanceLineWidths, scatterplot.lineWidthUnits),
scatterplot.lineWidthMinPixels, scatterplot.lineWidthMaxPixels
);
// outer radius needs to offset by half stroke width
outerRadiusPixels += stroked * lineWidthPixels / 2.0;
outerRadiusPixels += scatterplot.stroked * lineWidthPixels / 2.0;
// Expand geometry to accomodate edge smoothing
float edgePadding = antialiasing ? (outerRadiusPixels + SMOOTH_EDGE_RADIUS) / outerRadiusPixels : 1.0;
// Expand geometry to accommodate edge smoothing
float edgePadding = scatterplot.antialiasing ? (outerRadiusPixels + SMOOTH_EDGE_RADIUS) / outerRadiusPixels : 1.0;
// position on the containing square in [-1, 1] space
unitPosition = edgePadding * positions.xy;
geometry.uv = unitPosition;
geometry.pickingColor = instancePickingColors;
innerUnitRadius = 1.0 - stroked * lineWidthPixels / outerRadiusPixels;
innerUnitRadius = 1.0 - scatterplot.stroked * lineWidthPixels / outerRadiusPixels;
if (billboard) {
if (scatterplot.billboard) {
gl_Position = project_position_to_clipspace(instancePositions, instancePositions64Low, vec3(0.0), geometry.position);
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);
vec3 offset = edgePadding * positions * outerRadiusPixels;
Expand Down
52 changes: 36 additions & 16 deletions modules/layers/src/scatterplot-layer/scatterplot-layer.ts
Expand Up @@ -19,13 +19,11 @@
// THE SOFTWARE.

import {Layer, project32, picking, UNIT} from '@deck.gl/core';
import {UniformStore} from '@luma.gl/core';
import {Geometry} from '@luma.gl/engine';
import {Model} from '@luma.gl/engine';
import {GL} from '@luma.gl/constants';

import vs from './scatterplot-layer-vertex.glsl';
import fs from './scatterplot-layer-fragment.glsl';

import type {
LayerProps,
LayerDataSource,
Expand All @@ -37,6 +35,9 @@ import type {
DefaultProps
} from '@deck.gl/core';

import vs, {ScatterplotLayerUniforms, scatterplot} from './scatterplot-layer-vertex.glsl';
import fs from './scatterplot-layer-fragment.glsl';

const DEFAULT_COLOR: [number, number, number, number] = [0, 0, 0, 255];

/** All props supported by the ScatterplotLayer */
Expand Down Expand Up @@ -181,11 +182,19 @@ export default class ScatterplotLayer<DataT = any, ExtraPropsT extends {} = {}>
static defaultProps = defaultProps;
static layerName: string = 'ScatterplotLayer';

state!: Layer['state'] & {
uniformStore: UniformStore<{scatterplot: ScatterplotLayerUniforms}>;
};

getShaders() {
return super.getShaders({vs, fs, modules: [project32, picking]});
}

initializeState() {
this.state.uniformStore = new UniformStore<{scatterplot: ScatterplotLayerUniforms}>({
scatterplot
});

this.getAttributeManager()!.addInstanced({
instancePositions: {
size: 3,
Expand Down Expand Up @@ -251,20 +260,25 @@ export default class ScatterplotLayer<DataT = any, ExtraPropsT extends {} = {}>
lineWidthMaxPixels
} = this.props;

// opacity etc
this.state.model.setUniforms(uniforms);
this.state.model.setUniforms({
stroked: stroked ? 1 : 0,
filled,
billboard,
antialiasing,
radiusUnits: UNIT[radiusUnits],
radiusScale,
radiusMinPixels,
radiusMaxPixels,
lineWidthUnits: UNIT[lineWidthUnits],
lineWidthScale,
lineWidthMinPixels,
lineWidthMaxPixels

// scatterplot uniform block
this.state.uniformStore.setUniforms({
scatterplot: {
stroked: stroked ? 1 : 0,
filled,
billboard,
antialiasing,
radiusUnits: UNIT[radiusUnits],
radiusScale,
radiusMinPixels,
radiusMaxPixels,
lineWidthUnits: UNIT[lineWidthUnits],
lineWidthScale,
lineWidthMinPixels,
lineWidthMaxPixels
}
});
this.state.model.draw(this.context.renderPass);
}
Expand All @@ -282,6 +296,12 @@ export default class ScatterplotLayer<DataT = any, ExtraPropsT extends {} = {}>
positions: {size: 3, value: new Float32Array(positions)}
}
}),
bindings: {
scatterplotUniforms: this.state.uniformStore.getManagedUniformBuffer(
this.context.device,
'scatterplot'
)
},
isInstanced: true
});
}
Expand Down
1 change: 1 addition & 0 deletions modules/mapbox/package.json
Expand Up @@ -30,6 +30,7 @@
"prepublishOnly": "npm run build-bundle && npm run build-bundle -- --env=dev"
},
"dependencies": {
"@luma.gl/constants": "9.0.0-alpha.36",
"@luma.gl/core": "9.0.0-alpha.36",
"@math.gl/web-mercator": "4.0.0-alpha.4",
"@types/mapbox-gl": "^2.6.3"
Expand Down
2 changes: 1 addition & 1 deletion modules/test-utils/src/generate-layer-tests.ts
Expand Up @@ -19,7 +19,7 @@
// THE SOFTWARE.
import {_count as count} from '@deck.gl/core';

function noop() {}
function noop() {} // eslint-disable-line @typescript-eslint/no-empty-function

function defaultAssert(condition, comment) {
if (!condition) {
Expand Down

0 comments on commit 3bfeadc

Please sign in to comment.