Skip to content

可编程着色器 (AGSL Shaders)

源:Compose 中的自定义着色器

从 Android 13 (API 33) 开始,Android 图形管线支持 AGSL (Android Graphics Shading Language)。Compose 提供了极简的 API 来使用它。

兼容性

AGSL 仅在 Android 13+ 上原生支持。对于低版本,你可以使用第三方库(如 Rikka)或降级为普通的 Canvas 绘制。

1. 编写 AGSL 代码

AGSL 的语法与 GLSL (OpenGL ES 着色语言) 非常相似。

kotlin
// 定义一个简单的“色差偏移”着色器
const val SHADER_SRC = """
    uniform shader composable; // 输入的图像内容
    uniform float2 size;       // 图像尺寸
    uniform float time;        // 时间变量

    half4 main(float2 fragCoord) {
        // 计算偏移量
        float offset = sin(time + fragCoord.y * 0.05) * 10.0;
        
        // 分别采样 R, G, B 通道,产生错位
        half4 color = composable.eval(fragCoord);
        color.r = composable.eval(fragCoord + float2(offset, 0.0)).r;
        color.b = composable.eval(fragCoord - float2(offset, 0.0)).b;
        
        return color;
    }
"""

2. 创建 RuntimeShader

kotlin
val runtimeShader = remember { RuntimeShader(SHADER_SRC) }

3. 应用于 GraphicsLayer

使用 RenderEffect 将着色器应用到任何 Composable 上(包括图片、文字甚至复杂的布局)。

kotlin
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@Composable
fun GlitchEffectImage() {
    val time by rememberInfiniteTransition().animateFloat(
        initialValue = 0f,
        targetValue = 6.28f, // 2*PI
        animationSpec = infiniteRepeatable(tween(1000))
    )

    Image(
        painter = painterResource(R.drawable.hero),
        contentDescription = null,
        modifier = Modifier
            .fillMaxSize()
            .graphicsLayer {
                // 更新 Uniform 变量
                runtimeShader.setFloatUniform("size", size.width, size.height)
                runtimeShader.setFloatUniform("time", time)
                
                // 应用 RenderEffect
                renderEffect = RenderEffect
                    .createRuntimeShaderEffect(runtimeShader, "composable")
                    .asComposeRenderEffect()
            }
    )
}

4. 常见用途

  • 动态模糊 (Blur)
  • 噪点与颗粒感 (Grain)
  • 水波纹 (Ripple)
  • 全息效果 (Holographic)