SunShafts.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using System;
  2. using UnityEngine;
  3. namespace UnityStandardAssets.ImageEffects
  4. {
  5. [ExecuteInEditMode]
  6. [RequireComponent (typeof(Camera))]
  7. [AddComponentMenu ("Image Effects/Rendering/Sun Shafts")]
  8. public class SunShafts : PostEffectsBase
  9. {
  10. public enum SunShaftsResolution
  11. {
  12. Low = 0,
  13. Normal = 1,
  14. High = 2,
  15. }
  16. public enum ShaftsScreenBlendMode
  17. {
  18. Screen = 0,
  19. Add = 1,
  20. }
  21. public SunShaftsResolution resolution = SunShaftsResolution.Normal;
  22. public ShaftsScreenBlendMode screenBlendMode = ShaftsScreenBlendMode.Screen;
  23. public Transform sunTransform;
  24. public int radialBlurIterations = 2;
  25. public Color sunColor = Color.white;
  26. public Color sunThreshold = new Color(0.87f,0.74f,0.65f);
  27. public float sunShaftBlurRadius = 2.5f;
  28. public float sunShaftIntensity = 1.15f;
  29. public float maxRadius = 0.75f;
  30. public bool useDepthTexture = true;
  31. public Shader sunShaftsShader;
  32. private Material sunShaftsMaterial;
  33. public Shader simpleClearShader;
  34. private Material simpleClearMaterial;
  35. public override bool CheckResources () {
  36. CheckSupport (useDepthTexture);
  37. sunShaftsMaterial = CheckShaderAndCreateMaterial (sunShaftsShader, sunShaftsMaterial);
  38. simpleClearMaterial = CheckShaderAndCreateMaterial (simpleClearShader, simpleClearMaterial);
  39. if (!isSupported)
  40. ReportAutoDisable ();
  41. return isSupported;
  42. }
  43. void OnRenderImage (RenderTexture source, RenderTexture destination) {
  44. if (CheckResources()==false) {
  45. Graphics.Blit (source, destination);
  46. return;
  47. }
  48. // we actually need to check this every frame
  49. if (useDepthTexture)
  50. GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
  51. int divider = 4;
  52. if (resolution == SunShaftsResolution.Normal)
  53. divider = 2;
  54. else if (resolution == SunShaftsResolution.High)
  55. divider = 1;
  56. Vector3 v = Vector3.one * 0.5f;
  57. if (sunTransform)
  58. v = GetComponent<Camera>().WorldToViewportPoint (sunTransform.position);
  59. else
  60. v = new Vector3(0.5f, 0.5f, 0.0f);
  61. int rtW = source.width / divider;
  62. int rtH = source.height / divider;
  63. RenderTexture lrColorB;
  64. RenderTexture lrDepthBuffer = RenderTexture.GetTemporary (rtW, rtH, 0);
  65. // mask out everything except the skybox
  66. // we have 2 methods, one of which requires depth buffer support, the other one is just comparing images
  67. sunShaftsMaterial.SetVector ("_BlurRadius4", new Vector4 (1.0f, 1.0f, 0.0f, 0.0f) * sunShaftBlurRadius );
  68. sunShaftsMaterial.SetVector ("_SunPosition", new Vector4 (v.x, v.y, v.z, maxRadius));
  69. sunShaftsMaterial.SetVector ("_SunThreshold", sunThreshold);
  70. if (!useDepthTexture) {
  71. var format= GetComponent<Camera>().allowHDR ? RenderTextureFormat.DefaultHDR: RenderTextureFormat.Default;
  72. RenderTexture tmpBuffer = RenderTexture.GetTemporary (source.width, source.height, 0, format);
  73. RenderTexture.active = tmpBuffer;
  74. GL.ClearWithSkybox (false, GetComponent<Camera>());
  75. sunShaftsMaterial.SetTexture ("_Skybox", tmpBuffer);
  76. Graphics.Blit (source, lrDepthBuffer, sunShaftsMaterial, 3);
  77. RenderTexture.ReleaseTemporary (tmpBuffer);
  78. }
  79. else {
  80. Graphics.Blit (source, lrDepthBuffer, sunShaftsMaterial, 2);
  81. }
  82. // paint a small black small border to get rid of clamping problems
  83. DrawBorder (lrDepthBuffer, simpleClearMaterial);
  84. // radial blur:
  85. radialBlurIterations = Mathf.Clamp (radialBlurIterations, 1, 4);
  86. float ofs = sunShaftBlurRadius * (1.0f / 768.0f);
  87. sunShaftsMaterial.SetVector ("_BlurRadius4", new Vector4 (ofs, ofs, 0.0f, 0.0f));
  88. sunShaftsMaterial.SetVector ("_SunPosition", new Vector4 (v.x, v.y, v.z, maxRadius));
  89. for (int it2 = 0; it2 < radialBlurIterations; it2++ ) {
  90. // each iteration takes 2 * 6 samples
  91. // we update _BlurRadius each time to cheaply get a very smooth look
  92. lrColorB = RenderTexture.GetTemporary (rtW, rtH, 0);
  93. Graphics.Blit (lrDepthBuffer, lrColorB, sunShaftsMaterial, 1);
  94. RenderTexture.ReleaseTemporary (lrDepthBuffer);
  95. ofs = sunShaftBlurRadius * (((it2 * 2.0f + 1.0f) * 6.0f)) / 768.0f;
  96. sunShaftsMaterial.SetVector ("_BlurRadius4", new Vector4 (ofs, ofs, 0.0f, 0.0f) );
  97. lrDepthBuffer = RenderTexture.GetTemporary (rtW, rtH, 0);
  98. Graphics.Blit (lrColorB, lrDepthBuffer, sunShaftsMaterial, 1);
  99. RenderTexture.ReleaseTemporary (lrColorB);
  100. ofs = sunShaftBlurRadius * (((it2 * 2.0f + 2.0f) * 6.0f)) / 768.0f;
  101. sunShaftsMaterial.SetVector ("_BlurRadius4", new Vector4 (ofs, ofs, 0.0f, 0.0f) );
  102. }
  103. // put together:
  104. if (v.z >= 0.0f)
  105. sunShaftsMaterial.SetVector ("_SunColor", new Vector4 (sunColor.r, sunColor.g, sunColor.b, sunColor.a) * sunShaftIntensity);
  106. else
  107. sunShaftsMaterial.SetVector ("_SunColor", Vector4.zero); // no backprojection !
  108. sunShaftsMaterial.SetTexture ("_ColorBuffer", lrDepthBuffer);
  109. Graphics.Blit (source, destination, sunShaftsMaterial, (screenBlendMode == ShaftsScreenBlendMode.Screen) ? 0 : 4);
  110. RenderTexture.ReleaseTemporary (lrDepthBuffer);
  111. }
  112. }
  113. }