Skip to content

Instantly share code, notes, and snippets.

@jmadaminov
Created February 23, 2023 06:14
Show Gist options
  • Save jmadaminov/bc9b75c95eea084e569b646b4e45ff88 to your computer and use it in GitHub Desktop.
Save jmadaminov/bc9b75c95eea084e569b646b4e45ff88 to your computer and use it in GitHub Desktop.
A modifier which can be used on a Box composable for fancy animated look - works only on Android 13
import android.graphics.Color
import android.graphics.RuntimeShader
import android.os.Build
import androidx.compose.animation.core.withInfiniteAnimationFrameMillis
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.ShaderBrush
import org.intellij.lang.annotations.Language
fun Modifier.btnShaderBg(bgColor: androidx.compose.ui.graphics.Color): Modifier = this.composed {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// produce updating time in seconds variable to pass into shader
val time by produceState(0f) {
while (true) {
withInfiniteAnimationFrameMillis {
value = it / 1000f
}
}
}
Modifier.drawWithCache {
val shader = RuntimeShader(SHADER)
val shaderBrush = ShaderBrush(shader)
shader.setFloatUniform("iResolution", size.width, size.height)
shader.setFloatUniform("iTime", time)
// Pass the color to support color space automatically
shader.setColorUniform(
"iColor",
Color.valueOf(bgColor.red, bgColor.green, bgColor.blue, bgColor.alpha)
)
onDrawBehind {
drawRect(shaderBrush)
}
}
} else {
Modifier.drawWithCache {
val gradientBrush = Brush.verticalGradient(listOf(bgColor, BtnMain2))
onDrawBehind {
drawRect(gradientBrush)
}
}
}
}
@Language("AGSL")
private val SHADER = """
uniform float2 iResolution;
uniform float iTime;
layout(color) uniform half4 iColor;
float calculateColorMultiplier(float yCoord, float factor) {
return step(yCoord, 1.0 + factor * 4.0) - step(yCoord, factor - 0.1);
}
float4 main(in float2 fragCoord) {
// Config values
const float speedMultiplier = 1.5;
const float waveDensity = 1.0;
const float loops = 50.0;
const float energy = 0.6;
// Calculated values
float2 uv = fragCoord / iResolution.xy;
float3 color = iColor.rgb;
float timeOffset = iTime * speedMultiplier;
float hAdjustment = uv.x * 4.3;
float3 loopColor = vec3(1.0 - color.r, 1.0 - color.g, 1.0 - color.b) * 2.5 / loops;
for (float i = 1.0; i <= loops; i += 1.0) {
float loopFactor = i * 0.1;
float sinInput = (timeOffset + hAdjustment) * energy;
float curve = sin(sinInput) * (2.0 - loopFactor) * 0.05;
float colorMultiplier = calculateColorMultiplier(uv.y, loopFactor);
color += loopColor * colorMultiplier * iColor.rgb * uv.y;
uv.y += curve;
}
return float4(color, 1.0);
}
""".trimIndent()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment