diff --git a/MainGameVR/Features/VRFade.cs b/MainGameVR/Features/VRFade.cs index e1176ce..abcf02e 100644 --- a/MainGameVR/Features/VRFade.cs +++ b/MainGameVR/Features/VRFade.cs @@ -1,22 +1,27 @@ -using UnityEngine; +using System; +using System.Collections; +using UnityEngine; +using Valve.VR; using VRGIN.Core; -using VRGIN.Helpers; namespace KKS_VR.Features { /// - /// A VR fader that synchronizes with the fader of the base game. + /// A VR fader that replaces the fader of the base game. /// internal class VRFade : ProtectedBehaviour { /// /// Reference to the image used by the vanilla SceneFade object. /// - private CanvasGroup _vanillaImage; + private CanvasGroup _vanillaFade; - private Material _fadeMaterial; - private int _fadeMaterialColorID; - private float _alpha = 0f; + private readonly Color _fadeColor = Color.white; + private readonly float _gridFadeTime = 1; + private readonly float _fadeAlphaThresholdHigh = 0.9999f; + private readonly float _fadeAlphaThresholdLow = 0.0001f; + + private bool _isFading; public static void Create() { @@ -25,31 +30,91 @@ public static void Create() protected override void OnAwake() { - _vanillaImage = Manager.Scene.sceneFadeCanvas.canvasGroup; - _fadeMaterial = new Material(UnityHelper.GetShader("Custom/SteamVR_Fade")); - _fadeMaterialColorID = Shader.PropertyToID("fadeColor"); + _vanillaFade = Manager.Scene.sceneFadeCanvas?.canvasGroup ?? throw new ArgumentNullException(nameof(_vanillaFade), "sceneFadeCanvas or canvasGroup is null"); + } + + protected override void OnUpdate() + { + if (!_isFading && _vanillaFade && _vanillaFade.alpha > _fadeAlphaThresholdLow) + { + StartCoroutine(DeepFadeCo()); + } } - private void OnPostRender() + /// + /// A coroutine for entering "deep fade", where we cut to the compositor's grid and display some overlay. + /// Based on https://github.com/mosirnik/KK_MainGameVR/commit/12e435f1e9a70c7d7b5dd56de416d300a2836091 + /// + private IEnumerator DeepFadeCo() { - if (_vanillaImage != null) + if (OpenVR.Overlay == null || _isFading) + yield break; + + _isFading = true; + + // Make the world outside of the game the same color as the loading screen instead of the headset default skybox + SetCompositorSkyboxOverride(_fadeColor); + + var compositor = OpenVR.Compositor; + if (compositor != null) + { + // Fade the game out so the ouside world is now seen instead of the laggy loading screen + compositor.FadeGrid(_gridFadeTime, true); + + // It looks like we need to pause rendering here, otherwise the + // compositor will automatically put us back from the grid. + SteamVR_Render.pauseRendering = true; + } + + // Wait for the game to fully fade in + while (_vanillaFade.alpha <= _fadeAlphaThresholdHigh) + { + if (!_vanillaFade || _vanillaFade.alpha < _fadeAlphaThresholdLow) + goto endEarly; + + yield return null; + } + + // Wait for the game to start fading out + while (_vanillaFade.alpha > _fadeAlphaThresholdHigh) + { + yield return null; + } + + // Wait for things to settle down + yield return null; + yield return null; + + endEarly: + + // Let the game be rendered again and fade into it + SteamVR_Render.pauseRendering = false; + if (compositor != null) { - var fadeColor = _vanillaImage.alpha; - _alpha = Mathf.Max(_alpha - 0.05f, fadeColor); // Use at least 20 frames to fade out. - fadeColor = _alpha; - if (_alpha > 0.0001f) - { - _fadeMaterial.SetColor(_fadeMaterialColorID, new Color(1, 1, 1, fadeColor)); - _fadeMaterial.SetPass(0); - GL.Begin(GL.QUADS); - - GL.Vertex3(-1, -1, 0); - GL.Vertex3(1, -1, 0); - GL.Vertex3(1, 1, 0); - GL.Vertex3(-1, 1, 0); - GL.End(); - } + compositor.FadeGrid(_gridFadeTime, false); + yield return new WaitForSeconds(_gridFadeTime); } + + // Wait for the game to finish fading to make sure we are synchronized + while (_vanillaFade && _vanillaFade.alpha > _fadeAlphaThresholdLow) + { + yield return null; + } + + SteamVR_Skybox.ClearOverride(); + + _isFading = false; + } + + private static void SetCompositorSkyboxOverride(Color fadeColor) + { + var tex = new Texture2D(1, 1); + var color = fadeColor; + color.a = 1f; + tex.SetPixel(0, 0, color); + tex.Apply(); + SteamVR_Skybox.SetOverride(tex, tex, tex, tex, tex, tex); + Destroy(tex); } } }