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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.