NoiseEffect.cs 4.0 KB

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