Skip to content

Commit

Permalink
CARTO: split 2D gaussian blur into 1 1D passes (#8874)
Browse files Browse the repository at this point in the history
  • Loading branch information
felixpalmer authored and donmccurdy committed May 23, 2024
1 parent 8bb5ed5 commit cc3bf4b
Showing 1 changed file with 21 additions and 6 deletions.
27 changes: 21 additions & 6 deletions modules/carto/src/layers/heatmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const glsl = (s: TemplateStringsArray) => `${s}`;

const fs = glsl`\
uniform heatmapUniforms {
vec2 delta;
float radiusPixels;
vec2 colorDomain;
vec3 color1;
Expand Down Expand Up @@ -57,11 +58,15 @@ vec3 colorGradient(float value) {
}
const vec3 SHIFT = vec3(1.0, 256.0, 256.0 * 256.0);
vec4 pack(float value) {
return vec4(mod(vec3(value, floor(value / SHIFT.yz)), 256.0), 255.0) / 255.0;
}
float unpack(vec3 color) {
return 255.0 * dot(color, SHIFT);
}
vec4 heatmap_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) {
bool firstPass = (heatmap.delta.y < 0.5);
float accumulator = 0.0;
// Randomize the lookup values to hide the fixed number of samples
Expand All @@ -70,22 +75,24 @@ vec4 heatmap_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) {
// Gaussian normalization parameters
const float sigma = SUPPORT / 3.0;
const float a = -0.5 / (sigma * sigma);
const float w0 = 1.0 / (2.0 * 3.141592653589793 * sigma * sigma); // 2D normalization
const float w0 = 0.3989422804014327 / sigma; // 1D normalization
for (float t = -SUPPORT; t <= SUPPORT; t++) {
for (float s = -SUPPORT; s <= SUPPORT; s++) {
vec2 percent = (vec2(s, t) + offset - 0.5) / SUPPORT;
vec2 percent = (t * heatmap.delta + offset - 0.5) / SUPPORT;
vec2 delta = percent * heatmap.radiusPixels / texSize;
vec4 offsetColor = texture(source, texCoord + delta);
// Unpack float
float value = unpack(offsetColor.rgb);
// Gaussian
float weight = w0 * exp(a * (s * s + t * t));
float weight = w0 * exp(a * t * t);
accumulator += value * weight;
}
if (firstPass) {
return pack(accumulator);
}
// Apply domain
Expand Down Expand Up @@ -135,6 +142,7 @@ export type HeatmapProps = {
};

export type HeatmapUniforms = {
delta?: [number, number];
radiusPixels?: number;
colorDomain?: [number, number];
color1?: [number, number, number];
Expand All @@ -149,6 +157,7 @@ export type HeatmapUniforms = {
export const heatmap: ShaderPass<HeatmapProps, HeatmapUniforms> = {
name: 'heatmap',
uniformPropTypes: {
delta: {value: [0, 1]},
radiusPixels: {value: 20, min: 0, softMax: 100},
colorDomain: {value: [0, 1]},
color1: {value: [0, 0, 0]},
Expand All @@ -160,6 +169,7 @@ export const heatmap: ShaderPass<HeatmapProps, HeatmapUniforms> = {
opacity: {value: 1, min: 0, max: 1}
},
uniformTypes: {
delta: 'vec2<f32>',
radiusPixels: 'f32',
colorDomain: 'vec2<f32>',
color1: 'vec3<f32>',
Expand All @@ -172,13 +182,15 @@ export const heatmap: ShaderPass<HeatmapProps, HeatmapUniforms> = {
},
getUniforms: opts => {
const {
delta = [1, 0],
colorRange = defaultColorRange,
radiusPixels = 20,
colorDomain = [0, 1],
opacity = 1
} = opts as HeatmapProps;
} = opts as HeatmapProps & {delta: [number, number]};
const [color1, color2, color3, color4, color5, color6] = colorRange;
return {
delta,
color1,
color2,
color3,
Expand All @@ -192,5 +204,8 @@ export const heatmap: ShaderPass<HeatmapProps, HeatmapUniforms> = {
},
dependencies: [random],
fs,
passes: [{sampler: true}]
passes: [
{sampler: true, uniforms: {delta: [1, 0]}},
{sampler: true, uniforms: {delta: [0, 1]}}
]
};

0 comments on commit cc3bf4b

Please sign in to comment.