效果(忽略我的气泡😂):

一、原理

视频透视开启和关闭相关设置请参考官方网站:

视频透视 | PICO 开发者平台

主要用到的其实时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_UnderlayHole Shader:这个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;
    }
}

使用方法

  1. 创建一个材质并将shader代码复制进去。

  2. 创建一个 Quad,将材质应用到它上面,注意要放到camera的层级下作为子物体,当转动视角时也可以跟随移动。

  3. 创建一个空物体并将 TransitionController 脚本挂载到该物体上,在Inspector中将材质赋值,之后可以根据效果随意调整过渡时间。

  4. 设置一个按钮,将OnButtonclicked方法绑定。

  5. 导出apk或者实时预览测试即可。

四、补充

忘记一个点:在启用透视时,不支持开启后处理以及使用了Vulkan和渲染管线的情况下需要禁用HDR!!!

更多推荐