Pull to refresh

Comments 12

Шейдеры только в 13 Андроиде завезли, ниже их нет, так что конечно красиво, но ветвления логики что-то не заметно, кто соберёт на устройство ниже, поймает краш.

А у вас все хорошо работает, glsl вместо agls подхватился без проблем?

Да, работает хорошо, запускал как в эмуляторе, так и на физическом устройстве.

Я написал это приложение не просто на Jetpack Compose, а на Compose Multiplatform

Совсем запутали... Как понять что есть что?

Jetpack Compose - фреймворк для разработки под Андроид от Google. Вскоре после его релиза Jetbrains выпустили на его основе Compose Multiplatform - фреймворк, позволяющий запускать интерфейсы Jetpack Compose дополнительно в десктопных приложениях, iOS и в браузере. Управление состоянием, StateFlow, рендерер Skia те же. Подпробнее можно почитать тут: https://github.com/JetBrains/compose-multiplatform и в моей статье: https://habr.com/ru/companies/timeweb/articles/734818/

Они даже пару слов в язык добавили, все ради него.

Если вы про expect и actual - они доступны только при наличии KCP kotlin("multiplatform"). Любой желающий может добавить в свой проект на котлине новые ключевые слова, если напишет собственный плагин компиляции.

Да ладно, а чего же они аж в compose для android лежат без всяких плагинов? А давно у нас модификаторы языка без плагинов не собираются?

https://kotlinlang.org/docs/keyword-reference.html#modifier-keywords

Я так понимаю, что от Modifier.drawWithCache нету смысла, так как происходит постоянное изменение времени, а значит, что шейдеры пересоздаются на каждую перерисовку

(Промахнулся веткой, ответ на этот комментарий)

Согласно документации, drawWithCache вызывает лямбду когда изменился размер рисуемой области и/или состояние, которое читается из лямбды

В вашем случае, это сработает только между кадрами, если кадры будут рисоваться быстрее, чем вы изменяете переменную time

Можете print в консоль сделать и убедится, что у вас постоянно создаются новые шейдеры

Ну да, получается, что самое лучшее, что можно здесь сделать - это закешировать shaderBuilder:

actual fun Modifier.shaderEffect(shaderOption: ShaderOptions): Modifier = composed {
    val time by produceState(0f) {
        while (true) {
            withInfiniteAnimationFrameMillis {
                value = it / 1000f
            }
        }
    }
    val effect = remember(shaderOption) { RuntimeEffect.makeForShader(shaderOption.toShaderCode()) }
    val compositeShaderBuilder = remember(effect) { RuntimeShaderBuilder(effect) }
    Modifier.drawWithCache {
        compositeShaderBuilder.uniform(
            name = "iResolution",
            value1 = size.width,
            value2 = size.height
        )
        compositeShaderBuilder.uniform(
            "iTime",
            time
        )
        val shaderBrush = ShaderBrush(compositeShaderBuilder.makeShader())
        onDrawBehind {
            withTransform({ scale(scaleX = 1f, scaleY = -1f) }) {
                drawRect(shaderBrush)
            }
        }
    }
}

Тогда хотя бы выделения памяти под него не будет.

Это на примере десктопа, на андроиде будет чуть отличаться

Ещё, возможно, можно мигрировать это на Modifier.Node в Android реализации и получить еще прирост.

Sign up to leave a comment.