Skip to content

Commit 46faa82

Browse files
feat(android): add AGSL liquid glassmorphism shader and 3D parallax scroll modifiers
1 parent 3125c44 commit 46faa82

2 files changed

Lines changed: 89 additions & 0 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.bytecats.metanoia.ui.effects
2+
3+
import android.graphics.RenderEffect
4+
import android.graphics.RuntimeShader
5+
import android.os.Build
6+
import androidx.annotation.RequiresApi
7+
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.draw.drawWithContent
9+
import androidx.compose.ui.graphics.asComposeRenderEffect
10+
import androidx.compose.ui.graphics.graphicsLayer
11+
import org.intellij.lang.annotations.Language
12+
13+
@Language("AGSL")
14+
const val LIQUID_GLASS_SHADER = """
15+
uniform shader composable;
16+
uniform float2 u_resolution;
17+
uniform float u_time;
18+
uniform float u_aberration;
19+
20+
half4 main(float2 fragCoord) {
21+
float2 uv = fragCoord / u_resolution;
22+
23+
// Liquid wave displacement offset
24+
float wave = sin(uv.x * 12.0 + u_time * 2.0) * cos(uv.y * 12.0 + u_time * 1.5) * 0.008;
25+
26+
// Chromatic aberration (RGB shift)
27+
half4 colorR = composable.eval(fragCoord + float2(wave + u_aberration, wave));
28+
half4 colorG = composable.eval(fragCoord + float2(wave, wave));
29+
half4 colorB = composable.eval(fragCoord + float2(wave - u_aberration, wave));
30+
31+
// Tokyo Night ambient tint
32+
half3 tint = half3(0.48, 0.63, 0.97) * 0.12; // #7aa2f7
33+
34+
return half4(colorR.r + tint.r, colorG.g + tint.g, colorB.b + tint.b, colorG.a);
35+
}
36+
"""
37+
38+
/**
39+
* Applies an AGSL (Android Graphics Shader Language) liquid glassmorphism shader effect
40+
* on Android 13+ (API 33+), with graceful fallback for earlier Android versions.
41+
*/
42+
fun Modifier.agslLiquidGlass(
43+
time: Float,
44+
resolutionX: Float,
45+
resolutionY: Float,
46+
aberration: Float = 4f
47+
): Modifier = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
48+
this.graphicsLayer {
49+
val shader = RuntimeShader(LIQUID_GLASS_SHADER)
50+
shader.setFloatUniform("u_resolution", resolutionX.coerceAtLeast(1f), resolutionY.coerceAtLeast(1f))
51+
shader.setFloatUniform("u_time", time)
52+
shader.setFloatUniform("u_aberration", aberration)
53+
renderEffect = RenderEffect.createRuntimeShaderEffect(shader, "composable").asComposeRenderEffect()
54+
}
55+
} else {
56+
this
57+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.bytecats.metanoia.ui.effects
2+
3+
import androidx.compose.foundation.ScrollState
4+
import androidx.compose.foundation.lazy.LazyListState
5+
import androidx.compose.ui.Modifier
6+
import androidx.compose.ui.graphics.graphicsLayer
7+
8+
/**
9+
* Applies a smooth vertical 3D depth parallax effect based on scroll position.
10+
*/
11+
fun Modifier.parallaxScroll(
12+
scrollState: ScrollState,
13+
speed: Float = 0.3f
14+
): Modifier = this.graphicsLayer {
15+
translationY = scrollState.value * speed
16+
rotationX = (scrollState.value * 0.02f).coerceIn(-10f, 10f)
17+
}
18+
19+
/**
20+
* Applies a smooth vertical 3D depth parallax effect for LazyColumn items based on LazyListState.
21+
*/
22+
fun Modifier.parallaxLazyItem(
23+
lazyListState: LazyListState,
24+
index: Int,
25+
speed: Float = 0.25f
26+
): Modifier = this.graphicsLayer {
27+
val firstVisibleIndex = lazyListState.firstVisibleItemIndex
28+
val firstVisibleScrollOffset = lazyListState.firstVisibleItemScrollOffset
29+
30+
val diff = (index - firstVisibleIndex)
31+
translationY = (diff * 20f - firstVisibleScrollOffset * speed)
32+
}

0 commit comments

Comments
 (0)