PicoVR眼镜在XR融合现实显示模式下无法显示粒子问题

PicoVR眼镜开启XR融合现实显示模式下,Unity3D粒子效果无法显示问题,其原因是XR融合显示模式下,Unity3D应用显示层在最终合成到眼镜显示器时,驱动层先渲染摄像机画面,再以Alpha透明方式渲染应用层画面,问题就出在Alpha通道上:粒子显示位置的Alpha值为0。

究其原因,Unity3D在设置PicoXR视频融合模式时,需要将Camera设置为背景模式,背景色全黑,且背景色的Alpha值也为0。背景色的设置其实就是在BeginDraw时,用背景色清空渲染画布,值为0x00000000的背景色,初始画布为全黑透明画布。

渲染普通实体时,除了在画布上渲染颜色,还会将Alpha设置为255。而粒子一般用Additive叠加模式,其只会叠加画布颜色,不会修改画布Alpha透明度,导致最终合成时,粒子渲染颜色被替换为背景摄像机画面,看到的就是粒子画面全透明了,只有在实体表面才会有存留。

解决办法有两个:

其一是修改粒子的shader,让粒子shader渲染颜色同时,修改Alpha值。但这种方法要修改的东西很多,需要修改每个粒子的shader,工作量很大,而且不通用。

其二是增加一个后期shader,由后期shader统一处理最终提交给驱动的渲染画布。

操作如下:

1、创建一个后期着色器,在后期着色器中统一将有颜色的像素,根据色彩值修改Alpha值

c 复制代码
Shader "Hidden/AlphaByColor" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _Threshold ("Alpha Threshold", Range(0,1)) = 0.05
    }

    SubShader {
        Cull Off ZWrite Off ZTest Always

        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct v2f {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            sampler2D _MainTex;
            float _Threshold;

            v2f vert (appdata_img v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target {
                fixed4 col = tex2D(_MainTex, i.uv);
                
                // 方法1:亮度检测
                float luminance = dot(col.rgb, float3(0.299, 0.587, 0.114));
                float newAlpha = smoothstep(_Threshold, _Threshold + 0.1, luminance);
                col.a = max(col.a, newAlpha);
                
                // 方法2:颜色通道检测(二选一)
                // float colorPresence = max(col.r, max(col.g, col.b));
                // col.a = step(_Threshold, colorPresence);
                
                return col;
            }
            ENDCG
        }
    }
}

2、挂载后期处理脚本

csharp 复制代码
using UnityEngine;

[ExecuteInEditMode]
public class AlphaPostProcess : MonoBehaviour
{
  public Material postProcessMaterial;
  [Range(0, 1)] public float threshold = 0.05f;

  void OnRenderImage(RenderTexture src, RenderTexture dest)
  {
    postProcessMaterial.SetFloat("_Threshold", threshold);
    Graphics.Blit(src, dest, postProcessMaterial);
  }
}

这样处理以后,粒子就可以正常叠加在实景画面上了。

相关推荐
明耀1 小时前
WPF C# 用WebView加载H5页面(uniapp项目,vue项目)
uni-app·c#·wpf
我不是程序猿儿5 小时前
【C#】 lock 关键字
java·开发语言·c#
动感光博9 小时前
Unity序列化字段、单例模式(Singleton Pattern)
unity·单例模式·c#
黑洞视界10 小时前
NCC Mocha v0.2.0 发布, 新增对 Metrics 的支持
c#·.net·可观测性·observability
FAREWELL0007511 小时前
Unity基础学习(十五)核心系统——音效系统
学习·unity·c#·游戏引擎
uwvwko11 小时前
BUUCTF——web刷题第一页题解
android·前端·数据库·php·web·ctf
fzxwl11 小时前
隆重推荐(Android 和 iOS)UI 自动化工具—Maestro
android·ui·ios
zimoyin12 小时前
Java 快速转 C# 教程
java·开发语言·c#
向宇it12 小时前
【unity游戏开发——编辑器扩展】使用MenuItem自定义菜单栏拓展
开发语言·ui·unity·c#·编辑器·游戏引擎
动感光博12 小时前
Unity碰撞检测(射线投射、胶囊体投射)、交互(图层、掩码)
unity·c#·游戏引擎·游戏程序·动画