PAYATHON 2026

如何禁用 skybox 或将 SceneView 的黑色背景设为透明?

排障赵师傅

结论

要让骰子后方的 Compose 图层显示出来,需要让 SceneView 的渲染结果保留透明度,并停止绘制不透明背景。Modifier.background(Color.Transparent) 只影响 Compose 背景,无法清除 3D 渲染器已经画出的黑色像素。

你已经设置了 isOpaque = false 和 SurfaceType.TextureSurface,接下来应检查实际场景中的 skybox,以及 Filament 的混合模式和清屏颜色。仅凭这段代码,还不能确定黑色来自 skybox。

为什么蓝色只显示一瞬间

这通常是因为 SceneView 提交渲染帧之前,Compose 设置的蓝色背景可见;开始渲染后,不透明的 3D 输出就覆盖了它。

反复修改 Modifier.background(...) 无法解决渲染帧本身不透明的问题,需要检查以下配置:

  • 场景是否仍在绘制 skybox。
  • Filament View 是否允许透明混合。
  • 未绘制模型的位置在清屏后,Alpha 是否为 0。
  • 底层 TextureView 的 isOpaque 是否为 false。

禁用 skybox,并保留环境光照

skybox 负责显示天空或背景,环境光照中的 IndirectLight 负责照亮模型。隐藏 skybox 时,可以保留环境光照,避免骰子的外观随之改变。

在 Filament 层,可以这样移除可见的 skybox:

scene.skybox = null

这里的 scene 必须是 SceneView 正在渲染的 com.google.android.filament.Scene。

如果 SceneView 在加载或更新 environment 时重新设置了 skybox,就需要在环境配置中去掉 skybox,或者等环境应用完成后再执行上述设置。如果只在初始化早期清空一次,后续更新可能会覆盖这项设置。

透明渲染的配置示例

将 SceneView 实际使用的对象传入以下函数即可,无需另建场景或渲染器:

import com.google.android.filament.Renderer
import com.google.android.filament.Scene
import com.google.android.filament.View as FilamentView

fun configureTransparentBackground(
    scene: Scene,
    view: FilamentView,
    renderer: Renderer
) {
    // 停止绘制天空盒背景,保留已有的 IndirectLight。
    scene.skybox = null

    // 允许渲染结果与下方图层进行透明混合。
    view.blendMode = FilamentView.BlendMode.TRANSLUCENT

    // 将未绘制模型的位置清为透明。
    renderer.clearOptions = renderer.clearOptions.apply {
        clear = true
        clearColor = floatArrayOf(0f, 0f, 0f, 0f)
    }
}

题目没有给出 SceneView 的依赖版本,无法确定该版本通过哪些 Compose 参数或回调暴露 scene、view 和 renderer。接入时,应使用当前版本提供的初始化或更新入口,在环境应用完成后、渲染帧开始前配置这些对象。

部分版本会通过 isOpaque = false 自动设置透明混合和清屏。如果这两项设置已经正确,就重点检查 skybox 是否仍然存在,以及环境更新是否覆盖了配置。无需将相同设置一直放在 onFrame 中逐帧执行。

原代码中的旋转逻辑、相机位置和 LightNode 可以保留,它们不决定背景透明度。

让 Compose 内容位于骰子下方

透明区域下方还需要有 Compose 内容。可以用 Box 叠放图层,先放背景,再放骰子:

@Composable
fun DiceScreen(result: Int, isRolling: Boolean) {
    Box(modifier = Modifier.fillMaxSize()) {
        Box(
            modifier = Modifier
                .matchParentSize()
                .background(Color.Blue)
        )

        Dice3DScene(
            result = result,
            isRolling = isRolling,
            modifier = Modifier.matchParentSize()
        )
    }
}

先用蓝色背景验证,比使用透明背景更容易观察效果。配置正确后,骰子周围应该持续显示蓝色,此时再将蓝色 Box 换成游戏界面即可。

仍然黑屏时怎么排查

可以暂时移除模型,观察空场景:

  • 空场景仍然是黑色:继续检查 skybox、清屏 Alpha、混合模式,以及底层 TextureView 的 isOpaque 是否为 false。
  • 空场景已经透明,加载模型后才出现黑色区域:检查 dice.glb 是否包含背景平面或其他遮挡几何体。
  • 启动时透明,环境加载后变黑:检查应用环境时是否重新设置了 skybox。
  • 背景颜色始终不可见:检查 Compose 图层顺序,以及中间是否有不透明容器覆盖背景。

rememberEnvironment(environmentLoader, isOpaque = false) 的具体行为应以所用版本的实现为准。仅凭参数名称,无法确认运行时的 skybox、混合模式和清屏 Alpha 都已符合要求。

备注:内容仅供参考。