composer 不支持动态模糊,因其采用状态快照式渲染,不计算运动向量、不生成速度缓冲;可通过多层偏移叠加、opengl 自定义 shader 或 ffmpeg 补帧模拟高速摄影效果,但需规避性能陷阱。

Composer 本身不支持动态模糊(Motion Blur)参数,也没有内置的“高速摄影效果”开关——它压根不计算运动向量,也不生成速度缓冲(velocity buffer),所以任何想通过 Modifier.motionBlur 或类似 API 直接开启动态模糊的尝试,都会失败或返回未定义行为。
为什么 Composer 没有 motionBlur 参数
动态模糊依赖两个底层前提:物体在帧间的位移向量 + 摄像机快门时间建模。而 Composer 的渲染模型是“状态快照式”的:每帧只取当前 UI 树的最终布局、绘制指令和像素输出,不保留上一帧的位置/变换差值,也不暴露 z-depth 或 motion vector 纹理。这意味着:
-
Modifier.blur()是静态高斯模糊,无时间维度,无法响应速度变化 - 所有动画(
animate*AsState)插值发生在 CPU 层,不触发 GPU 级运动采样 - AndroidView / GLSurfaceView 中实现的自定义模糊 shader,必须自己算位移、传 uniform、做 temporal accumulation —— Composer 不参与也不感知
模拟高速摄影效果的可行路径
所谓“高速摄影感”,本质是强运动拖尾 + 瞬时定格 + 低帧率错觉。Composer 无法原生做到,但可通过组合手段逼近视觉效果:
- 用
Animatable驱动Modifier.graphicsLayer(alpha = 0.3f, translationX = x),手动叠加多个偏移+半透明图层(最多3–4层),模拟拖影 - 在
AndroidView内部用 OpenGL 实现基于帧差的 motion vector 采样,再 feed 给 fragment shader 做 directional blur —— 此时模糊方向/长度由前后帧 UV 差决定 - 导出阶段补帧:用 FFmpeg 对 Composer 输出的 30fps 视频做
-vf minterpolate=fps=60,再加tblend=all_mode=average混合相邻帧,伪造拖尾(适合离线渲染)
容易被忽略的性能陷阱
哪怕走自定义 OpenGL 路径,也得盯紧三件事:
- 每帧生成 motion vector texture 必须用
glReadPixels同步读取,会卡 GPU 管线;更优解是用transform feedback或compute shader异步产出,但 Compose 层无法调度 - 拖影图层叠加超过 4 层,低端 Android 设备的
SurfaceFlinger合成开销陡增,掉帧比模糊本身还严重 - FFmpeg 补帧方案里,
minterpolate默认用mi_mode=mci,对快速平移物体易产生鬼影;必须显式设mi_mode=dup或mi_mode=blend并调小mcps
真正难的不是“怎么模糊”,而是“怎么让模糊只出现在该动的地方、动得有多快、持续几帧”——这些判断逻辑不在 Composer,而在你能否把运动语义从 UI 描述中提取出来,喂给底层图形管线。











