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