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, SteerAngleAndSpeed } 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 [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; [Range(0, 1)] public float distInnerOuterRadius = .05f; 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 ValueBasedRestrictionSuggestor speedSuggestor; 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 || vignettingSource == VignettingSource.SteerAngleAndSpeed) { steerAngleSuggestor = new ValueBasedRestrictionSuggestor(threshold, minRestriction, maxRestriction, bikeController.maxSteeringAngle); //deg if (vignettingSource == VignettingSource.SteerAngleAndSpeed) { speedSuggestor = new ValueBasedRestrictionSuggestor(0, minRestriction, maxRestriction, 25f); } } } 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; if (vignettingSource == VignettingSource.SteerAngle) { desiredRestriction = steerAngleSuggestor.Suggestion; } else { speedSuggestor.Value = bikeController.CurrentSpeed; var steerSuggestion = steerAngleSuggestor.Suggestion; var speedSuggestion = speedSuggestor.Suggestion; if (steerSuggestion == 0) { desiredRestriction = 0f; } else { desiredRestriction = (2 * steerSuggestion + speedSuggestion) / 3; } } } 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 - distInnerOuterRadius, 0, 1)); } private void OnDestroy() { if (!blitFeatureAvailable) return; blitFeature.SetActive(false); } } }