DynamicVignetting.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. using System.Linq;
  2. using Controller.Bicycle;
  3. using SicknessReduction.Visual.Rendering;
  4. using UnityEngine;
  5. using UnityEngine.Rendering.Universal;
  6. namespace SicknessReduction.Visual.Vignetting
  7. {
  8. public enum VignettingSource
  9. {
  10. AngularVelocity,
  11. SteerAngle,
  12. SteerAngleAndSpeed
  13. }
  14. public class DynamicVignetting : MonoBehaviour
  15. {
  16. //TODO: cite https://www.researchgate.net/publication/326760789_Assessing_vignetting_as_a_means_to_reduce_VR_sickness_during_amplified_head_rotations
  17. //TODO: there is a patent for this https://patents.google.com/patent/US9645395B2/en
  18. //TODO: check Fernandes & Feiner
  19. [Header("Unity Objects")] public ForwardRendererData forwardRenderer;
  20. public RbBicycleController bikeController;
  21. public Transform hmd;
  22. [Header("Restriction Data")] public VignettingSource vignettingSource;
  23. [Range(0, 1)] public float minRestriction = 0.3f;
  24. [Range(0, 1)] public float maxRestriction = 0.7f;
  25. [Range(0, 1)] public float distInnerOuterRadius = .05f;
  26. public float maxRestrictionChangePerSecond = 0.8f;
  27. [Tooltip("Depending on Vignetting source -> deg or deg/s")]
  28. public float threshold = 20f;
  29. //TODO: figure out what angular velocity means in my context
  30. private MaterialBlitFeature blitFeature;
  31. private Material blitFeatureMaterial;
  32. private bool blitFeatureAvailable;
  33. private ValueBasedRestrictionSuggestor steerAngleSuggestor;
  34. private QueueBasedRestrictionSuggestorVector3 angularVelocitySuggestor;
  35. private ValueBasedRestrictionSuggestor speedSuggestor;
  36. private float currentRestriction;
  37. private void Start()
  38. {
  39. blitFeature = (MaterialBlitFeature) forwardRenderer.rendererFeatures.FirstOrDefault(f =>
  40. f is MaterialBlitFeature && f.name.Equals("VignetteBlitFilter"));
  41. blitFeatureAvailable = blitFeature != null;
  42. if (!blitFeatureAvailable) return;
  43. // ReSharper disable once PossibleNullReferenceException
  44. blitFeatureMaterial = blitFeature.settings.MaterialToBlit;
  45. if (vignettingSource == VignettingSource.AngularVelocity)
  46. {
  47. angularVelocitySuggestor =
  48. new QueueBasedRestrictionSuggestorVector3(threshold, minRestriction, maxRestriction, 180f); //deg/s
  49. }
  50. else if (vignettingSource == VignettingSource.SteerAngle || vignettingSource == VignettingSource.SteerAngleAndSpeed)
  51. {
  52. steerAngleSuggestor =
  53. new ValueBasedRestrictionSuggestor(threshold, minRestriction, maxRestriction,
  54. bikeController.maxSteeringAngle); //deg
  55. if (vignettingSource == VignettingSource.SteerAngleAndSpeed)
  56. {
  57. speedSuggestor = new ValueBasedRestrictionSuggestor(0, minRestriction,
  58. maxRestriction, 25f);
  59. }
  60. }
  61. }
  62. private void Update()
  63. {
  64. if (!blitFeatureAvailable) return;
  65. float desiredRestriction;
  66. if (vignettingSource == VignettingSource.AngularVelocity)
  67. {
  68. angularVelocitySuggestor.AddValue(bikeController.rigidBody.transform.localEulerAngles);
  69. desiredRestriction = angularVelocitySuggestor.Suggestion;
  70. }
  71. else
  72. {
  73. steerAngleSuggestor.Value = bikeController.CurrentSteerAngle;
  74. if (vignettingSource == VignettingSource.SteerAngle)
  75. {
  76. desiredRestriction = steerAngleSuggestor.Suggestion;
  77. }
  78. else
  79. {
  80. speedSuggestor.Value = bikeController.CurrentSpeed;
  81. var steerSuggestion = steerAngleSuggestor.Suggestion;
  82. var speedSuggestion = speedSuggestor.Suggestion;
  83. if (steerSuggestion == 0)
  84. {
  85. desiredRestriction = 0f;
  86. }
  87. else
  88. {
  89. desiredRestriction = (2 * steerSuggestion + speedSuggestion) / 3;
  90. }
  91. }
  92. }
  93. var desiredChange = desiredRestriction - currentRestriction;
  94. var maxChange = Time.deltaTime * maxRestrictionChangePerSecond;
  95. var change = Mathf.Sign(desiredChange) * Mathf.Min(Mathf.Abs(desiredChange), maxChange);
  96. var correctedRestriction = Mathf.Clamp(currentRestriction + change, 0, 1);
  97. Debug.Log("V: CurrentRestriction = " + currentRestriction);
  98. Debug.Log("V: DesiredChange = " + desiredChange);
  99. Debug.Log("V: MaxChange = " + maxChange);
  100. Debug.Log("V: DesiredRestriction = " + desiredRestriction);
  101. Debug.Log("V: CorrectedRestriction = " + correctedRestriction);
  102. if (correctedRestriction > 0f)
  103. {
  104. blitFeature.SetActive(true);
  105. UpdateMaterial(correctedRestriction);
  106. return;
  107. }
  108. blitFeature.SetActive(false);
  109. }
  110. private void UpdateMaterial(float restriction)
  111. {
  112. currentRestriction = restriction;
  113. var r = Mathf.Clamp(1 - restriction, 0, 1);
  114. blitFeatureMaterial.SetFloat("_OFOV", r);
  115. blitFeatureMaterial.SetFloat("_IFOV", Mathf.Clamp(r - distInnerOuterRadius, 0, 1));
  116. }
  117. private void OnDestroy()
  118. {
  119. if (!blitFeatureAvailable) return;
  120. blitFeature.SetActive(false);
  121. }
  122. }
  123. }