drawStars function

void drawStars(
  1. Canvas canvas,
  2. Size size,
  3. double rotation,
  4. double time,
)

📲 Draw Stars

We draw this starfield canvas - on the Canvas size - with a size rotation - and a rotation around center time - at a specific time

It fills the canvas

Implementation

void drawStars(Canvas canvas, Size size, double rotation, double time) {
  /// 📷 Creates a 140 degree projection matrix for our size,
  /// with a near of 0 and a far of 1
  /// and rotates around the Z axis by rotation degrees
  final projection = vector.makePerspectiveMatrix(
      140, size.width / size.height, 0, 1)
    ..rotateZ(rotation);

  /// 🧮 Generates a "page" of stars (back to front) of varying opacities
  /// We draw pages to minimize draw calls
  /// E.g.
  ///   1 Draw Call = Single Paint, all stars look the same
  ///   1 Draw Call for 1,000 stars = slow, inefficient
  ///   Solution: Create kSteps/pages and draw each page with a common
  ///   paint back to front (painters algorithm)
  ///   This allows me to artistically handle distance variations
  ///   without tanking performance.

  final intervals = List.generate(kSteps, (idx) => idx / kSteps.toDouble());
  for (final interval in intervals) {
    /// 🎨 Generate star color based on the current page
    /// We fade the opacity with distance to camera
    ///
    /// We also adjust the size based on distance (between 1-2 px)
    _starsPaint
      ..color = Colors.white.withOpacity(1 - interval)
      ..strokeWidth = (1 - interval) + 1.5;

    // 🖌️ Draw the points
    canvas.drawPoints(
        PointMode.points,
        _stars
            // ✂️ where star Z is in current interval
            .where((star) => star
                .zForTime(time)
                .chain((z) => z > interval && z < (interval + kStepSize)))
            // 📺 Convert this Star into a Screen Space Offset
            .map((star) => star
                .project(time, projection) // Project to screen space
                .translate(
                    0.5, 0.5) // Transform it from -0.5->0.5 range to 0-1 range
                .scale(size.width,
                    size.height)) // Scale it from 0-1 range to canvas size
            //Creates a List<Offset> to draw, from all stars
            .toList(),
        _starsPaint);
  }
}