jetpack compose 不支持深度图输入与景深虚化,因其渲染管线缺失深度缓冲、无 fragment shader 接口、modifier 无法感知像素级距离;唯一可行路径是通过 androidview 嵌入 opengl,在着色器中绑定颜色与深度纹理并按深度值动态计算模糊半径。

Jetpack Compose 本身不支持深度图(Depth Map)输入或解析,也没有任何 API 能接收、采样或驱动基于深度图的景深虚化效果。 所有在 Compose UI 层尝试“用深度图做景深”的方案,都会因渲染管线缺失深度缓冲、无 fragment shader 接口、Modifier 不可感知像素级距离而失败。
Compose 里根本读不到深度图
深度图是灰度图像,每个像素值代表该位置到相机的距离。但 Compose 的 Image、AsyncImage 或 Canvas 绘制都只把图当普通位图处理:Bitmap 或 Painter 不携带深度语义;drawImage() 不提供 uv 坐标到深度值的映射能力;Modifier.drawBehind 无法访问像素原始深度数据。你传进一张 PNG 深度图,Compose 只认它是个“带灰度的图”,不是“可计算的深度场”。
AndroidView + OpenGL 是唯一可行路径
真要让深度图起作用,必须绕过 Compose 渲染层,在其下方用原生能力合成:
- 用
AndroidView嵌入GLSurfaceView或TextureView - 在 OpenGL 着色器中同时绑定两张纹理:
colorTex(前景图)和depthTex(16-bit grayscale 深度图) - fragment shader 中写
float depth = texture2D(depthTex, uv).r;,再用它缩放模糊半径:gaussianBlur(colorTex, uv, baseRadius * (1.0 - depth)) - 通过
Animatable驱动uBlurRadiusuniform,实现动画插值
注意:深度图必须与前景图严格像素对齐,否则出现“伪影撕裂”;且深度值范围需归一化(0–1),不能直接用 Photoshop 导出的反相灰度(白=远)——得先 invert 再除以 255。
RenderEffect.createBlurEffect 不能替代深度图
有人误以为 Android 12+ 的 RenderEffect.createBlurEffect 能配合深度图使用,实际不能:
-
RenderEffect只接受一个模糊半径float,不接受纹理或采样逻辑 - 它作用于整个
View的绘制输出,无法按像素查深度、做非线性模糊衰减 - 在低端机上半径 >25 会崩溃,且开启后该区域失去触摸响应
- 即使你用
AndroidView包裹一个View并设RenderEffect,它仍是均一模糊,和深度无关
别在 Compose 里硬套影视术语
“景深”“焦点距离”“光圈大小”这些词在 SOLIDWORKS Composer 或 Photoshop 里有明确物理含义和参数接口,但在 Jetpack Compose 中没有对应概念。它的 zIndex 是绘制顺序,shadow 是阴影高度,Modifier.clip 是裁剪形状——都不是深度感知的视觉通道。想突出某个组件?用 zIndex 提升 + shadow(elevation = 8.dp) + 半透明背景遮罩,比强行模糊更稳定、更可访问、更省电。











