GPU-accelerated weather effects for Android Compose, powered by AGSL.
- Runs entirely on the GPU via AGSL shaders (API 33+)
- Transparent overlay — renders on top of any content
- Battery Saver automatically downgrades quality to
LOW; system "Remove animations" setting disables animated effects - No-op on unsupported devices (< API 33) with a fallback option
Add to your version catalog (libs.versions.toml):
[versions]
aether = "0.1.2"
[libraries]
aether = { module = "com.ms-square:aether", version.ref = "aether" }Then add the dependency to your module's build.gradle.kts:
dependencies {
implementation(libs.aether)
}// Apply rain as an overlay
Box(
modifier = Modifier
.fillMaxSize()
.aetherOverlay(Rain())
) {
// your content here
}aetherOverlay also accepts a qualityPreset parameter (LOW, MEDIUM, HIGH) to control rendering quality. Defaults to HIGH.
val rain = remember {
Rain(
intensity = 3, // 1–5 layers
speed = 1.0f, // fall speed multiplier
dropLength = 1.0f, // streak length multiplier
colors = RainColors(), // core, halo, and atmospheric tint
wind = Wind.LightBreeze
)
}Presets: Rain.light(), Rain.moderate(), Rain.heavy(), Rain.storm()
val snow = remember {
Snow(
density = 3, // 1–5 layers
speed = 1.0f, // fall speed multiplier
flakeSize = 1.0f, // size multiplier
wind = Wind.Calm
)
}Presets: Snow.light(), Snow.moderate(), Snow.heavy(), Snow.blizzard()
val clouds = remember {
Clouds(
coverage = 0.30f, // 0 = wispy, 1 = overcast
speed = 1.0f // drift speed multiplier
)
}Presets: Clouds.wispy(), Clouds.partlyCloudy(), Clouds.overcast()
val lightning = remember {
LightningFlash(
brightness = 1.5f, // peak brightness multiplier
boltCount = 3, // 1–5 root bolts
forkIntensity = 0.4f // fork pattern intensity (0–1)
)
}
val scope = rememberCoroutineScope()
// Trigger a flash
scope.launch { lightning.flash(durationMs = 300) }Stack multiple effects by chaining modifiers:
val rain = remember { Rain() }
val lightning = remember { LightningFlash() }
Box(
modifier = Modifier
.fillMaxSize()
.aetherOverlay(rain)
.aetherOverlay(lightning)
)| Requirement | |
|---|---|
| Minimum SDK | 26 (Android 8.0) |
| Effects active | 33+ (Android 13 — AGSL required) |
On devices below API 33, aetherOverlay is a no-op. Use the fallback parameter to provide an alternative:
Modifier.aetherOverlay(
effect = Clouds(),
fallback = Modifier.background(Color.Gray)
)You can also check at runtime:
if (isAetherAvailable()) {
// AGSL effects supported
}The sample app showcases all effects with interactive controls and a Google Maps overlay demo.
To run it:
- Sign up with Google Maps Platform and create a project with the Maps SDK for Android enabled
- Obtain an API key (follow the API key instructions if you're new to the process)
- Create a
secrets.propertiesfile in the project root:MAPS_API_KEY=YOUR_GOOGLE_MAPS_API_KEY - Build and install:
./gradlew :sample:installDebug
Note: The effects gallery and playground work without a Maps API key. The key is only required for the Map tab.
See CHANGELOG.md for release history.

