A Hello, World AGSL shader that reacts to audio amplitude (see Audio processing).
Hello, reactive AGSL
package io.orllewin.shaders.ui.shaders
import android.graphics.RuntimeShader
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.ShaderBrush
/**
* Hello-world audio-reactive shader. A square that bounces in time with audio
* [amplitude] (0f..1f).
*
* Requires API 33+
*/
@Composable
fun HelloShadersAGSL(
amplitude: Float = 0f,
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
HelloShaders(amplitude)
}
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@Composable
private fun HelloShaders(amplitude: Float) {
val shader = remember { RuntimeShader(HELLO_SHADERS_SRC) }
val brush = remember { ShaderBrush(shader) }
Spacer(
modifier = Modifier
.fillMaxSize()
.drawBehind {
shader.setFloatUniform("iResolution", size.width, size.height)
shader.setFloatUniform("amplitude", amplitude * 1.5f)
drawRect(brush = brush, size = size)
}
)
}
private const val HELLO_SHADERS_SRC = """
uniform float2 iResolution;
uniform float amplitude;
half4 main(float2 fragCoord) {
// Centre of the screen, in pixels.
float centerX = iResolution.x * 0.5;
float centerY = iResolution.y * 0.5;
// Square half-size, in pixels. 100px (silent) to 500px (loud).
float halfSize = 100.0 + amplitude * 400.0;
// The four edges of the square, in pixels.
float left = centerX - halfSize;
float right = centerX + halfSize;
float top = centerY - halfSize;
float bottom = centerY + halfSize;
// Line thickness (pixels)
float thickness = 4.0;
float x = fragCoord.x;
float y = fragCoord.y;
// Collision detection
bool onLeftLine = abs(x - left) < thickness && y > top && y < bottom;
bool onRightLine = abs(x - right) < thickness && y > top && y < bottom;
bool onTopLine = abs(y - top) < thickness && x > left && x < right;
bool onBottomLine = abs(y - bottom) < thickness && x > left && x < right;
if (onLeftLine || onRightLine || onTopLine || onBottomLine) {
return half4(1.0, 1.0, 1.0, 1.0);
}
return half4(0.0, 0.0, 0.0, 1.0);
}
"""