在unity中实现pico MR到VR的过度转换
效果(忽略我的气泡😂):

一、原理
视频透视开启和关闭相关设置请参考官方网站:
主要用到的其实时pico提供的一个PXR_Over Lay的PXR_UnderlayHole Shader。
1.PXR_OverLay的作用
PXR_OverLay组件是 PICO XR SDK 中的一部分,主要用于实现虚拟现实(VR)中的图像叠加。它允许你将一个透明的虚拟层叠加到现有的 VR 场景中,从而实现类似增强现实(AR)效果的功能。通过 PXR_OverLay组件,你可以将现实世界的视频流或图像与虚拟世界中的元素进行融合。

2.PXR_UnderlayHole Shader的作用
PXR_UnderlayHole是 PICO 提供的一个 shader,专门用于创建一个透明的“孔”,通过这个孔可以看到背景或现实世界的内容。它在 VR 中被用于实现 MR(混合现实)效果,在虚拟场景中“打孔”以显示现实世界内容。这个shader位置如下:

3.使用 PXR_OverLay和 PXR_UnderlayHole实现 MR 到 VR 的过渡
为了实现从 MR到 VR的过渡,可以通过以下步骤结合 PXR_OverLay和 PXR_UnderlayHole来控制过渡效果。
- 设置PXR_OverLay,将type设置为underlay,这样现实世界图像位于虚拟世界的背景层,使虚拟世界物体浮动在现实世界之上
。 -
使用
PXR_UnderlayHoleShader:这个shade可以很好地支持 MR 场景下将虚拟元素叠加到现实世界中,但其只提供了开启和关闭功能,并没有直接提供平滑过渡的功能,直接使用会非常生硬。 -
增加
_Alpha控制透明度:通过在 Shader 中引入 _Alpha 变量,我们可以动态控制现实世界图像的透明度,使其随着过渡进度逐渐消失,最终呈现一个完整的虚拟世界场景。 -
实时调整 _Alpha:通过 Unity 的 Slider 控件或者自定义控制方式,我们可以在代码中动态调整 _Alpha的值,从而实现从 MR 到 VR 的平滑过渡。
二、shader代码
如果你想要实现其他的效果,不仅仅是控制alpha,就需要自己修改了。
Shader "Unlit/PXR_UnderlayHole_Custom"
{
Properties
{
_MainTex ("Texture(A)", 2D) = "Black" {}
_Alpha ("Alpha", Range(0,1)) = 1
}
SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
LOD 100
Blend Zero OneMinusSrcAlpha
ZWrite Off
ColorMask RGBA
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
sampler2D _MainTex;
float _Alpha;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = v.texcoord;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.texcoord);
col.rgb = 0; // 颜色不用,只要 alpha
col.a = _Alpha; // 用 _Alpha 全局控制
return col;
}
ENDCG
}
}
}
三、在unity中使用shader
下面是测试代码,你可以按照自己的想法实现。
由于我的项目已经过了很久,最初的测试代码已经没了,以下仅供参考。
using UnityEngine;
using System.Collections;
public class TransitionController : MonoBehaviour
{
// 材质变量,请在 Inspector 中拖入你的 holeMat
public Material holeMat;
// 渐变持续时间(秒)
public float fadeDuration = 2.0f;
public void OnButtonClicked()
{
// 确保材质不为空
if (holeMat != null)
{
// 启动协程,开始渐变
StartCoroutine(FadeOutAlpha());
}
}
/// <summary>
/// 自动将材质的 _Alpha 值从 1 渐变到 0 的协程。
/// </summary>
private IEnumerator FadeOutAlpha()
{
float elapsedTime = 0f;
// 渐变开始时,先开启透视(对应原代码中的 value > 0.9)
PXR_Manager.EnableVideoSeeThrough = true;
// 循环直到渐变时间结束
while (elapsedTime < fadeDuration)
{
// 根据已用时间计算当前的 Alpha 值,从 1 到 0
float currentAlpha = 1.0f - (elapsedTime / fadeDuration);
// 应用 Alpha 值到材质
holeMat.SetFloat("_Alpha", currentAlpha);
// 增加已用时间
elapsedTime += Time.deltaTime;
// 等待下一帧
yield return null;
}
// 确保最终 Alpha 值为 0
holeMat.SetFloat("_Alpha", 0f);
// 渐变结束后,关闭透视(对应原代码中的 value == 0)
PXR_Manager.EnableVideoSeeThrough = false;
}
}
使用方法
-
创建一个材质并将shader代码复制进去。
-
创建一个 Quad,将材质应用到它上面,注意要放到camera的层级下作为子物体,当转动视角时也可以跟随移动。
-
创建一个空物体并将 TransitionController 脚本挂载到该物体上,在Inspector中将材质赋值,之后可以根据效果随意调整过渡时间。
-
设置一个按钮,将OnButtonclicked方法绑定。
-
导出apk或者实时预览测试即可。
四、补充
忘记一个点:在启用透视时,不支持开启后处理以及使用了Vulkan和渲染管线的情况下需要禁用HDR!!!

更多推荐



所有评论(0)