8th Wall XR для Unity: сохранение RealityTexture на диск

Я пытаюсь сохранить канал камеры в png, используя этот код, но, похоже, он работает неправильно:

void RecordAndSaveFrameTexture()
{
    if (mXr.ShouldUseRealityRGBATexture())
    {
        SaveTextureAsPNG(mXr.GetRealityRGBATexture(), mTakeDirInfo.FullName + "/texture_" + mFrameInfo.mFrameCount.ToString() + ".png");
    }
    else
    {
        SaveTextureAsPNG(mXr.GetRealityYTexture(), mTakeDirInfo.FullName + "/texture_y_" + mFrameInfo.mFrameCount.ToString() + ".png");
        SaveTextureAsPNG(mXr.GetRealityUVTexture(), mTakeDirInfo.FullName + "/texture_uv_" + mFrameInfo.mFrameCount.ToString() + ".png");
    }

}

public static void SaveTextureAsPNG(Texture2D aTexture, string aFullPath)
{
    byte[] bytes = aTexture.EncodeToPNG();
    System.IO.File.WriteAllBytes(aFullPath, bytes);
    Debug.Log("Image with Instance ID:" + aTexture.GetInstanceID() + "with dims of " + aTexture.width.ToString() + " px X " + aTexture.height + " px " + " with size of" + bytes.Length / 1024 + "Kb was saved as: " + aFullPath);
}

При тестировании на Android без ArCore я получаю черные изображения (со случайными цветными пикселями) с правильным размером 480 x 640 пикселей. С ArCore это черное изображение размером 0 КБ.

1 ответ

Решение

Создание изображения из этих текстур напрямую не работает, так как эти данные передаются через XRCameraYUVShader а также XRARCoreCamera прежде чем действительное изображение может быть предоставлено.

Одним из вариантов является создание пользовательской версии XRVideoController который обеспечивает доступ к материалу, используемому для рендеринга камеры. Оттуда ваш код может быть изменен так:

void RecordAndSaveFrameTexture() {
  Texture2D src = xr.ShouldUseRealityRGBATexture()
      ? xr.GetRealityRGBATexture()
      : xr.GetRealityYTexture();

  RenderTexture renderTexture = new RenderTexture (src.width, src.height, 0, RenderTextureFormat.ARGB32);
  Graphics.Blit (null, renderTexture, xrMat);
  SaveTextureAsPNG(renderTexture, Application.persistentDataPath + "/texture.png");
}

public static void SaveTextureAsPNG(RenderTexture renderTexture, string aFullPath) {
  Texture2D aTexture = new Texture2D(renderTexture.width, renderTexture.height, TextureFormat.RGBA32, false);
  RenderTexture.active = renderTexture;
  aTexture.ReadPixels(new Rect(0, 0, aTexture.width, aTexture.height), 0, 0);
  RenderTexture.active = null;

  byte[] bytes = aTexture.EncodeToPNG();
  System.IO.File.WriteAllBytes(aFullPath, bytes);
}

куда xrMat материал, используемый для рендеринга камеры.

Это даст изображение с камеры без каких-либо игровых объектов Unity. Если вы хотите, чтобы игровые объекты отображались на сохраненном изображении, вы можете переопределить OnRenderImage чтобы достичь этого:

void OnRenderImage(RenderTexture src, RenderTexture dest) {
    if (shouldSaveImageFrame) {
      SaveTextureAsPNG(src, Application.persistentDataPath + "/_rgbatexture.png");
      shouldSaveImageFrame = false;
    }
    Graphics.Blit (src, dest);
}

куда shouldSaveImageFrame это флаг, который вы установили в другом месте, чтобы предотвратить сохранение изображения в каждом кадре.

Другие вопросы по тегам