yuusuke0706d
@yuusuke0706d (yu da)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

360度カメラ映像を背景にリアルタイムにレイトレーシングでIBLをしたい   

解決したいこと

360度カメラ映像を背景にリアルタイムでレイトレーシングを使いIBLをしたいです。が方法がわからないので教えていただきたいです

現在、360度カメラRICOH THETA Vの映像をWebcamTextureで受け取り、HDRP のvolumeのhdriskyにwebcamTextureをTexture2D とし cubemapに変更し、Update内で都度hdriskyにcubemapを入れています

発生している問題・エラー

実行時、cubemapの各面が真っ黒になり、とてもシーンが重くなります。 これを直す方法や、このコードでなく新しく別の方法などあったら教えていただきたいです。
探すうえでのキーワードでもなんでも教えていただきたいです。

該当するソースコード

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.Profiling;
 using UnityEngine.Rendering;
 using UnityEngine.Rendering.HighDefinition;
 
 public class StCubemapToHdrisky : MonoBehaviour
 {
     public string deviceNameKeyword = "RICOH THETA UVC";
     Texture2D equirectangularImage;
     private WebCamTexture webcamTexture;
     public Cubemap cubemap;
     public Volume m_Volume;
     HDRISky hdrisky;
     VolumeProfile profile;
     void Start()
     {
        profile = m_Volume.sharedProfile;
         if (!profile.TryGet<HDRISky>(out var hdrisky))
         {
             hdrisky = profile.Add<HDRISky>(false);
         }
         hdrisky.active = true;
         hdrisky.hdriSky.overrideState = true;

         
         StartStreaming();
     }
 
     void Update()
     {
         if (webcamTexture != null && webcamTexture.isPlaying)
         { 
             equirectangularImage.SetPixels(webcamTexture.GetPixels());
             ConvertToCubemap(equirectangularImage, cubemap); 
             profile.TryGet<HDRISky>(out var hdrisky);
             hdrisky.hdriSky.value = cubemap;      
         }
     }
     void ConvertToCubemap(Texture2D equirectangularImage, Cubemap cubemap)
     {
         if (equirectangularImage == null || cubemap == null)
         {
             Debug.LogError("Equirectangular image or Cubemap is not assigned.");
             return;
         }
 
         // Cubemapのサイズを指定
         int cubemapSize = equirectangularImage.width / 4;
         cubemap = new Cubemap(cubemapSize, TextureFormat.RGBA32, false);
 
         // 各面を計算
         for (int face = 0; face < 6; face++)
         {
             RenderFace((CubemapFace)face, equirectangularImage);
         }
 
         // Cubemapを適用
         cubemap.Apply();
     }
 
     void RenderFace(CubemapFace face, Texture2D equirectangularImage)
     {
         // 各面のサイズを計算
         int faceSize = cubemap.width;
         Color[] facePixels = new Color[faceSize * faceSize];
 
         // equirectangular画像からCubemap面に対応する領域を計算
         Rect faceRect = GetFaceRect(face, faceSize);
 
         // ピクセルデータを取得
         for (int y = 0; y < faceSize; y++)
         {
             for (int x = 0; x < faceSize; x++)
             {
                 // equirectangular画像から対応するピクセルを取得
                 int sourceX = Mathf.RoundToInt(faceRect.x + (x / (float)faceSize) * faceRect.width);
                 int sourceY = Mathf.RoundToInt(faceRect.y + (y / (float)faceSize) * faceRect.height);
                 facePixels[y * faceSize + x] = equirectangularImage.GetPixel(sourceX, sourceY);
             }
         }
 
         // ピクセルデータをCubemap面に設定
         cubemap.SetPixels(facePixels, face);
     }
 
     Rect GetFaceRect(CubemapFace face, int faceSize)
     {
         // 各面に対応するequirectangular画像の領域を計算するための簡略化された方法
         int x = (int)face % 4 * faceSize;
         int y = (int)face / 4 * faceSize;
         return new Rect(x, y, faceSize, faceSize);
     }
 
     void StartStreaming()
     {
         WebCamDevice device = new WebCamDevice();
         if (!FindDevice(ref device))
         {
             Debug.LogError($"キーワード: {deviceNameKeyword} を含むウェブカメラが見つかりませんでした");
             return;
         }
 
         if (webcamTexture != null)
         {
             webcamTexture.Stop();
             Destroy(webcamTexture);
         }
         // WebCamTextureを開始
         webcamTexture = new WebCamTexture(device.name);
         webcamTexture.Play();
         Debug.Log($"デバイスからストリーミング中: {device.name}");
         equirectangularImage = new Texture2D(webcamTexture.width, webcamTexture.height, TextureFormat.RGBA32, false);
 
     }
 
 
     bool FindDevice(ref WebCamDevice target)
     {
         WebCamDevice[] devices = WebCamTexture.devices;
         foreach (WebCamDevice device in devices)
         {
             Debug.Log($"利用可能なデバイス: {device.name}");
             if (device.name.Contains(deviceNameKeyword))
             {
                 target = device;
                 return true;
             }
         }
         return false;
     }
 }
0

なんとなくストリーミングの画像サイズが大きすぎて処理が追いついてないのかなと思います
シータVのストリーミング動画の解像度は8Kサイズと2Kサイズだと思いましたが
それを受信して箱型にマッピングして表示の時点で凄まじい処理能力が必要になりそう
ひとまず全てのフレームを処理するんじゃなしに最初に1フレームだけ処理して意図した結果になるか試して確認してみてから
ストリーミングの解像度を落とすなり
処理するフレームレートを落とすなり
ストリーミングで受信した画像を縮小リサイズして、その後の処理に回すなり
とかになると思います
8Kの画像を29、9fpsでリアルタイムに変換はちょっと無茶では…

1Like

Your answer might help someone💌