using System.Linq; using Controller.Bicycle; using SicknessReduction.Visual.Rendering; using UnityEngine; using UnityEngine.Rendering.Universal; namespace SicknessReduction.Visual.Vignetting { public enum VignettingSource { AngularVelocity, SteerAngle } public class DynamicVignetting : MonoBehaviour { //TODO: cite https://www.researchgate.net/publication/326760789_Assessing_vignetting_as_a_means_to_reduce_VR_sickness_during_amplified_head_rotations //TODO: there is a patent for this https://patents.google.com/patent/US9645395B2/en //TODO: check Fernandes & Feiner private const float DIST_IFOV_OVOF = .10f; [Header("Unity Objects")] public ForwardRendererData forwardRenderer; public RbBicycleController bikeController; public Transform hmd; [Header("Restriction Data")] public VignettingSource vignettingSource; [Range(0, 1)] public float minRestriction = 0.3f; [Range(0, 1)] public float maxRestriction = 0.7f; public float maxRestrictionChangePerSecond = 0.8f; [Tooltip("Depending on Vignetting source -> deg or deg/s")] public float threshold = 20f; //TODO: figure out what angular velocity means in my context private MaterialBlitFeature blitFeature; private Material blitFeatureMaterial; private bool blitFeatureAvailable; private ValueBasedRestrictionSuggestor steerAngleSuggestor; private QueueBasedRestrictionSuggestorVector3 angularVelocitySuggestor; private float currentRestriction; private void Start() { blitFeature = (MaterialBlitFeature) forwardRenderer.rendererFeatures.FirstOrDefault(f => f is MaterialBlitFeature && f.name.Equals("VignetteBlitFilter")); blitFeatureAvailable = blitFeature != null; if (!blitFeatureAvailable) return; // ReSharper disable once PossibleNullReferenceException blitFeatureMaterial = blitFeature.settings.MaterialToBlit; if (vignettingSource == VignettingSource.AngularVelocity) { angularVelocitySuggestor = new QueueBasedRestrictionSuggestorVector3(threshold, minRestriction, maxRestriction, 180f); //deg/s } else if (vignettingSource == VignettingSource.SteerAngle) { steerAngleSuggestor = new ValueBasedRestrictionSuggestor(threshold: threshold, minRestriction, maxRestriction, bikeController.maxSteeringAngle); //deg } } private void Update() { if (!blitFeatureAvailable) return; float desiredRestriction; if (vignettingSource == VignettingSource.AngularVelocity) { angularVelocitySuggestor.AddValue(bikeController.rigidBody.transform.localEulerAngles); desiredRestriction = angularVelocitySuggestor.Suggestion; } else { steerAngleSuggestor.Value = bikeController.CurrentSteerAngle; desiredRestriction = steerAngleSuggestor.Suggestion; } var desiredChange = desiredRestriction - currentRestriction; var maxChange = Time.deltaTime * maxRestrictionChangePerSecond; var change = Mathf.Sign(desiredChange) * Mathf.Min(Mathf.Abs(desiredChange), maxChange); var correctedRestriction = Mathf.Clamp(currentRestriction + change, 0, 1); Debug.Log("V: CurrentRestriction = " + currentRestriction); Debug.Log("V: DesiredChange = " + desiredChange); Debug.Log("V: MaxChange = " + maxChange); Debug.Log("V: DesiredRestriction = " + desiredRestriction); Debug.Log("V: CorrectedRestriction = " + correctedRestriction); if (correctedRestriction > 0f) { blitFeature.SetActive(true); UpdateMaterial(correctedRestriction); return; } blitFeature.SetActive(false); } private void UpdateMaterial(float restriction) { currentRestriction = restriction; var r = Mathf.Clamp(1 - restriction, 0, 1); blitFeatureMaterial.SetFloat("_OFOV", r); blitFeatureMaterial.SetFloat("_IFOV", Mathf.Clamp(r - DIST_IFOV_OVOF, 0, 1)); } private void OnDestroy() { if (!blitFeatureAvailable) return; blitFeature.SetActive(false); } } }