Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 54 additions & 33 deletions JetLagged/app/src/main/java/com/example/jetlagged/Background.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,58 +19,79 @@ package com.example.jetlagged
import android.graphics.Color
import android.graphics.RuntimeShader
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.animation.core.withInfiniteAnimationFrameMillis
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.mutableFloatStateOf
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 androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.node.DrawModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import com.example.jetlagged.ui.theme.White
import com.example.jetlagged.ui.theme.Yellow
import com.example.jetlagged.ui.theme.YellowVariant
import kotlinx.coroutines.launch
import org.intellij.lang.annotations.Language

fun Modifier.yellowBackground(): 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) {
private data object YellowBackgroundElement : ModifierNodeElement<YellowBackgroundNode>() {
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun create() = YellowBackgroundNode()
override fun update(node: YellowBackgroundNode) {
}
}

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
private class YellowBackgroundNode : DrawModifierNode, Modifier.Node() {

private val shader = RuntimeShader(SHADER)
private val shaderBrush = ShaderBrush(shader)
private val time = mutableFloatStateOf(0f)

init {
shader.setColorUniform(
"color",
Color.valueOf(Yellow.red, Yellow.green, Yellow.blue, Yellow.alpha)
)
}

override fun ContentDrawScope.draw() {
shader.setFloatUniform("resolution", size.width, size.height)
shader.setFloatUniform("time", time.floatValue)
drawRect(shaderBrush)
drawContent()
}

override fun onAttach() {
coroutineScope.launch {
while (true) {
withInfiniteAnimationFrameMillis {
value = it / 1000f
time.floatValue = it / 1000f
}
}
}
Modifier.drawWithCache {
val shader = RuntimeShader(SHADER)
val shaderBrush = ShaderBrush(shader)
shader.setFloatUniform("iResolution", size.width, size.height)
// Pass the color to support color space automatically
shader.setColorUniform(
"iColor",
Color.valueOf(Yellow.red, Yellow.green, Yellow.blue, Yellow.alpha)
)
onDrawBehind {
shader.setFloatUniform("iTime", time)
drawRect(shaderBrush)
}
}
}
}

fun Modifier.yellowBackground(): Modifier =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
this.then(YellowBackgroundElement)
} else {
Modifier.drawWithCache {
drawWithCache {

val gradientBrush = Brush.verticalGradient(listOf(Yellow, YellowVariant, White))
onDrawBehind {
drawRect(gradientBrush)
}
}
}
}

@Language("AGSL")
val SHADER = """
uniform float2 iResolution;
uniform float iTime;
layout(color) uniform half4 iColor;
uniform float2 resolution;
uniform float time;
layout(color) uniform half4 color;

float calculateColorMultiplier(float yCoord, float factor) {
return step(yCoord, 1.0 + factor * 2.0) - step(yCoord, factor - 0.1);
Expand All @@ -84,23 +105,23 @@ val SHADER = """
const float energy = 0.6;

// Calculated values
float2 uv = fragCoord / iResolution.xy;
float3 color = iColor.rgb;
float timeOffset = iTime * speedMultiplier;
float2 uv = fragCoord / resolution.xy;
float3 rgbColor = color.rgb;
float timeOffset = time * speedMultiplier;
float hAdjustment = uv.x * 4.3;
float3 loopColor = vec3(1.0 - color.r, 1.0 - color.g, 1.0 - color.b) / loops;
float3 loopColor = vec3(1.0 - rgbColor.r, 1.0 - rgbColor.g, 1.0 - rgbColor.b) / 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) * (1.0 - loopFactor) * 0.05;
float colorMultiplier = calculateColorMultiplier(uv.y, loopFactor);
color += loopColor * colorMultiplier;
rgbColor += loopColor * colorMultiplier;

// Offset for next loop
uv.y += curve;
}

return float4(color, 1.0);
return float4(rgbColor, 1.0);
}
""".trimIndent()