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

carto module UBO #9038

Merged
merged 4 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 30 additions & 7 deletions modules/carto/src/layers/heatmap-tile-layer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import {ShaderModule} from '@luma.gl/shadertools';
import {getResolution} from 'quadbin';

import {Accessor, CompositeLayer, CompositeLayerProps, DefaultProps, Layer} from '@deck.gl/core';
import {
Accessor,
CompositeLayer,
CompositeLayerProps,
DefaultProps,
Layer,
UniformTypes
} from '@deck.gl/core';
import {SolidPolygonLayer} from '@deck.gl/layers';

import {HeatmapProps, heatmap} from './heatmap';
Expand All @@ -18,23 +26,35 @@ function unitDensityForCell(cell: bigint) {
return Math.pow(4.0, cellResolution);
}

const uniformBlock = `\
uniform densityUniforms {
float factor;
} density;
`;

type DensityProps = {factor: number};
const densityUniforms = {
name: 'density',
vs: uniformBlock,
uniformTypes: {
factor: 'f32'
} as const satisfies UniformTypes<Required<DensityProps>>
} as const satisfies ShaderModule<DensityProps>;

// Modified polygon layer to draw offscreen and output value expected by heatmap
class RTTSolidPolygonLayer extends RTTModifier(SolidPolygonLayer) {
static layerName = 'RTTSolidPolygonLayer';

getShaders(type) {
const shaders = super.getShaders(type);
shaders.inject = {
'vs:#decl': `
uniform float densityFactor;
`,
'vs:#main-end': `
// Value from getWeight accessor
float weight = elevations;

// Keep "power" delivered to screen constant when tiles update
// by outputting normalized density
weight *= densityFactor;
weight *= density.factor;

// Pack float into 3 channels to pass to heatmap shader
// SCALE value important, as we don't want to saturate
Expand All @@ -47,15 +67,18 @@ uniform float densityFactor;
vColor = vec4(mod(vec3(weight, floor(weight / SHIFT.yz)), 256.0), 255.0) / 255.0;
`
};
shaders.modules = [...shaders.modules, densityUniforms];
return shaders;
}

draw(this, opts: any) {
const cell = this.props!.data[0];
const maxDensity = this.props.elevationScale;
const densityFactor = unitDensityForCell(cell.id) / maxDensity;
const densityProps: DensityProps = {
factor: unitDensityForCell(cell.id) / maxDensity
};
for (const model of this.state.models) {
model.setUniforms({densityFactor});
model.shaderInputs.setProps({density: densityProps});
}

super.draw(opts);
Expand Down
36 changes: 13 additions & 23 deletions modules/carto/src/layers/raster-layer-vertex.glsl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,6 @@ in vec4 instanceLineColors;

in vec3 instancePickingColors;

// Custom uniforms
uniform float opacity;
uniform bool extruded;
uniform bool stroked;
uniform bool isStroke;
uniform float coverage;
uniform float elevationScale;
uniform float widthScale;
uniform vec3 offset;

// Result
out vec4 vColor;
#ifdef FLAT_SHADING
Expand All @@ -29,18 +19,18 @@ out vec4 position_commonspace;

void main(void) {
// Rather than positioning using attribute, layout pixel grid using gl_InstanceID
vec2 common_position = offset.xy;
float scale = offset.z;
vec2 common_position = column.offset.xy;
float scale = column.widthScale; // Re-use widthScale prop to pass cell scale

int yIndex = - (gl_InstanceID / BLOCK_WIDTH);
int xIndex = gl_InstanceID + (yIndex * BLOCK_WIDTH);
common_position += scale * vec2(float(xIndex), float(yIndex));

vec4 color = isStroke ? instanceLineColors : instanceFillColors;
vec4 color = column.isStroke ? instanceLineColors : instanceFillColors;

// if alpha == 0.0 or z < 0.0, do not render element
float shouldRender = float(color.a > 0.0 && instanceElevations >= 0.0);
float cellWidth = coverage * scale;
float cellWidth = column.coverage * scale;

// Get position directly from quadbin, rather than projecting
// Important to set geometry.position before using project_ methods below
Expand All @@ -56,11 +46,11 @@ void main(void) {
// calculate stroke offset
float strokeOffsetRatio = 1.0;

if (extruded) {
elevation = instanceElevations * (positions.z + 1.0) / 2.0 * elevationScale;
} else if (stroked) {
float halfOffset = project_pixel_size(widthScale) / cellWidth;
if (isStroke) {
if (column.extruded) {
elevation = instanceElevations * (positions.z + 1.0) / 2.0 * column.elevationScale;
} else if (column.stroked) {
float halfOffset = project_pixel_size(column.widthScale) / cellWidth;
if (column.isStroke) {
strokeOffsetRatio -= sign(positions.z) * halfOffset;
} else {
strokeOffsetRatio -= halfOffset;
Expand All @@ -81,16 +71,16 @@ void main(void) {
DECKGL_FILTER_GL_POSITION(gl_Position, geometry);

// Light calculations
if (extruded && !isStroke) {
if (column.extruded && !column.isStroke) {
#ifdef FLAT_SHADING
position_commonspace = geometry.position;
vColor = vec4(color.rgb, color.a * opacity);
vColor = vec4(color.rgb, color.a * layer.opacity);
#else
vec3 lightColor = lighting_getLightColor(color.rgb, project.cameraPosition, geometry.position.xyz, geometry.normal);
vColor = vec4(lightColor, color.a * opacity);
vColor = vec4(lightColor, color.a * layer.opacity);
#endif
} else {
vColor = vec4(color.rgb, color.a * opacity);
vColor = vec4(color.rgb, color.a * layer.opacity);
}

DECKGL_FILTER_COLOR(vColor, geometry);
Expand Down
6 changes: 4 additions & 2 deletions modules/carto/src/layers/raster-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ export default class RasterLayer<DataT = any, ExtraProps = {}> extends Composite

const blockSize = data.blockSize ?? 0;
const [xOffset, yOffset, scale] = quadbinToOffset(tileIndex);
const offset = [xOffset, yOffset, scale / blockSize];
const offset = [xOffset, yOffset];
const lineWidthScale = scale / blockSize;

// Filled Column Layer
const CellLayer = this.getSubLayerClass('column', RasterColumnLayer);
Expand All @@ -118,7 +119,8 @@ export default class RasterLayer<DataT = any, ExtraProps = {}> extends Composite
data, // Pass through data for getSubLayerAccessor()
length: blockSize * blockSize
},
offset
offset,
lineWidthScale // Re-use widthScale prop to pass cell scale
}
);
}
Expand Down
Loading