NoiseAndScratches.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. using System;
  2. using UnityEngine;
  3. using Random = UnityEngine.Random;
  4. namespace UnityStandardAssets.ImageEffects
  5. {
  6. [ExecuteInEditMode]
  7. [RequireComponent (typeof(Camera))]
  8. [AddComponentMenu("Image Effects/Noise/Noise and Scratches")]
  9. public class NoiseAndScratches : MonoBehaviour
  10. {
  11. /// Monochrome noise just adds grain. Non-monochrome noise
  12. /// more resembles VCR as it adds noise in YUV color space,
  13. /// thus introducing magenta/green colors.
  14. public bool monochrome = true;
  15. private bool rgbFallback = false;
  16. // Noise grain takes random intensity from Min to Max.
  17. [Range(0.0f,5.0f)]
  18. public float grainIntensityMin = 0.1f;
  19. [Range(0.0f, 5.0f)]
  20. public float grainIntensityMax = 0.2f;
  21. /// The size of the noise grains (1 = one pixel).
  22. [Range(0.1f, 50.0f)]
  23. public float grainSize = 2.0f;
  24. // Scratches take random intensity from Min to Max.
  25. [Range(0.0f, 5.0f)]
  26. public float scratchIntensityMin = 0.05f;
  27. [Range(0.0f, 5.0f)]
  28. public float scratchIntensityMax = 0.25f;
  29. /// Scratches jump to another locations at this times per second.
  30. [Range(1.0f, 30.0f)]
  31. public float scratchFPS = 10.0f;
  32. /// While scratches are in the same location, they jitter a bit.
  33. [Range(0.0f, 1.0f)]
  34. public float scratchJitter = 0.01f;
  35. public Texture grainTexture;
  36. public Texture scratchTexture;
  37. public Shader shaderRGB;
  38. public Shader shaderYUV;
  39. private Material m_MaterialRGB;
  40. private Material m_MaterialYUV;
  41. private float scratchTimeLeft = 0.0f;
  42. private float scratchX, scratchY;
  43. protected void Start ()
  44. {
  45. // Disable if we don't support image effects
  46. if (!SystemInfo.supportsImageEffects) {
  47. enabled = false;
  48. return;
  49. }
  50. if ( shaderRGB == null || shaderYUV == null )
  51. {
  52. Debug.Log( "Noise shaders are not set up! Disabling noise effect." );
  53. enabled = false;
  54. }
  55. else
  56. {
  57. if ( !shaderRGB.isSupported ) // disable effect if RGB shader is not supported
  58. enabled = false;
  59. else if ( !shaderYUV.isSupported ) // fallback to RGB if YUV is not supported
  60. rgbFallback = true;
  61. }
  62. }
  63. protected Material material {
  64. get {
  65. if ( m_MaterialRGB == null ) {
  66. m_MaterialRGB = new Material( shaderRGB );
  67. m_MaterialRGB.hideFlags = HideFlags.HideAndDontSave;
  68. }
  69. if ( m_MaterialYUV == null && !rgbFallback ) {
  70. m_MaterialYUV = new Material( shaderYUV );
  71. m_MaterialYUV.hideFlags = HideFlags.HideAndDontSave;
  72. }
  73. return (!rgbFallback && !monochrome) ? m_MaterialYUV : m_MaterialRGB;
  74. }
  75. }
  76. protected void OnDisable() {
  77. if ( m_MaterialRGB )
  78. DestroyImmediate( m_MaterialRGB );
  79. if ( m_MaterialYUV )
  80. DestroyImmediate( m_MaterialYUV );
  81. }
  82. private void SanitizeParameters()
  83. {
  84. grainIntensityMin = Mathf.Clamp( grainIntensityMin, 0.0f, 5.0f );
  85. grainIntensityMax = Mathf.Clamp( grainIntensityMax, 0.0f, 5.0f );
  86. scratchIntensityMin = Mathf.Clamp( scratchIntensityMin, 0.0f, 5.0f );
  87. scratchIntensityMax = Mathf.Clamp( scratchIntensityMax, 0.0f, 5.0f );
  88. scratchFPS = Mathf.Clamp( scratchFPS, 1, 30 );
  89. scratchJitter = Mathf.Clamp( scratchJitter, 0.0f, 1.0f );
  90. grainSize = Mathf.Clamp( grainSize, 0.1f, 50.0f );
  91. }
  92. // Called by the camera to apply the image effect
  93. void OnRenderImage (RenderTexture source, RenderTexture destination)
  94. {
  95. SanitizeParameters();
  96. if ( scratchTimeLeft <= 0.0f )
  97. {
  98. scratchTimeLeft = Random.value * 2 / scratchFPS; // we have sanitized it earlier, won't be zero
  99. scratchX = Random.value;
  100. scratchY = Random.value;
  101. }
  102. scratchTimeLeft -= Time.deltaTime;
  103. Material mat = material;
  104. mat.SetTexture("_GrainTex", grainTexture);
  105. mat.SetTexture("_ScratchTex", scratchTexture);
  106. float grainScale = 1.0f / grainSize; // we have sanitized it earlier, won't be zero
  107. mat.SetVector("_GrainOffsetScale", new Vector4(
  108. Random.value,
  109. Random.value,
  110. (float)Screen.width / (float)grainTexture.width * grainScale,
  111. (float)Screen.height / (float)grainTexture.height * grainScale
  112. ));
  113. mat.SetVector("_ScratchOffsetScale", new Vector4(
  114. scratchX + Random.value*scratchJitter,
  115. scratchY + Random.value*scratchJitter,
  116. (float)Screen.width / (float) scratchTexture.width,
  117. (float)Screen.height / (float) scratchTexture.height
  118. ));
  119. mat.SetVector("_Intensity", new Vector4(
  120. Random.Range(grainIntensityMin, grainIntensityMax),
  121. Random.Range(scratchIntensityMin, scratchIntensityMax),
  122. 0, 0 ));
  123. Graphics.Blit (source, destination, mat);
  124. }
  125. }
  126. }