0

I have an application that displays the northern lights on a map. I receive a lot of points that need to be rendered (2000+ points).

Here’s what the final result should look like: enter image description here

Since this puts a heavy load on the CPU, the map starts to lag.

That’s why I decided to offload the rendering task to the GPU and create a shader.

I’m not very familiar with shaders—here’s what I’ve managed to do so far.

#version 460 core
#include <flutter/runtime_effect.glsl>

uniform float uProbability;
uniform vec2 uSize;

out vec4 fragColor;

float radius = 10.0;

vec4 color1 = vec4(226.0/255.0, 255.0/255.0, 227.0/255.0, 0.2);
vec4 color2 = vec4(138.0/255.0, 245.0/255.0, 111.0/255.0, 0.3);
vec4 color3 = vec4(255.0/255.0, 255.0/255.0, 29.0/255.0, 0.7);
vec4 color4 = vec4(250.0/255.0, 137.0/255.0, 24.0/255.0, 0.8);
vec4 color5 = vec4(255.0/255.0, 67.0/255.0, 67.0/255.0, 0.8);

vec4 getColorForProb(float value) {
    if (value < 0.1) return color1;
    else if (value < 0.2) return color2;
    else if (value < 0.4) return color3;
    else if (value < 0.6) return color4;
    else return color5; 
}

void main() {
    vec2 pixelPos = FlutterFragCoord().xy;
    vec2 center = uSize * .5;
    float distance = length(pixelPos - center);
    

    float gradient = 1.0 - smoothstep(0.0, radius, distance);
    vec4 color = getColorForProb(uProbability);
    

    fragColor = vec4(color.rgb, color.a * gradient);
}

class _IntensityPainter extends CustomPainter {
  const _IntensityPainter(this.marker, this.zoom, this.shader);

  final FragmentShader shader;
  final AuroraMarker marker;
  final int zoom;

  double get baseBlurRadius => 5.0 / zoom;

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint();

    shader
      ..setFloat(0, marker.auroraProbability)
      ..setFloat(1, size.width)
      ..setFloat(2, size.height);
    canvas.drawCircle(
      Offset.zero,
      size.width / 2,
      paint..shader = shader,
    );
  }

  @override
  bool shouldRepaint(covariant _IntensityPainter oldDelegate) {
    return oldDelegate.marker != marker;
  }

Here’s how it looks now:

enter image description here

The problem is that when I try to set alpha < 1, the color starts to turn white. And I don’t have a blur radius.

Could you please suggest how to fix this?

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.