#pragma once #include #include #include namespace mbgl { namespace shaders { template <> struct ShaderSource { static constexpr const char* name = "HeatmapShader"; static const std::array attributes; static constexpr std::array instanceAttributes{}; static const std::array textures; static constexpr auto vertex = R"( struct VertexInput { @location(0) position: vec2, #ifndef HAS_UNIFORM_u_weight @location(1) weight: vec2, #endif #ifndef HAS_UNIFORM_u_radius @location(2) radius: vec2, #endif }; struct VertexOutput { @builtin(position) position: vec4, @location(0) weight: f32, @location(1) extrude: vec2, }; struct HeatmapDrawableUBO { matrix: mat4x4, extrude_scale: f32, weight_t: f32, radius_t: f32, pad1: f32, }; struct HeatmapEvaluatedPropsUBO { weight: f32, radius: f32, intensity: f32, padding: f32, }; struct GlobalIndexUBO { value: u32, pad: vec3, }; @group(0) @binding(1) var globalIndex: GlobalIndexUBO; @group(0) @binding(2) var drawableVector: array; @group(0) @binding(4) var props: HeatmapEvaluatedPropsUBO; const ZERO: f32 = 1.0 / 255.0 / 16.0; const GAUSS_COEF: f32 = 0.3989422804014327; @vertex fn main(in: VertexInput) -> VertexOutput { var out: VertexOutput; let drawable = drawableVector[globalIndex.value]; #ifdef HAS_UNIFORM_u_weight let weight = props.weight; #else let weight = unpack_mix_float(in.weight, drawable.weight_t); #endif #ifdef HAS_UNIFORM_u_radius let radius = props.radius; #else let radius = unpack_mix_float(in.radius, drawable.radius_t); #endif let pos = vec2(f32(in.position.x), f32(in.position.y)); let unscaled_extrude = fma(vec2(f32(in.position.x & 1), f32(in.position.y & 1)), vec2(2.0, 2.0), vec2(-1.0, -1.0)); let S = sqrt(-2.0 * log(ZERO / (max(weight, ZERO) * max(props.intensity, ZERO) * GAUSS_COEF))) / 3.0; let extrude = S * unscaled_extrude; let scaled_extrude = extrude * radius * drawable.extrude_scale; let base = floor(pos * 0.5); out.position = drawable.matrix * vec4(base + scaled_extrude, 0.0, 1.0); out.weight = weight; out.extrude = extrude; return out; } )"; static constexpr auto fragment = R"( struct FragmentInput { @location(0) weight: f32, @location(1) extrude: vec2, }; struct HeatmapEvaluatedPropsUBO { weight: f32, radius: f32, intensity: f32, padding: f32, }; const GAUSS_COEF: f32 = 0.3989422804014327; @group(0) @binding(4) var props: HeatmapEvaluatedPropsUBO; @fragment fn main(in: FragmentInput) -> @location(0) vec4 { #ifdef OVERDRAW_INSPECTOR return vec4(1.0, 1.0, 1.0, 1.0); #else let d = -0.5 * 3.0 * 3.0 * dot(in.extrude, in.extrude); let val = in.weight * props.intensity * GAUSS_COEF * exp(d); return vec4(val, 1.0, 1.0, 1.0); #endif } )"; }; } // namespace shaders } // namespace mbgl