Skip to content

perf: draw rain, clouds, and the wavefront with less work - #632

Merged
lowrt merged 5 commits into
mainfrom
perf/cheaper-drawing
Nov 1, 2026
Merged

lowrt merged 5 commits into
mainfrom
perf/cheaper-drawing

Conversation

@whes1015

@whes1015 whes1015 commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

這個 PR 做了什麼

畫面該少算的少算。地震波前該畫的時候,畫的是當下的範圍,不是上一拍留下的半徑。

正式程式碼,五則 commit:

  • 首頁卡片雨水。求解從 5 步改成 3 步,累積緩衝用半解析度(像素約四分之一),模糊的 σ 跟著這個比例縮。card_water_field.dart、rain_on_card.dart
  • 暴雨與雪的粒子池降一檔。高階雨 1792 → 1472,高階雪 900 → 739。低階雨 1024、低階雪 640 沒有改。小雨的比例也沒有改。precipitation_field.dart、weather_sky_background.dart
  • 玻璃上的雨先 bake 成 256×256 的覆蓋圖,折射那一拍再去取樣。rain_on_glass.dart、shaders/weather/rain_on_glass.frag
  • 雲的太陽、地面、環境光在每一幀之前就算好(含增益、暖色混合、霧),shader 不再每幀去取 sky LUT。sky_clouds.dart、weather_sky_painter.dart、shaders/cloud/clouds.frag
  • 地震波前。移動不到一個螢幕像素就不重傳 GeoJSON;過了門檻就傳當下半徑,縮小一個像素以上也傳較小的那一圈。圓從 64 邊改成 48 邊(弓高約半徑的 0.21%,上一版 0.12%)。低階手機仍依 wavefrontTick 每 200 ms 醒一次,像素門檻疊在這上面,沒有取代它。進行中的寫入仍會被跳過,那是 main 上已有的行為。框選覆蓋改成第一次立刻算、之後每 200 ms。已取消的速報不畫、也不把閘門撐著。樣式重載會清掉上一組環。wavefront_cadence.dart、geo_circle.dart、rts_layer.dart、report_replay_page.dart

測試與正式程式碼分開:

  • 卡片雨水的步數與半解析度尺寸、粒子池常數、雲的烘焙公式、玻璃覆蓋圖是 256² 且不是全黑
  • shader uniform:雲少一個 sampler、多 12 個烘焙浮點;玻璃雨多 uMode、sampler 變 2
  • 波前:次像素停住、之後補上當下半徑、縮小要傳、zoom 缺失或不是有限數就傳、新的 id 就傳、框選 200 ms。圖層測試在 zoom 14 仍要求每一拍都寫、低階 5 Hz、寫入還沒回來就合併;zoom 7 的 160 ms 不該多傳一次。取消的速報不進集合
  • preview tag 的場景改成走同一條烘焙。預設的 tool/dev/test.sh 不會跑它們

沒有做、也刻意不做:定位點的脈衝、雲的雙線性取樣、走時表、日出、星圖。沒有在 iOS 或 Android 實機上看過畫面,也沒有量 FPS 或耗電;上面的數字是程式裡的常數,不是實機量測。EEW 推估公式沒有動,eew_estimator_test.dart 的 golden 沒有改。pubspec.lock 裡本機 MapLibre 的絕對路徑沒有進任何一則 commit。

相關 issue

開 PR 前搜過 gh issue list --state all --search 'rain OR wavefront OR shader OR 發熱 OR 波前'。沒有對應的 issue。

怎麼驗

本機在推之前:

  • tool/dev/analyze.sh 通過
  • tool/check/commits.sh origin/main..HEAD 通過(5 則)
  • 推送時 pre-push 跑的 tool/check.sh 通過:格式、analyze、workflow、l10n、lockfile、完整測試 3636 通過(另有 6 個跳過)。CI 跑的是 Linux,本機是 Darwin
  • 下列測試在拆 commit 之前另外跑過,都通過:
tool/dev/test.sh \
  test/features/home/weather_sky/card_water_field_test.dart \
  test/features/home/weather_sky/precipitation_field_test.dart \
  test/features/home/weather_sky/rain_on_glass_field_test.dart \
  test/features/home/presentation/widgets/weather_sky/sky_clouds_test.dart \
  test/shaders/weather_sky_shader_test.dart \
  test/shared/map/wavefront_cadence_test.dart \
  test/shared/map/geo_circle_test.dart \
  test/features/map/presentation/layers/rts_layer_eew_push_test.dart \
  test/features/map/presentation/layers/rts_layer_box_push_test.dart \
  test/features/earthquake/presentation/pages/report_replay_page_test.dart

回放那兩則 tier 測試只鎖「次像素的波前不會每一拍都重畫」。回放時鐘是 Stopwatch,tester.pump 不會把波往前推,所以它不再數 60 Hz 和 5 Hz。頻率改由 rts_layer_eew_push_test.dart 在 zoom 14 鎖:高階每一拍、低階一秒五次。

實機還沒看。用 tool/run.sh 開起來之後:

  • 首頁:卡片上的雨、大雨、大雪、玻璃上的雨、從白天到晚上的雲。看起來應和之前同一種天氣,不該少一塊或閃一下
  • 強震監視器有速報時:拉遠,波前不該每 16 ms 重畫一次;拉近到一步超過一個像素,圈要跟著當下半徑走,不能停在比較小或比較大的舊圈。已取消的速報不該留著圈
  • 報告回放同樣看波前。低階手機仍約每 200 ms 醒一次,那是原本的 wavefrontTick
  • 預覽 shader 預設不跑。要看的話:tool/dev/test.sh --tags preview test/shaders/preview_render_test.dart test/shaders/rain_on_glass_test.dart

安全關鍵的部分是波前半徑,不是推估。推估器沒改。半徑由 wavefrontUploadDue 決定:沒過一個像素就沿用上一圈,過了就用呼叫當下的半徑(縮小也一樣)。圖層測試用會跟著 FakeAsync 走的時鐘,避免 DateTime.now() 在假時間裡凍結、門檻看起來永遠通過。

檢查清單

  • tool/check/commits.sh origin/main..HEAD 通過
    —— commit 訊息就是更新日誌,格式見 commit.md
  • 一個 commit 一件事(這條 gate 驗不了,靠自己和 review)
  • mise exec -- flutter analyze 與 mise exec -- flutter test 通過
    —— 實際跑的是 tool/dev/analyze.sh 與 pre-push 的 tool/check.sh(完整測試 3636 通過)。沒有直接打 mise exec
  • 新的使用者可見字串都走 AppLocalizations,沒有寫死
  • CI 全部通過(gh pr checks:每一項都是 pass 或 skipped)—— 沒過不能合併,
    見 pr.md
    —— build、Android、iOS、code-review、changes、codecov/project、codecov/patch 都是 pass
  • 有 UI 變更的話:用的是 AppSpacing / AppRadius / AppMotion,
    深色模式看過,文字對比度可接受
    —— 沒有改版面 tokens。外觀是雨、雲、波前的繪製量,還沒在實機對過,深色模式也還沒看

@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.49749% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 94.50%. Comparing base (703bdb4) to head (d2607d6).

Files with missing lines Patch % Lines
...resentation/widgets/weather_sky/rain_on_glass.dart 98.18% 1 Missing ⚠️

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@lowrt lowrt added this to the v26.4 milestone Oct 20, 2026
@YinCheng0106 YinCheng0106 added android Issues or pull requests related to the Android platform. ios Issues or pull requests related to the iOS platform. labels Oct 23, 2026
@PiscesXD
PiscesXD force-pushed the perf/cheaper-drawing branch from 8bc8c29 to 9041729 Compare October 30, 2026 16:17
@PiscesXD

Copy link
Copy Markdown
Member

LGTM

Platform: all

Optimization(zh-Hant): 首頁卡片上的雨水少算幾步,看起來一樣
Optimization(en-US): rain on the home card takes fewer steps and looks the same
Platform: all

Optimization(zh-Hant): 大雨和大雪少畫一些粒子,看起來一樣
Optimization(en-US): heavy rain and snow draw fewer particles and look the same
Platform: all

Optimization(zh-Hant): 玻璃上的雨滴改成先畫成一張小圖,看起來一樣
Optimization(en-US): raindrops on the glass are drawn from one small picture and look the same
Platform: all

Optimization(zh-Hant): 雲的顏色改在每一幀之前算好,看起來一樣
Optimization(en-US): cloud colors are worked out before each frame and look the same
Platform: all

Optimization(zh-Hant): 地震波前不到一個像素就不重畫,畫出來的是當下的範圍
Optimization(en-US): an earthquake wavefront is redrawn only after it moves a pixel, at its current size
@lowrt
lowrt force-pushed the perf/cheaper-drawing branch from 9041729 to d2607d6 Compare November 1, 2026 05:02
@lowrt
lowrt merged commit 3e518f0 into main Nov 1, 2026
@lowrt
lowrt deleted the perf/cheaper-drawing branch November 1, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

android Issues or pull requests related to the Android platform. ios Issues or pull requests related to the iOS platform. size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants