原理:第二块屏幕同步显示第一块屏幕的内容,包括摄像头位置,模型位置等,扣掉skybox和background,把需要的部分渲染出来,然后启用摄像头,把摄像头拍到的画面渲染到原来的背景上
前期工作:
2个摄像机,一个主摄像机 一个AR摄像机 把AR相机的Culling Mask 中 不需要的层级剔除掉。
新建一个RawImage ,指定给Canvas,这个想要全屏覆盖,先把Canvas的渲染模式 RenderMode改为ScreenSpace-Camera 然后指定给ARCamera,设置Plane Distance 这个位置最好显示到你的AR场景后面,避免出现场景被切除,然后切换成WorldSpace ,Order in Layer改成-1。
主要逻辑:
private int currentCamIndex = 0;
private WebCamTexture webCamTexture;
public RawImage rawImage;
public void SwapCameraClicked()
{
if (WebCamTexture.devices.Length > 0)
{
currentCamIndex += 1;
currentCamIndex %= WebCamTexture.devices.Length;
while (IsVirtualWebcam(WebCamTexture.devices[currentCamIndex].name))
{
currentCamIndex += 1;
currentCamIndex %= WebCamTexture.devices.Length;
}
if (webCamTexture != null)
{
StopCamera();
StartStopCameraClicked();
}
}
}
private bool isContainsNotMatchCase(string target, string contains)
{
if (target.IndexOf(contains, StringComparison.OrdinalIgnoreCase) >= 0)
{
return true;
}
return false;
}
public bool IsVirtualWebcam(string deviceId)
{
if (isContainsNotMatchCase(deviceId, "virtual"))
{
return true;
return false;
}
WebCamDevice device;
public void StartStopCameraClicked()
{
if (webCamTexture != null)
{
StopCamera();
}
else
{
device = WebCamTexture.devices[currentCamIndex];
if (!device.Equals(null))
{
int width = 1920;
int height = 1080;
webCamTexture = new WebCamTexture(device.name, width, height, 24);
rawImage.texture = webCamTexture;
webCamTexture.Play();
Debug.Log("StartDeviceCamera" + WebCamTexture.devices[currentCamIndex].name);
}
}
}
private void StopCamera()
{
rawImage.texture = null;
webCamTexture.Stop();
webCamTexture = null;
Debug.Log("StopDeviceCamera" + WebCamTexture.devices[currentCamIndex].name);
}
public void StartARMode()
{
for (int i = 0; i < Display.displays.Length; i++)
{
if (i < 2)
{
Display.displays[i].Activate();
}
}
StartStopCameraClicked();
}
主要问题:如果有虚拟摄像头,会导致出问题,目前判断跳过虚拟摄像头是获取名字,但是不同商家生产的命名不同。