解决使用ARCore出现绿色闪屏的问题

这个问题是我在使用Filament时遇到,其他渲染引擎可作参考。



解决Filament中使用ARCore出现绿色闪屏的问题

问题现象

使用ARCore的工程中,出现绿屏闪烁。问题帧截图如下:
问题帧

问题定位

问题来源

在filament的1.21.0之前的版本,Stream对象提供了stream(long externalTextureId)方法,允许传递一个纹理ID,之前是通过如下方式实现AR功能。

    // Create the filament stream.
    Stream stream =
        new Stream.Builder()
            .stream(textureId)
                .width(width)
                .height(height)
                .build(engine);
    initialize(stream);

而在1.21.0之后的版本,stream(textureId)方法已过时,官方推荐采用Texture对象的importTexture的方式去加载。故修改成如下内容

    filamentTexture = new Texture.Builder()
            .sampler(Texture.Sampler.SAMPLER_EXTERNAL)
            .importTexture(textureId)
            .build(engine.getFilamentEngine());

实测,也能运行,但是偶现绿屏。

解决方案

相关Issue的解决方式

方式1:类型替换
解决前,找了下Issues,发现以前有人解决过。
Issue的提出者是ThomasGorisse

ThomasGorisse 是sceneview仓库的贡献者,继20年sceneform存档以后,他先后维护了sceneform、sceneview。

Texture from a GLuint texture ID #5513

一句话,就是采用SAMPLER_2D 类型替换SAMPLER_EXTERNAL类型。

方式2:使用ARCore的setCameraTextureNames 替换setCameraTextureName

使用更多的纹理对象

这里引入pixelflinger 的回答:(pixelflinger commented on May 3, 2022)
I think the problem is that you need to call setCameraTextureNames on ARCore with enough textures – probably at least 4., the problem here is that there is only a single texture that is used at the same time for texturing and camera capture.

green flickering and laggy camera stream in android #5498

实际上,ThomasGorisse 的sceneview仓库即是采用这个解决方案,他采用了6个纹理对象。
ARCameraStream
如下:

    /**
     * Passing multiple textures allows for a multithreaded rendering pipeline
     */
    val cameraTextureIds = IntArray(6) { OpenGL.createExternalTextureId() }

我的解决方式

一句话概括

FPS控制在30即可解决问题

为什么我会想到这样去解决?

记得以前使用ARCore,画面FPS即为30。不记得在哪里看到过条评论,说ARCore在1.26版本以后采用Camera2。

由于时间有限,未作深究,以下是我的推测:

最新的ARCore,刷新率有明显提升,但是若是某帧画面未及时返回,所以会导致这一帧在Filament中渲染就是绿色的。

为什么我不采用使用更多的纹理对象去解决?

因为只有ARCore提供了setCameraTextureNames 这个方法,而AREngine只有setCameraTextureName方法。况且若是使用多个纹理对象,之前集成的其他内容都会受到这里的改动而导致未知的问题。

部分步骤

1、重新编译材质

为实现AR的功能,此前我们用了一个材质文件,用于关联相机视频流。
此时,我们需要修改材质文件,并重新编译。

将‘samplerExternal’修改为‘sampler2d’

旧材质

material {
    name : flat,
    shadingModel : unlit,
    blending : opaque,
    parameters : [
        {
            type : samplerExternal,
            name : cameraTexture
        },
        {
            type : float4x4,
            name : uvTransform
        }
    ],
    requires : [
        uv0
    ]
}
......

新材质

material {
    name : flat,
    vertexDomain : device,
    shadingModel : unlit,
    blending : opaque,
    culling : none,
    parameters : [
        {
            type : sampler2d,
            name : cameraTexture
        },
        {
            type : float4x4,
            name : uvTransform
        }
    ],
    requires : [
        uv0
    ]
}
...

2、使用SAMPLER_2D类型

  filamentTexture = Texture.Builder()
      .width(resolution.width)
      .height(resolution.height)
      .levels(1)
      .sampler(Texture.Sampler.SAMPLER_2D)
      .format(Texture.InternalFormat.RGBA8)
      .importTexture(externalTextureId.toLong())
      .build(filamentEngine)

更多代码可转至开源项目“Sceneform-EQR”中查看


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQ-雪梨蛋花汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值