From 5c096b4c1b0ff2ec4d3ebc37b32ca252a92031db Mon Sep 17 00:00:00 2001
From: client_Wu Xijin <364452445@qq.com>
Date: 星期五, 31 八月 2018 11:11:40 +0800
Subject: [PATCH] 3132  对游戏中一些可能出现的空引用异常进行保护

---
 Core/DynamicShadowProjector/ShadowTextureRenderer.cs | 2312 +++++++++++++++++++++++++++++++---------------------------
 1 files changed, 1,238 insertions(+), 1,074 deletions(-)

diff --git a/Core/DynamicShadowProjector/ShadowTextureRenderer.cs b/Core/DynamicShadowProjector/ShadowTextureRenderer.cs
index f87f8d4..8936d11 100644
--- a/Core/DynamicShadowProjector/ShadowTextureRenderer.cs
+++ b/Core/DynamicShadowProjector/ShadowTextureRenderer.cs
@@ -10,1134 +10,1298 @@
 using UnityEngine.Rendering;
 using System.Collections.Generic;
 
-namespace DynamicShadowProjector {
-	[ExecuteInEditMode]
-	[DisallowMultipleComponent]
-	[RequireComponent(typeof(Projector))]
-	public class ShadowTextureRenderer : MonoBehaviour {
-		public enum TextureMultiSample {
-			x1 = 1,
-			x2 = 2,
-			x4 = 4,
-			x8 = 8,
-		}
-		public enum TextureSuperSample {
-			x1 = 1,
-			x4 = 2,
-			x16 = 4,
-		}
-		public enum MipmapFalloff {
-			None = 0,
-			Linear,
-			Custom,
-		}
-		public enum BlurFilter {
-			Uniform = 0,
-			Gaussian,
-		}
-		// Serialize Fields
-		[SerializeField]
-		private TextureMultiSample m_multiSampling = TextureMultiSample.x4;
-		[SerializeField]
-		private TextureSuperSample m_superSampling = TextureSuperSample.x1;
-		[SerializeField]
-		private MipmapFalloff m_mipmapFalloff = MipmapFalloff.Linear;
-		[SerializeField]
-		private BlurFilter m_blurFilter = BlurFilter.Uniform;
-		[SerializeField]
-		private bool m_testViewClip = true;
-		[SerializeField]
-		private int m_textureWidth = 64;
-		[SerializeField]
-		private int m_textureHeight = 64;
-		[SerializeField]
-		private int m_mipLevel = 0;
-		[SerializeField]
-		private int m_blurLevel = 1;
-		[SerializeField]
-		private float m_blurSize = 3;
-		[SerializeField]
-		private float m_mipmapBlurSize = 0;
-		[SerializeField]
-		private bool m_singlePassMipmapBlur = false;
-		[SerializeField]
-		private Color m_shadowColor = new Color(0,0,0,1);
-		[SerializeField]
-		private Material m_blurShader;
-		[SerializeField]
-		private Material m_downsampleShader;
-		[SerializeField]
-		private Material m_copyMipmapShader;
-		[SerializeField]
-		private Material m_eraseShadowShader;
-		[SerializeField]
-		private float[] m_customMipmapFalloff;
-		[SerializeField]
-		private RenderTextureFormat[] m_preferredTextureFormats;
-		[SerializeField]
-		private Camera[] m_camerasForViewClipTest;
+namespace DynamicShadowProjector
+{
+    [ExecuteInEditMode]
+    [DisallowMultipleComponent]
+    [RequireComponent(typeof(Projector))]
+    public class ShadowTextureRenderer : MonoBehaviour
+    {
+        public enum TextureMultiSample
+        {
+            x1 = 1,
+            x2 = 2,
+            x4 = 4,
+            x8 = 8,
+        }
+        public enum TextureSuperSample
+        {
+            x1 = 1,
+            x4 = 2,
+            x16 = 4,
+        }
+        public enum MipmapFalloff
+        {
+            None = 0,
+            Linear,
+            Custom,
+        }
+        public enum BlurFilter
+        {
+            Uniform = 0,
+            Gaussian,
+        }
+        // Serialize Fields
+        [SerializeField]
+        private TextureMultiSample m_multiSampling = TextureMultiSample.x4;
+        [SerializeField]
+        private TextureSuperSample m_superSampling = TextureSuperSample.x1;
+        [SerializeField]
+        private MipmapFalloff m_mipmapFalloff = MipmapFalloff.Linear;
+        [SerializeField]
+        private BlurFilter m_blurFilter = BlurFilter.Uniform;
+        [SerializeField]
+        private bool m_testViewClip = true;
+        [SerializeField]
+        private int m_textureWidth = 64;
+        [SerializeField]
+        private int m_textureHeight = 64;
+        [SerializeField]
+        private int m_mipLevel = 0;
+        [SerializeField]
+        private int m_blurLevel = 1;
+        [SerializeField]
+        private float m_blurSize = 3;
+        [SerializeField]
+        private float m_mipmapBlurSize = 0;
+        [SerializeField]
+        private bool m_singlePassMipmapBlur = false;
+        [SerializeField]
+        private Color m_shadowColor = new Color(0, 0, 0, 1);
+        [SerializeField]
+        private Material m_blurShader;
+        [SerializeField]
+        private Material m_downsampleShader;
+        [SerializeField]
+        private Material m_copyMipmapShader;
+        [SerializeField]
+        private Material m_eraseShadowShader;
+        [SerializeField]
+        private float[] m_customMipmapFalloff;
+        [SerializeField]
+        private RenderTextureFormat[] m_preferredTextureFormats;
+        [SerializeField]
+        private Camera[] m_camerasForViewClipTest;
 
-		// public properties
-		public TextureMultiSample multiSampling
-		{
-			get { return m_multiSampling; }
-			set {
-				if (m_multiSampling != value) {
-					m_multiSampling = value;
-					SetTexturePropertyDirty();
-				}
-			}
-		}
-		public TextureSuperSample superSampling
-		{
-			get { return m_superSampling; }
-			set {
-				if (m_superSampling != value) {
-					bool b = useIntermediateTexture;
-					m_superSampling = value;
-					if (b != useIntermediateTexture && m_multiSampling != TextureMultiSample.x1) {
-						SetTexturePropertyDirty();
-					}
-				}
-			}
-		}
-		public int textureWidth
-		{
-			get { return m_textureWidth; }
-			set {
-				if (m_textureWidth != value) {
-					m_textureWidth = value;
-					SetTexturePropertyDirty();
-				}
-			}
-		}
-		public int textureHeight
-		{
-			get { return m_textureHeight; }
-			set {
-				if (m_textureHeight != value) {
-					m_textureHeight = value;
-					SetTexturePropertyDirty();
-				}
-			}
-		}
-		public int mipLevel
-		{
-			get { return m_mipLevel; }
-			set {
-				if (m_mipLevel != value) {
-					if (m_mipLevel == 0 || value == 0) {
-						SetTexturePropertyDirty();
-					}
-					m_mipLevel = value;
-				}
-			}
-		}
-		public int blurLevel
-		{
-			get { return m_blurLevel; }
-			set
-			{
-				if (m_blurLevel != value) {
-					bool b = useIntermediateTexture;
-					m_blurLevel = value;
-					if (b != useIntermediateTexture && m_multiSampling != TextureMultiSample.x1) {
-						SetTexturePropertyDirty();
-					}
-				}
-			}
-		}
-		public float blurSize
-		{
-			get { return m_blurSize; }
-			set { m_blurSize = value; }
-		}
-		public BlurFilter blurFilter
-		{
-			get { return m_blurFilter; }
-			set { m_blurFilter = value; }
-		}
-		public float mipmapBlurSize
-		{
-			get { return m_mipmapBlurSize; }
-			set
-			{
-				m_mipmapBlurSize = value;
-			}
-		}
-		public bool singlePassMipmapBlur {
-			get { return m_singlePassMipmapBlur; }
-			set { m_singlePassMipmapBlur = value; }
-		}
-		public MipmapFalloff mipmapFalloff
-		{
-			get { return m_mipmapFalloff; }
-			set
-			{
-				m_mipmapFalloff = value;
-			}
-		}
-		public float[] customMipmapFalloff
-		{
-			get { return m_customMipmapFalloff; }
-			set
-			{
-				m_customMipmapFalloff = value;
-			}
-		}
-		public Color shadowColor
-		{
-			get { return m_shadowColor; }
-			set {
-				if (m_shadowColor != value) {
-					bool b = useIntermediateTexture;
-					m_shadowColor = value;
-					if (b != useIntermediateTexture && m_multiSampling != TextureMultiSample.x1) {
-						SetTexturePropertyDirty();
-					}
-				}
-			}
-		}
-		public Material blurShader
-		{
-			get { return m_blurShader; }
-			set
-			{
-				m_blurShader = value;
-			}
-		}
-		public Material downsampleShader
-		{
-			get { return m_downsampleShader; }
-			set { m_downsampleShader = value; }
-		}
-		public Material copyMipmapShader
-		{
-			get { return m_copyMipmapShader; }
-			set
-			{
-				m_copyMipmapShader = value;
-			}
-		}
-		public Material eraseShadowShader
-		{
-			get { return m_eraseShadowShader; }
-			set { m_eraseShadowShader = value; }
-		}
-		public RenderTexture shadowTexture
-		{
-			get { return m_shadowTexture; }
-		}
-		public bool testViewClip
-		{
-			get { return m_testViewClip; }
-			set { m_testViewClip = value; }
-		}
-		public Camera[] camerasForViewClipTest
-		{
-			get { return m_camerasForViewClipTest; }
-			set { m_camerasForViewClipTest = value; }
-		}
-		public float cameraNearClipPlane
-		{
-			get {
-				if (m_camera == null) {
-					Initialize();
-				}
-				return m_camera.nearClipPlane;
-			}
-			set {
-				if (m_camera == null) {
-					Initialize();
-				}
-				m_camera.nearClipPlane = value;
-			}
-		}
-		public LayerMask cameraCullingMask
-		{
-			get {
-				if (m_camera == null) {
-					Initialize();
-				}
-				return m_camera.cullingMask;
-			}
-			set {
-				if (m_camera == null) {
-					Initialize();
-				}
-				m_camera.cullingMask = value;
-			}
-		}
-		public void SetReplacementShader(Shader shader, string replacementTag)
-		{
-			if (m_camera == null) {
-				Initialize();
-			}
-			if (shader != null) {
-				m_camera.SetReplacementShader(shader, replacementTag);
-			}
-			else {
-				m_camera.ResetReplacementShader();
-			}
-		}
+        // public properties
+        public TextureMultiSample multiSampling
+        {
+            get { return m_multiSampling; }
+            set
+            {
+                if (m_multiSampling != value)
+                {
+                    m_multiSampling = value;
+                    SetTexturePropertyDirty();
+                }
+            }
+        }
+        public TextureSuperSample superSampling
+        {
+            get { return m_superSampling; }
+            set
+            {
+                if (m_superSampling != value)
+                {
+                    bool b = useIntermediateTexture;
+                    m_superSampling = value;
+                    if (b != useIntermediateTexture && m_multiSampling != TextureMultiSample.x1)
+                    {
+                        SetTexturePropertyDirty();
+                    }
+                }
+            }
+        }
+        public int textureWidth
+        {
+            get { return m_textureWidth; }
+            set
+            {
+                if (m_textureWidth != value)
+                {
+                    m_textureWidth = value;
+                    SetTexturePropertyDirty();
+                }
+            }
+        }
+        public int textureHeight
+        {
+            get { return m_textureHeight; }
+            set
+            {
+                if (m_textureHeight != value)
+                {
+                    m_textureHeight = value;
+                    SetTexturePropertyDirty();
+                }
+            }
+        }
+        public int mipLevel
+        {
+            get { return m_mipLevel; }
+            set
+            {
+                if (m_mipLevel != value)
+                {
+                    if (m_mipLevel == 0 || value == 0)
+                    {
+                        SetTexturePropertyDirty();
+                    }
+                    m_mipLevel = value;
+                }
+            }
+        }
+        public int blurLevel
+        {
+            get { return m_blurLevel; }
+            set
+            {
+                if (m_blurLevel != value)
+                {
+                    bool b = useIntermediateTexture;
+                    m_blurLevel = value;
+                    if (b != useIntermediateTexture && m_multiSampling != TextureMultiSample.x1)
+                    {
+                        SetTexturePropertyDirty();
+                    }
+                }
+            }
+        }
+        public float blurSize
+        {
+            get { return m_blurSize; }
+            set { m_blurSize = value; }
+        }
+        public BlurFilter blurFilter
+        {
+            get { return m_blurFilter; }
+            set { m_blurFilter = value; }
+        }
+        public float mipmapBlurSize
+        {
+            get { return m_mipmapBlurSize; }
+            set
+            {
+                m_mipmapBlurSize = value;
+            }
+        }
+        public bool singlePassMipmapBlur
+        {
+            get { return m_singlePassMipmapBlur; }
+            set { m_singlePassMipmapBlur = value; }
+        }
+        public MipmapFalloff mipmapFalloff
+        {
+            get { return m_mipmapFalloff; }
+            set
+            {
+                m_mipmapFalloff = value;
+            }
+        }
+        public float[] customMipmapFalloff
+        {
+            get { return m_customMipmapFalloff; }
+            set
+            {
+                m_customMipmapFalloff = value;
+            }
+        }
+        public Color shadowColor
+        {
+            get { return m_shadowColor; }
+            set
+            {
+                if (m_shadowColor != value)
+                {
+                    bool b = useIntermediateTexture;
+                    m_shadowColor = value;
+                    if (b != useIntermediateTexture && m_multiSampling != TextureMultiSample.x1)
+                    {
+                        SetTexturePropertyDirty();
+                    }
+                }
+            }
+        }
+        public Material blurShader
+        {
+            get { return m_blurShader; }
+            set
+            {
+                m_blurShader = value;
+            }
+        }
+        public Material downsampleShader
+        {
+            get { return m_downsampleShader; }
+            set { m_downsampleShader = value; }
+        }
+        public Material copyMipmapShader
+        {
+            get { return m_copyMipmapShader; }
+            set
+            {
+                m_copyMipmapShader = value;
+            }
+        }
+        public Material eraseShadowShader
+        {
+            get { return m_eraseShadowShader; }
+            set { m_eraseShadowShader = value; }
+        }
+        public RenderTexture shadowTexture
+        {
+            get { return m_shadowTexture; }
+        }
+        public bool testViewClip
+        {
+            get { return m_testViewClip; }
+            set { m_testViewClip = value; }
+        }
+        public Camera[] camerasForViewClipTest
+        {
+            get { return m_camerasForViewClipTest; }
+            set { m_camerasForViewClipTest = value; }
+        }
+        public float cameraNearClipPlane
+        {
+            get
+            {
+                if (m_camera == null)
+                {
+                    Initialize();
+                }
+                return m_camera.nearClipPlane;
+            }
+            set
+            {
+                if (m_camera == null)
+                {
+                    Initialize();
+                }
+                m_camera.nearClipPlane = value;
+            }
+        }
+        public LayerMask cameraCullingMask
+        {
+            get
+            {
+                if (m_camera == null)
+                {
+                    Initialize();
+                }
+                return m_camera.cullingMask;
+            }
+            set
+            {
+                if (m_camera == null)
+                {
+                    Initialize();
+                }
+                m_camera.cullingMask = value;
+            }
+        }
+        public void SetReplacementShader(Shader shader, string replacementTag)
+        {
+            if (m_camera == null)
+            {
+                Initialize();
+            }
+            if (shader != null)
+            {
+                m_camera.SetReplacementShader(shader, replacementTag);
+            }
+            else
+            {
+                m_camera.ResetReplacementShader();
+            }
+        }
 
-		private static int s_falloffParamID;
-		private static int s_blurOffsetHParamID;
-		private static int s_blurOffsetVParamID;
-		private static int s_blurWeightHParamID;
-		private static int s_blurWeightVParamID;
-		private static int s_downSampleBlurOffset0ParamID;
-		private static int s_downSampleBlurOffset1ParamID;
-		private static int s_downSampleBlurOffset2ParamID;
-		private static int s_downSampleBlurOffset3ParamID;
-		private static int s_downSampleBlurWeightParamID;
-		private Projector m_projector;
-		private Material m_projectorMaterial;
-		private CommandBuffer m_commandBuffer;
-		private RenderTexture m_shadowTexture;
-		[SerializeField][HideInInspector]
-		private Camera m_camera;
-		private bool m_isTexturePropertyChanged;
-		private bool m_isVisible = false;
-		private bool m_shadowTextureValid = false;
+        private static int s_falloffParamID;
+        private static int s_blurOffsetHParamID;
+        private static int s_blurOffsetVParamID;
+        private static int s_blurWeightHParamID;
+        private static int s_blurWeightVParamID;
+        private static int s_downSampleBlurOffset0ParamID;
+        private static int s_downSampleBlurOffset1ParamID;
+        private static int s_downSampleBlurOffset2ParamID;
+        private static int s_downSampleBlurOffset3ParamID;
+        private static int s_downSampleBlurWeightParamID;
+        private Projector m_projector;
+        private Material m_projectorMaterial;
+        private CommandBuffer m_commandBuffer;
+        private RenderTexture m_shadowTexture;
+        [SerializeField]
+        [HideInInspector]
+        private Camera m_camera;
+        private bool m_isTexturePropertyChanged;
+        private bool m_isVisible = false;
+        private bool m_shadowTextureValid = false;
 
-		public bool isProjectorVisible
-		{
-			get { return m_isVisible; }
-		}
+        public bool isProjectorVisible
+        {
+            get { return m_isVisible; }
+        }
 
-		// Call SetCommandBufferDirty or UpdateCommandBuffer when child objects are added/deleted/disabled/enabled.
-		public void SetTexturePropertyDirty()
-		{
-			m_isTexturePropertyChanged = true;
-		}
-		public void CreateRenderTexture()
-		{
-			if (m_textureWidth <= 0 || m_textureHeight <= 0 || m_projector == null) {
-				return;
-			}
-			// choose a texture format
-			RenderTextureFormat textureFormat = RenderTextureFormat.ARGB32;
-			if (m_preferredTextureFormats != null && 0 < m_preferredTextureFormats.Length) {
-				foreach (RenderTextureFormat format in m_preferredTextureFormats) {
-					if (SystemInfo.SupportsRenderTextureFormat(textureFormat)) {
-						textureFormat = format;
-					}
-				}
-			}
-			// create texture
-			if (m_shadowTexture != null) {
-				if (m_camera != null) {
-					m_camera.targetTexture = null;
-				}
-				DestroyImmediate(m_shadowTexture);
-			}
-			m_shadowTexture = new RenderTexture(m_textureWidth, m_textureHeight, 0, textureFormat, RenderTextureReadWrite.Linear);
-			if (useIntermediateTexture) {
-				m_shadowTexture.antiAliasing = 1;
-			}
-			else {
-				m_shadowTexture.antiAliasing = (int)m_multiSampling;
-			}
-			if (0 < m_mipLevel) {
-				m_shadowTexture.useMipMap = true;
+        // Call SetCommandBufferDirty or UpdateCommandBuffer when child objects are added/deleted/disabled/enabled.
+        public void SetTexturePropertyDirty()
+        {
+            m_isTexturePropertyChanged = true;
+        }
+        public void CreateRenderTexture()
+        {
+            if (m_textureWidth <= 0 || m_textureHeight <= 0 || m_projector == null)
+            {
+                return;
+            }
+            // choose a texture format
+            RenderTextureFormat textureFormat = RenderTextureFormat.ARGB32;
+            if (m_preferredTextureFormats != null && 0 < m_preferredTextureFormats.Length)
+            {
+                foreach (RenderTextureFormat format in m_preferredTextureFormats)
+                {
+                    if (SystemInfo.SupportsRenderTextureFormat(textureFormat))
+                    {
+                        textureFormat = format;
+                    }
+                }
+            }
+            // create texture
+            if (m_shadowTexture != null)
+            {
+                if (m_camera != null)
+                {
+                    m_camera.targetTexture = null;
+                }
+                DestroyImmediate(m_shadowTexture);
+            }
+            m_shadowTexture = new RenderTexture(m_textureWidth, m_textureHeight, 0, textureFormat, RenderTextureReadWrite.Linear);
+            if (useIntermediateTexture)
+            {
+                m_shadowTexture.antiAliasing = 1;
+            }
+            else
+            {
+                m_shadowTexture.antiAliasing = (int)m_multiSampling;
+            }
+            if (0 < m_mipLevel)
+            {
+                m_shadowTexture.useMipMap = true;
 #if UNITY_5_5_OR_NEWER
-				m_shadowTexture.autoGenerateMips = false;
+                m_shadowTexture.autoGenerateMips = false;
 #else
 				m_shadowTexture.generateMips = false;
 #endif
-				m_shadowTexture.mipMapBias = 0.0f;
-				m_shadowTexture.filterMode = FilterMode.Trilinear;
-			}
-			else {
-				m_shadowTexture.useMipMap = false;
-				m_shadowTexture.filterMode = FilterMode.Bilinear;
-			}
-			m_shadowTexture.wrapMode = TextureWrapMode.Clamp;
-			m_shadowTexture.Create();
-			m_shadowTextureValid = false;
-			if (m_projector.material != null) {
-				m_projector.material.SetTexture("_ShadowTex", m_shadowTexture);
-				m_projector.material.SetFloat("_DSPMipLevel", m_mipLevel);
-			}
-			if (m_camera != null) {
-				m_camera.targetTexture = m_shadowTexture;
-			}
-			m_isTexturePropertyChanged = false;
-		}
-		public void AddCommandBuffer(CommandBuffer commandBuffer)
-		{
-			m_camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, commandBuffer); // just in case
-			m_camera.AddCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, commandBuffer);
-		}
+                m_shadowTexture.mipMapBias = 0.0f;
+                m_shadowTexture.filterMode = FilterMode.Trilinear;
+            }
+            else
+            {
+                m_shadowTexture.useMipMap = false;
+                m_shadowTexture.filterMode = FilterMode.Bilinear;
+            }
+            m_shadowTexture.wrapMode = TextureWrapMode.Clamp;
+            m_shadowTexture.Create();
+            m_shadowTextureValid = false;
+            if (m_projector.material != null)
+            {
+                m_projector.material.SetTexture("_ShadowTex", m_shadowTexture);
+                m_projector.material.SetFloat("_DSPMipLevel", m_mipLevel);
+            }
+            if (m_camera != null)
+            {
+                m_camera.targetTexture = m_shadowTexture;
+            }
+            m_isTexturePropertyChanged = false;
+        }
+        public void AddCommandBuffer(CommandBuffer commandBuffer)
+        {
+            m_camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, commandBuffer); // just in case
+            m_camera.AddCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, commandBuffer);
+        }
 
-		public void RemoveCommandBuffer(CommandBuffer commandBuffer)
-		{
-			m_camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, commandBuffer);
-		}
+        public void RemoveCommandBuffer(CommandBuffer commandBuffer)
+        {
+            m_camera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, commandBuffer);
+        }
 
-		static void InitializeShaderPropertyIDs()
-		{
-			s_falloffParamID = Shader.PropertyToID("_Falloff");
-			s_blurOffsetHParamID = Shader.PropertyToID("_OffsetH");
-			s_blurOffsetVParamID = Shader.PropertyToID("_OffsetV");
-			s_blurWeightHParamID = Shader.PropertyToID("_WeightH");
-			s_blurWeightVParamID = Shader.PropertyToID("_WeightV");
-			s_downSampleBlurOffset0ParamID = Shader.PropertyToID("_Offset0");
-			s_downSampleBlurOffset1ParamID = Shader.PropertyToID("_Offset1");
-			s_downSampleBlurOffset2ParamID = Shader.PropertyToID("_Offset2");
-			s_downSampleBlurOffset3ParamID = Shader.PropertyToID("_Offset3");
-			s_downSampleBlurWeightParamID = Shader.PropertyToID("_Weight");
-		}
+        static void InitializeShaderPropertyIDs()
+        {
+            s_falloffParamID = Shader.PropertyToID("_Falloff");
+            s_blurOffsetHParamID = Shader.PropertyToID("_OffsetH");
+            s_blurOffsetVParamID = Shader.PropertyToID("_OffsetV");
+            s_blurWeightHParamID = Shader.PropertyToID("_WeightH");
+            s_blurWeightVParamID = Shader.PropertyToID("_WeightV");
+            s_downSampleBlurOffset0ParamID = Shader.PropertyToID("_Offset0");
+            s_downSampleBlurOffset1ParamID = Shader.PropertyToID("_Offset1");
+            s_downSampleBlurOffset2ParamID = Shader.PropertyToID("_Offset2");
+            s_downSampleBlurOffset3ParamID = Shader.PropertyToID("_Offset3");
+            s_downSampleBlurWeightParamID = Shader.PropertyToID("_Weight");
+        }
 
-		bool useIntermediateTexture
-		{
-			get {
-				return m_superSampling != TextureSuperSample.x1 || 0 < m_blurLevel || HasShadowColor() || (0 < m_mipLevel && m_multiSampling != TextureMultiSample.x1);
-			}
-		}
-		bool Initialize()
-		{
-			m_isVisible = false;
-			if (IsInitialized()) { 
-				return true;
-			}
-			m_isTexturePropertyChanged = true;
-			InitializeShaderPropertyIDs();
-			m_projector = GetComponent<Projector>();
-			CloneProjectorMaterialIfShared();
-			if (m_camera == null) {
-				m_camera = gameObject.GetComponent<Camera>();
-				if (m_camera == null) {
-					m_camera = gameObject.AddComponent<Camera>();
-				}
-				m_camera.hideFlags = HideFlags.HideInInspector;
-			}
-			else {
-				m_camera.RemoveAllCommandBuffers();
-			}
-			m_camera.depth = -100;
-			m_camera.cullingMask = 0;
-			m_camera.clearFlags = CameraClearFlags.Nothing;
-			m_camera.backgroundColor = new Color(1,1,1,0);
-			m_camera.useOcclusionCulling = false;
-			m_camera.renderingPath = RenderingPath.Forward;
-			m_camera.nearClipPlane = 0.01f;
+        bool useIntermediateTexture
+        {
+            get
+            {
+                return m_superSampling != TextureSuperSample.x1 || 0 < m_blurLevel || HasShadowColor() || (0 < m_mipLevel && m_multiSampling != TextureMultiSample.x1);
+            }
+        }
+        bool Initialize()
+        {
+            m_isVisible = false;
+            if (IsInitialized())
+            {
+                return true;
+            }
+            m_isTexturePropertyChanged = true;
+            InitializeShaderPropertyIDs();
+            m_projector = GetComponent<Projector>();
+            CloneProjectorMaterialIfShared();
+            if (m_camera == null)
+            {
+                m_camera = gameObject.GetComponent<Camera>();
+                if (m_camera == null)
+                {
+                    m_camera = gameObject.AddComponent<Camera>();
+                }
+                m_camera.hideFlags = HideFlags.HideInInspector;
+            }
+            else
+            {
+                m_camera.RemoveAllCommandBuffers();
+            }
+            m_camera.depth = -100;
+            m_camera.cullingMask = 0;
+            m_camera.clearFlags = CameraClearFlags.Nothing;
+            m_camera.backgroundColor = new Color(1, 1, 1, 0);
+            m_camera.useOcclusionCulling = false;
+            m_camera.renderingPath = RenderingPath.Forward;
+            m_camera.nearClipPlane = 0.01f;
 #if UNITY_5_6_OR_NEWER
-			m_camera.forceIntoRenderTexture = true;
+            m_camera.forceIntoRenderTexture = true;
 #endif
-			m_camera.enabled = true;
-			CreateRenderTexture();
-			return true;
-		}
+            m_camera.enabled = true;
+            CreateRenderTexture();
+            return true;
+        }
 
-		bool IsInitialized()
-		{
-			return m_projector != null && m_camera != null;
-		}
+        bool IsInitialized()
+        {
+            return m_projector != null && m_camera != null;
+        }
 
-		void Awake()
-		{
-			Initialize();
-		}
+        void Awake()
+        {
+            Initialize();
+        }
 
-		void OnEnable()
-		{
-			if (m_camera != null) {
-				m_camera.enabled = true;
-			}
-		}
+        void OnEnable()
+        {
+            if (m_camera != null)
+            {
+                m_camera.enabled = true;
+            }
+        }
 
-		void OnDisable()
-		{
-			if (m_camera != null) {
-				m_camera.enabled = false;
-			}
-		}
+        void OnDisable()
+        {
+            if (m_camera != null)
+            {
+                m_camera.enabled = false;
+            }
+        }
 
-		void Start()
-		{
+        void Start()
+        {
 #if UNITY_EDITOR
-			if (m_testViewClip && Application.isPlaying)
+            if (m_testViewClip && Application.isPlaying)
 #else
 			if (m_testViewClip)
 #endif
-			{
-				if (m_camerasForViewClipTest == null || m_camerasForViewClipTest.Length == 0) {
-					if (Camera.main != null) {
-						m_camerasForViewClipTest = new Camera[1] {Camera.main};
-					}
-				}
-			}
-		}
+            {
+                if (m_camerasForViewClipTest == null || m_camerasForViewClipTest.Length == 0)
+                {
+                    if (Camera.main != null)
+                    {
+                        m_camerasForViewClipTest = new Camera[1] { Camera.main };
+                    }
+                }
+            }
+        }
 
-		void OnValidate()
-		{
-			CreateRenderTexture();
-			InitializeShaderPropertyIDs();
-			// check custom mipmap falloff
-			if (m_mipmapFalloff == MipmapFalloff.Custom && 0 < m_mipLevel) {
-				if (m_customMipmapFalloff == null || m_customMipmapFalloff.Length == 0) {
-					m_customMipmapFalloff = new float[m_mipLevel];
-					for (int i = 0; i < m_mipLevel; ++i) {
-						m_customMipmapFalloff[i] = ((float)(m_mipLevel - i))/(float)(m_mipLevel + 1);
-					}
-				}
-				else if (m_mipLevel != m_customMipmapFalloff.Length) {
-					float[] customFalloff = new float[m_mipLevel];
-					for (int i = 0; i < m_mipLevel; ++i) {
-						float oldIndex = ((float)(m_customMipmapFalloff.Length + 1)*(i + 1))/(float)(m_mipLevel + 1);
-						int j = Mathf.FloorToInt(oldIndex);
-						float w = oldIndex - j;
-						float v0 = (j == 0 ? 1.0f : m_customMipmapFalloff[j - 1]);
-						float v1 = (j < m_customMipmapFalloff.Length) ? m_customMipmapFalloff[j] : 0.0f;
-						customFalloff[i] = Mathf.Lerp(v0, v1, w);
-					}
-					m_customMipmapFalloff = customFalloff;
-				}
-			}
-		}
-		private static HashSet<Material> s_sharedMaterials;
-		const HideFlags CLONED_MATERIAL_HIDE_FLAGS = HideFlags.HideAndDontSave;
-		void CloneProjectorMaterialIfShared()
-		{
+        void OnValidate()
+        {
+            CreateRenderTexture();
+            InitializeShaderPropertyIDs();
+            // check custom mipmap falloff
+            if (m_mipmapFalloff == MipmapFalloff.Custom && 0 < m_mipLevel)
+            {
+                if (m_customMipmapFalloff == null || m_customMipmapFalloff.Length == 0)
+                {
+                    m_customMipmapFalloff = new float[m_mipLevel];
+                    for (int i = 0; i < m_mipLevel; ++i)
+                    {
+                        m_customMipmapFalloff[i] = ((float)(m_mipLevel - i)) / (float)(m_mipLevel + 1);
+                    }
+                }
+                else if (m_mipLevel != m_customMipmapFalloff.Length)
+                {
+                    float[] customFalloff = new float[m_mipLevel];
+                    for (int i = 0; i < m_mipLevel; ++i)
+                    {
+                        float oldIndex = ((float)(m_customMipmapFalloff.Length + 1) * (i + 1)) / (float)(m_mipLevel + 1);
+                        int j = Mathf.FloorToInt(oldIndex);
+                        float w = oldIndex - j;
+                        float v0 = (j == 0 ? 1.0f : m_customMipmapFalloff[j - 1]);
+                        float v1 = (j < m_customMipmapFalloff.Length) ? m_customMipmapFalloff[j] : 0.0f;
+                        customFalloff[i] = Mathf.Lerp(v0, v1, w);
+                    }
+                    m_customMipmapFalloff = customFalloff;
+                }
+            }
+        }
+        private static HashSet<Material> s_sharedMaterials;
+        const HideFlags CLONED_MATERIAL_HIDE_FLAGS = HideFlags.HideAndDontSave;
+        void CloneProjectorMaterialIfShared()
+        {
 #if UNITY_EDITOR
-			if (!Application.isPlaying) {
-				return;
-			}
+            if (!Application.isPlaying)
+            {
+                return;
+            }
 #endif
-			if (m_projector.material == null || (m_projector.material.hideFlags == CLONED_MATERIAL_HIDE_FLAGS && m_projector.material == m_projectorMaterial)) {
-				return;
-			}
-			if (m_projectorMaterial != null && m_projectorMaterial.hideFlags == CLONED_MATERIAL_HIDE_FLAGS) {
-				DestroyImmediate(m_projectorMaterial);
-			}
-			if (s_sharedMaterials == null) {
-				s_sharedMaterials = new HashSet<Material>();
-			}
-			if (s_sharedMaterials.Contains(m_projector.material)) {
-				m_projector.material = new Material(m_projector.material);
-				m_projector.material.hideFlags = CLONED_MATERIAL_HIDE_FLAGS;
-			}
-			else {
-				s_sharedMaterials.Add(m_projector.material);
-			}
-			m_projectorMaterial = m_projector.material;
-		}
+            if (m_projector.material == null || (m_projector.material.hideFlags == CLONED_MATERIAL_HIDE_FLAGS && m_projector.material == m_projectorMaterial))
+            {
+                return;
+            }
+            if (m_projectorMaterial != null && m_projectorMaterial.hideFlags == CLONED_MATERIAL_HIDE_FLAGS)
+            {
+                DestroyImmediate(m_projectorMaterial);
+            }
+            if (s_sharedMaterials == null)
+            {
+                s_sharedMaterials = new HashSet<Material>();
+            }
+            if (s_sharedMaterials.Contains(m_projector.material))
+            {
+                m_projector.material = new Material(m_projector.material);
+                m_projector.material.hideFlags = CLONED_MATERIAL_HIDE_FLAGS;
+            }
+            else
+            {
+                s_sharedMaterials.Add(m_projector.material);
+            }
+            m_projectorMaterial = m_projector.material;
+        }
 
-		void OnDestroy()
-		{
-			if (m_projectorMaterial != null) {
-				if (s_sharedMaterials != null && s_sharedMaterials.Contains(m_projectorMaterial)) {
-					s_sharedMaterials.Remove(m_projectorMaterial);
-				}
-				if (m_projectorMaterial.hideFlags == CLONED_MATERIAL_HIDE_FLAGS) {
-					if (m_projector.material == m_projectorMaterial) {
-						m_projector.material = null;
-					}
-					DestroyImmediate(m_projectorMaterial);
-				}
-			}
-			if (m_shadowTexture != null) {
-				if (m_camera != null) {
-					m_camera.targetTexture = null;
-				}
-				DestroyImmediate(m_shadowTexture);
-				m_shadowTexture = null;
-			}
-			if (m_camera != null) {
-				m_camera.RemoveAllCommandBuffers();
-			}
-			m_isVisible = false;
-		}
+        void OnDestroy()
+        {
+            if (m_projectorMaterial != null)
+            {
+                if (s_sharedMaterials != null && s_sharedMaterials.Contains(m_projectorMaterial))
+                {
+                    s_sharedMaterials.Remove(m_projectorMaterial);
+                }
+                if (m_projectorMaterial.hideFlags == CLONED_MATERIAL_HIDE_FLAGS)
+                {
+                    if (m_projector.material == m_projectorMaterial)
+                    {
+                        m_projector.material = null;
+                    }
+                    DestroyImmediate(m_projectorMaterial);
+                }
+            }
+            if (m_shadowTexture != null)
+            {
+                if (m_camera != null)
+                {
+                    m_camera.targetTexture = null;
+                }
+                DestroyImmediate(m_shadowTexture);
+                m_shadowTexture = null;
+            }
+            if (m_camera != null)
+            {
+                m_camera.RemoveAllCommandBuffers();
+            }
+            m_isVisible = false;
+        }
 
-		bool IsReadyToExecute()
-		{
-			if (m_textureWidth <= 0 || m_textureHeight <= 0 || m_eraseShadowShader == null) {
-				return false;
-			}
-			if (0 < m_mipLevel || m_superSampling != TextureSuperSample.x1) {
-				if (m_downsampleShader == null) {
-					return false;
-				}
-			}
-			if (0 < m_blurLevel || (0.0f < m_mipmapBlurSize && 0 < m_mipLevel)) {
-				if (m_blurShader == null) {
-					return false;
-				}
-			}
-			if (0 < m_mipLevel && (m_copyMipmapShader == null || m_downsampleShader == null)) {
-				return false;
-			}
-			return true;
-		}
+        bool IsReadyToExecute()
+        {
+            if (m_textureWidth <= 0 || m_textureHeight <= 0 || m_eraseShadowShader == null)
+            {
+                return false;
+            }
+            if (0 < m_mipLevel || m_superSampling != TextureSuperSample.x1)
+            {
+                if (m_downsampleShader == null)
+                {
+                    return false;
+                }
+            }
+            if (0 < m_blurLevel || (0.0f < m_mipmapBlurSize && 0 < m_mipLevel))
+            {
+                if (m_blurShader == null)
+                {
+                    return false;
+                }
+            }
+            if (0 < m_mipLevel && (m_copyMipmapShader == null || m_downsampleShader == null))
+            {
+                return false;
+            }
+            return true;
+        }
 
-		void SetVisible(bool isVisible)
-		{
-			m_isVisible = isVisible;
-			SendMessage("OnVisibilityChanged", isVisible);
-		}
+        void SetVisible(bool isVisible)
+        {
+            m_isVisible = isVisible;
+            SendMessage("OnVisibilityChanged", isVisible);
+        }
 
 #if UNITY_EDITOR
-		private bool m_isRenderingFromUpdate = false;
-		public void ForceRenderTexture()
-		{
-			m_isRenderingFromUpdate = true;
-			// it is necessary to set camera parameters before Render, because render events will not be invoked if the volume of the view frustum is zero,
-			// and there is no chance to fix the camera parameters in OnPreCull function.
-			m_camera.orthographic = m_projector.orthographic;
-			m_camera.orthographicSize = m_projector.orthographicSize;
-			m_camera.fieldOfView = m_projector.fieldOfView;
-			m_camera.aspect = m_projector.aspectRatio;
-			m_camera.farClipPlane = m_projector.farClipPlane;
+        private bool m_isRenderingFromUpdate = false;
+        public void ForceRenderTexture()
+        {
+            m_isRenderingFromUpdate = true;
+            // it is necessary to set camera parameters before Render, because render events will not be invoked if the volume of the view frustum is zero,
+            // and there is no chance to fix the camera parameters in OnPreCull function.
+            m_camera.orthographic = m_projector.orthographic;
+            m_camera.orthographicSize = m_projector.orthographicSize;
+            m_camera.fieldOfView = m_projector.fieldOfView;
+            m_camera.aspect = m_projector.aspectRatio;
+            m_camera.farClipPlane = m_projector.farClipPlane;
 #if UNITY_5_6
-			// workaround for Unity 5.6
-			// Unity 5.6 has a bug whereby a temporary render texture does not work if m_camera.targetTexture != null. This bug is fixed in Unity 2017.
-			m_camera.targetTexture = null;
+            // workaround for Unity 5.6
+            // Unity 5.6 has a bug whereby a temporary render texture does not work if m_camera.targetTexture != null. This bug is fixed in Unity 2017.
+            m_camera.targetTexture = null;
 #endif
-			m_camera.Render();
-			m_isRenderingFromUpdate = false;
-		}
+            m_camera.Render();
+            m_isRenderingFromUpdate = false;
+        }
 #endif
-		void Update()
-		{
+        void Update()
+        {
 #if UNITY_EDITOR
-			if (!Application.isPlaying
-				&& (!m_shadowTextureValid
-					|| m_camera.orthographic != m_projector.orthographic
-					|| m_camera.orthographicSize != m_projector.orthographicSize
-					|| m_camera.fieldOfView != m_projector.fieldOfView
-					|| m_camera.aspect != m_projector.aspectRatio
-					|| m_camera.farClipPlane != m_projector.farClipPlane)
-			) {
-				ForceRenderTexture();
-			}
+            if (!Application.isPlaying
+                && (!m_shadowTextureValid
+                    || m_camera.orthographic != m_projector.orthographic
+                    || m_camera.orthographicSize != m_projector.orthographicSize
+                    || m_camera.fieldOfView != m_projector.fieldOfView
+                    || m_camera.aspect != m_projector.aspectRatio
+                    || m_camera.farClipPlane != m_projector.farClipPlane)
+            )
+            {
+                ForceRenderTexture();
+            }
 #endif
-			if (m_camera != null && !m_camera.enabled) {
-				m_camera.enabled = true;
-			}
-		}
+            if (m_camera != null && !m_camera.enabled)
+            {
+                m_camera.enabled = true;
+            }
+        }
 
-		void OnPreCull()
-		{
-			if (m_projector.material != m_projectorMaterial) {
-				// projector material changed.
-				CloneProjectorMaterialIfShared();
-				m_projector.material.SetTexture("_ShadowTex", m_shadowTexture);
-				m_projector.material.SetFloat("_DSPMipLevel", m_mipLevel);
-			}
+        void OnPreCull()
+        {
+            if (m_projector.material != m_projectorMaterial)
+            {
+                // projector material changed.
+                CloneProjectorMaterialIfShared();
+                m_projector.material.SetTexture("_ShadowTex", m_shadowTexture);
+                m_projector.material.SetFloat("_DSPMipLevel", m_mipLevel);
+            }
 #if UNITY_EDITOR
-			if (!(Application.isPlaying || m_isRenderingFromUpdate)) {
-				m_camera.enabled = false;
-				return;
-			}
-			if (!IsReadyToExecute()) {
-				m_camera.enabled = false;
-				return;
-			}
-			if (!IsInitialized() && !Initialize()) {
-				m_camera.enabled = false;
-				return;
-			}
-			if (m_projector.material == null) {
-				if (m_isVisible) {
-					SetVisible(false);
-				}
-				m_camera.enabled = false;
-				return;
-			}
-			m_projector.material.SetTexture("_ShadowTex", m_shadowTexture);
-			m_projector.material.SetFloat("_DSPMipLevel", m_mipLevel);
+            if (!(Application.isPlaying || m_isRenderingFromUpdate))
+            {
+                m_camera.enabled = false;
+                return;
+            }
+            if (!IsReadyToExecute())
+            {
+                m_camera.enabled = false;
+                return;
+            }
+            if (!IsInitialized() && !Initialize())
+            {
+                m_camera.enabled = false;
+                return;
+            }
+            if (m_projector.material == null)
+            {
+                if (m_isVisible)
+                {
+                    SetVisible(false);
+                }
+                m_camera.enabled = false;
+                return;
+            }
+            m_projector.material.SetTexture("_ShadowTex", m_shadowTexture);
+            m_projector.material.SetFloat("_DSPMipLevel", m_mipLevel);
 #endif
-			if (m_isTexturePropertyChanged) {
-				CreateRenderTexture();
-			}
-			m_camera.orthographic = m_projector.orthographic;
-			m_camera.orthographicSize = m_projector.orthographicSize;
-			m_camera.fieldOfView = m_projector.fieldOfView;
-			m_camera.aspect = m_projector.aspectRatio;
-			m_camera.farClipPlane = m_projector.farClipPlane;
-			// view clip test
-			bool isVisible = true;
-			if (!m_projector.enabled) {
-				isVisible = false;
-			}
+            if (m_isTexturePropertyChanged)
+            {
+                CreateRenderTexture();
+            }
+            m_camera.orthographic = m_projector.orthographic;
+            m_camera.orthographicSize = m_projector.orthographicSize;
+            m_camera.fieldOfView = m_projector.fieldOfView;
+            m_camera.aspect = m_projector.aspectRatio;
+            m_camera.farClipPlane = m_projector.farClipPlane;
+            // view clip test
+            bool isVisible = true;
+            if (!m_projector.enabled)
+            {
+                isVisible = false;
+            }
 #if UNITY_EDITOR
-			else if (m_testViewClip && Application.isPlaying)
+            else if (m_testViewClip && Application.isPlaying)
 #else
 			else if (m_testViewClip)
 #endif
-			{
-				if (m_camerasForViewClipTest == null || m_camerasForViewClipTest.Length == 0) {
-					if (Camera.main != null) {
-						m_camerasForViewClipTest = new Camera[1] {Camera.main};
-					}
-				}
-				if (m_camerasForViewClipTest != null && 0 < m_camerasForViewClipTest.Length) {
-					Vector3 v0 = m_camera.ViewportToWorldPoint(new Vector3(0,0,m_camera.nearClipPlane));
-					Vector3 v1 = m_camera.ViewportToWorldPoint(new Vector3(1,0,m_camera.nearClipPlane));
-					Vector3 v2 = m_camera.ViewportToWorldPoint(new Vector3(0,1,m_camera.nearClipPlane));
-					Vector3 v3 = m_camera.ViewportToWorldPoint(new Vector3(1,1,m_camera.nearClipPlane));
-					Vector3 v4 = m_camera.ViewportToWorldPoint(new Vector3(0,0,m_camera.farClipPlane));
-					Vector3 v5 = m_camera.ViewportToWorldPoint(new Vector3(1,0,m_camera.farClipPlane));
-					Vector3 v6 = m_camera.ViewportToWorldPoint(new Vector3(0,1,m_camera.farClipPlane));
-					Vector3 v7 = m_camera.ViewportToWorldPoint(new Vector3(1,1,m_camera.farClipPlane));
-					isVisible = false;
-					for (int i = 0; i < m_camerasForViewClipTest.Length; ++i) {
-						Camera cam = m_camerasForViewClipTest[i];
-						Vector3 min = cam.WorldToViewportPoint(v0);
-						if (min.z < 0.0f) { min.x = -min.x; min.y = -min.y; }
-						Vector3 max = min;
-						Vector3 v = cam.WorldToViewportPoint(v1);
-						if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
-						min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
-						max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
-						v = cam.WorldToViewportPoint(v2);
-						if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
-						min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
-						max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
-						v = cam.WorldToViewportPoint(v3);
-						if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
-						min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
-						max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
-						v = cam.WorldToViewportPoint(v4);
-						if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
-						min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
-						max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
-						v = cam.WorldToViewportPoint(v5);
-						if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
-						min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
-						max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
-						v = cam.WorldToViewportPoint(v6);
-						if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
-						min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
-						max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
-						v = cam.WorldToViewportPoint(v7);
-						if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
-						min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
-						max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
-						if (0.0f < max.x && min.x < 1.0f && 0.0f < max.y && min.y < 1.0f && cam.nearClipPlane < max.z && min.z < cam.farClipPlane) {
-							isVisible = true;
-							break;
-						}
-					}
-				}
-			}
-			if (isVisible != m_isVisible) {
-				SetVisible(isVisible);
-			}
-			if (!isVisible) {
-				if (m_camera != null) {
-					m_camera.enabled = false;
-				}
-				if (m_shadowTexture != null && !m_shadowTextureValid) {
-					RenderTexture currentRT = RenderTexture.active;
-					RenderTexture.active = m_shadowTexture;
-					GL.Clear(false, true, new Color(1,1,1,0));
-					m_shadowTextureValid = true;
-					RenderTexture.active = currentRT;
-				}
-			}
-		}
+            {
+                if (m_camerasForViewClipTest == null || m_camerasForViewClipTest.Length == 0)
+                {
+                    if (Camera.main != null)
+                    {
+                        m_camerasForViewClipTest = new Camera[1] { Camera.main };
+                    }
+                }
+                if (m_camerasForViewClipTest != null && 0 < m_camerasForViewClipTest.Length)
+                {
+                    Vector3 v0 = m_camera.ViewportToWorldPoint(new Vector3(0, 0, m_camera.nearClipPlane));
+                    Vector3 v1 = m_camera.ViewportToWorldPoint(new Vector3(1, 0, m_camera.nearClipPlane));
+                    Vector3 v2 = m_camera.ViewportToWorldPoint(new Vector3(0, 1, m_camera.nearClipPlane));
+                    Vector3 v3 = m_camera.ViewportToWorldPoint(new Vector3(1, 1, m_camera.nearClipPlane));
+                    Vector3 v4 = m_camera.ViewportToWorldPoint(new Vector3(0, 0, m_camera.farClipPlane));
+                    Vector3 v5 = m_camera.ViewportToWorldPoint(new Vector3(1, 0, m_camera.farClipPlane));
+                    Vector3 v6 = m_camera.ViewportToWorldPoint(new Vector3(0, 1, m_camera.farClipPlane));
+                    Vector3 v7 = m_camera.ViewportToWorldPoint(new Vector3(1, 1, m_camera.farClipPlane));
+                    isVisible = false;
+                    for (int i = 0; i < m_camerasForViewClipTest.Length; ++i)
+                    {
+                        Camera cam = m_camerasForViewClipTest[i];
+                        Vector3 min = cam.WorldToViewportPoint(v0);
+                        if (min.z < 0.0f) { min.x = -min.x; min.y = -min.y; }
+                        Vector3 max = min;
+                        Vector3 v = cam.WorldToViewportPoint(v1);
+                        if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
+                        min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
+                        max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
+                        v = cam.WorldToViewportPoint(v2);
+                        if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
+                        min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
+                        max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
+                        v = cam.WorldToViewportPoint(v3);
+                        if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
+                        min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
+                        max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
+                        v = cam.WorldToViewportPoint(v4);
+                        if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
+                        min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
+                        max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
+                        v = cam.WorldToViewportPoint(v5);
+                        if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
+                        min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
+                        max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
+                        v = cam.WorldToViewportPoint(v6);
+                        if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
+                        min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
+                        max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
+                        v = cam.WorldToViewportPoint(v7);
+                        if (v.z < 0.0f) { v.x = -v.x; v.y = -v.y; }
+                        min.x = Mathf.Min(min.x, v.x); min.y = Mathf.Min(min.y, v.y); min.z = Mathf.Min(min.z, v.z);
+                        max.x = Mathf.Max(max.x, v.x); max.y = Mathf.Max(max.y, v.y); max.z = Mathf.Max(max.z, v.z);
+                        if (0.0f < max.x && min.x < 1.0f && 0.0f < max.y && min.y < 1.0f && cam.nearClipPlane < max.z && min.z < cam.farClipPlane)
+                        {
+                            isVisible = true;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (isVisible != m_isVisible)
+            {
+                SetVisible(isVisible);
+            }
+            if (!isVisible)
+            {
+                if (m_camera != null)
+                {
+                    m_camera.enabled = false;
+                }
+                if (m_shadowTexture != null && !m_shadowTextureValid)
+                {
+                    RenderTexture currentRT = RenderTexture.active;
+                    RenderTexture.active = m_shadowTexture;
+                    GL.Clear(false, true, new Color(1, 1, 1, 0));
+                    m_shadowTextureValid = true;
+                    RenderTexture.active = currentRT;
+                }
+            }
+        }
 
-		bool HasShadowColor()
-		{
-			return m_shadowColor.a != 1 || (m_shadowColor.r + shadowColor.g + shadowColor.b) != 0;
-		}
+        bool HasShadowColor()
+        {
+            return m_shadowColor.a != 1 || (m_shadowColor.r + shadowColor.g + shadowColor.b) != 0;
+        }
 
-		void OnPreRender()
-		{
+        void OnPreRender()
+        {
 #if UNITY_EDITOR
-			if (!(Application.isPlaying || m_isRenderingFromUpdate)) {
-				return;
-			}
+            if (!(Application.isPlaying || m_isRenderingFromUpdate))
+            {
+                return;
+            }
 #endif
-			if (!m_isVisible) {
-				return;
-			}
-			m_shadowTexture.DiscardContents();
-			if (useIntermediateTexture) {
-				int width = m_textureWidth * (int)m_superSampling;
-				int height = m_textureHeight * (int)m_superSampling;
-				m_camera.targetTexture = RenderTexture.GetTemporary(width, height, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear, (int)m_multiSampling);
-				m_camera.targetTexture.filterMode = FilterMode.Bilinear;
-			}
-			else {
-				m_camera.targetTexture = m_shadowTexture;
-			}
-			m_camera.clearFlags = CameraClearFlags.SolidColor;
-		}
-		private const int MAX_BLUR_TAP_SIZE = 7;
-		private static float[] s_blurWeights = new float[MAX_BLUR_TAP_SIZE];
-		struct BlurParam {
-			public int tap;
-			public Vector4 offset;
-			public Vector4 weight;
-		};
-		static BlurParam GetBlurParam(float blurSize, BlurFilter filter)
-		{
-			BlurParam param = new BlurParam();
+            if (!m_isVisible)
+            {
+                return;
+            }
+            m_shadowTexture.DiscardContents();
+            if (useIntermediateTexture)
+            {
+                int width = m_textureWidth * (int)m_superSampling;
+                int height = m_textureHeight * (int)m_superSampling;
+                m_camera.targetTexture = RenderTexture.GetTemporary(width, height, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear, (int)m_multiSampling);
+                m_camera.targetTexture.filterMode = FilterMode.Bilinear;
+            }
+            else
+            {
+                m_camera.targetTexture = m_shadowTexture;
+            }
+            m_camera.clearFlags = CameraClearFlags.SolidColor;
+        }
+        private const int MAX_BLUR_TAP_SIZE = 7;
+        private static float[] s_blurWeights = new float[MAX_BLUR_TAP_SIZE];
+        struct BlurParam
+        {
+            public int tap;
+            public Vector4 offset;
+            public Vector4 weight;
+        };
+        static BlurParam GetBlurParam(float blurSize, BlurFilter filter)
+        {
+            BlurParam param = new BlurParam();
 
-			if (blurSize < 0.1f) {
-				param.tap = 3;
-				param.offset.x = 0.0f;
-				param.offset.y = 0.0f;
-				param.offset.z = 0.0f;
-				param.offset.w = 0.0f;
-				param.weight.x = 1.0f;
-				param.weight.y = 0.0f;
-				param.weight.z = 0.0f;
-				param.weight.w = 0.0f;
-				return param;
-			}
-			// calculate weights
-			if (filter == BlurFilter.Gaussian) {
-				// gaussian filter
-				float a = 1.0f/(2.0f*blurSize*blurSize);
-				float totalWeight = 1.0f;
-				s_blurWeights[0] = 1.0f;
-				for (int i = 1; i < s_blurWeights.Length; ++i) {
-					s_blurWeights[i] = Mathf.Exp(-i*i*a);
-					totalWeight += 2.0f*s_blurWeights[i];
-				}
-				float w = 1.0f/totalWeight;
-				for (int i = 0; i < s_blurWeights.Length; ++i) {
-					s_blurWeights[i] *= w;
-				}
-			}
-			else {
-				// uniform filter
-				float a = 0.5f/(0.5f + blurSize);
-				for (int i = 0; i < s_blurWeights.Length; ++i) {
-					if (i <= blurSize) {
-						s_blurWeights[i] = a;
-					}
-					else if (i - 1 < blurSize) {
-						s_blurWeights[i] = a * (blurSize - (i - 1));
-					}
-					else {
-						s_blurWeights[i] = 0.0f;
-					}
-				}
-			}
-			param.offset.x = 1.0f + s_blurWeights[2]/(s_blurWeights[1] + s_blurWeights[2]);
-			param.offset.y = 3.0f + s_blurWeights[4]/(s_blurWeights[3] + s_blurWeights[4]); 
-			param.offset.z = 5.0f + s_blurWeights[6]/(s_blurWeights[5] + s_blurWeights[6]);
-			param.offset.w = 0.0f;
+            if (blurSize < 0.1f)
+            {
+                param.tap = 3;
+                param.offset.x = 0.0f;
+                param.offset.y = 0.0f;
+                param.offset.z = 0.0f;
+                param.offset.w = 0.0f;
+                param.weight.x = 1.0f;
+                param.weight.y = 0.0f;
+                param.weight.z = 0.0f;
+                param.weight.w = 0.0f;
+                return param;
+            }
+            // calculate weights
+            if (filter == BlurFilter.Gaussian)
+            {
+                // gaussian filter
+                float a = 1.0f / (2.0f * blurSize * blurSize);
+                float totalWeight = 1.0f;
+                s_blurWeights[0] = 1.0f;
+                for (int i = 1; i < s_blurWeights.Length; ++i)
+                {
+                    s_blurWeights[i] = Mathf.Exp(-i * i * a);
+                    totalWeight += 2.0f * s_blurWeights[i];
+                }
+                float w = 1.0f / totalWeight;
+                for (int i = 0; i < s_blurWeights.Length; ++i)
+                {
+                    s_blurWeights[i] *= w;
+                }
+            }
+            else
+            {
+                // uniform filter
+                float a = 0.5f / (0.5f + blurSize);
+                for (int i = 0; i < s_blurWeights.Length; ++i)
+                {
+                    if (i <= blurSize)
+                    {
+                        s_blurWeights[i] = a;
+                    }
+                    else if (i - 1 < blurSize)
+                    {
+                        s_blurWeights[i] = a * (blurSize - (i - 1));
+                    }
+                    else
+                    {
+                        s_blurWeights[i] = 0.0f;
+                    }
+                }
+            }
+            param.offset.x = 1.0f + s_blurWeights[2] / (s_blurWeights[1] + s_blurWeights[2]);
+            param.offset.y = 3.0f + s_blurWeights[4] / (s_blurWeights[3] + s_blurWeights[4]);
+            param.offset.z = 5.0f + s_blurWeights[6] / (s_blurWeights[5] + s_blurWeights[6]);
+            param.offset.w = 0.0f;
 
-			if (s_blurWeights[3] < 0.02f) {
-				param.tap = 3;
-				float a = 0.5f/(0.5f*s_blurWeights[0] + s_blurWeights[1] + s_blurWeights[2]);
-				param.weight.x = Mathf.Round(255*a*s_blurWeights[0])/255.0f;
-				param.weight.y = 0.5f - 0.5f*param.weight.x;
-				param.weight.z = 0.0f;
-				param.weight.w = 0.0f;
-			}
-			else if (s_blurWeights[5] < 0.02f) {
-				param.tap = 5;
-				float a = 0.5f/(0.5f*s_blurWeights[0] + s_blurWeights[1] + s_blurWeights[2] + s_blurWeights[3] + s_blurWeights[4]);
-				param.weight.x = Mathf.Round(255*a*s_blurWeights[0])/255.0f;
-				param.weight.y = Mathf.Round(255*a*(s_blurWeights[1] + s_blurWeights[2]))/255.0f;
-				param.weight.z = 0.5f - (0.5f*param.weight.x + param.weight.y);
-				param.weight.w = 0.0f;
-			}
-			else {
-				param.tap = 7;
-				param.weight.x = Mathf.Round(255*s_blurWeights[0])/255.0f;
-				param.weight.y = Mathf.Round(255*(s_blurWeights[1] + s_blurWeights[2]))/255.0f;
-				param.weight.z = Mathf.Round(255*(s_blurWeights[3] + s_blurWeights[4]))/255.0f;
-				param.weight.w = 0.5f - (0.5f*param.weight.x + param.weight.y + param.weight.z);
-			}
-			return param;
-		}
-		static BlurParam GetDownsampleBlurParam(float blurSize, BlurFilter filter)
-		{
-			BlurParam param = new BlurParam();
-			param.tap = 4;
-			if (blurSize < 0.1f) {
-				param.offset.x = 0.0f;
-				param.offset.y = 0.0f;
-				param.offset.z = 0.0f;
-				param.offset.w = 0.0f;
-				param.weight.x = 1.0f;
-				param.weight.y = 0.0f;
-				param.weight.z = 0.0f;
-				param.weight.w = 0.0f;
-				return param;
-			}
-			// calculate weights
-			if (filter == BlurFilter.Gaussian) {
-				// gaussian filter
-				float a = 1.0f/(2.0f*blurSize*blurSize);
-				float totalWeight = 0.0f;
-				for (int i = 0; i < param.tap; ++i) {
-					float x = i + 0.5f;
-					s_blurWeights[i] = Mathf.Exp(-x*x*a);
-					totalWeight += 2.0f*s_blurWeights[i];
-				}
-				float w = 1.0f/totalWeight;
-				for (int i = 0; i < param.tap; ++i) {
-					s_blurWeights[i] *= w;
-				}
-			}
-			else {
-				// uniform filter
-				float a = 0.5f/blurSize;
-				for (int i = 0; i < param.tap; ++i) {
-					if (i + 1 <= blurSize) {
-						s_blurWeights[i] = a;
-					}
-					else if (i < blurSize) {
-						s_blurWeights[i] = a * (blurSize - i);
-					}
-					else {
-						s_blurWeights[i] = 0.0f;
-					}
-				}
-			}
-			param.offset.x = 0.5f + s_blurWeights[1]/(s_blurWeights[0] + s_blurWeights[1]);
-			param.offset.y = 2.5f + s_blurWeights[3]/(s_blurWeights[2] + s_blurWeights[3]); 
-			param.offset.z = 0.0f;
-			param.offset.w = 0.0f;
-			
-			param.weight.x = s_blurWeights[0] + s_blurWeights[1];
-			param.weight.y = s_blurWeights[2] + s_blurWeights[3];
-			param.weight.z = 0.0f;
-			param.weight.w = 0.0f;
+            if (s_blurWeights[3] < 0.02f)
+            {
+                param.tap = 3;
+                float a = 0.5f / (0.5f * s_blurWeights[0] + s_blurWeights[1] + s_blurWeights[2]);
+                param.weight.x = Mathf.Round(255 * a * s_blurWeights[0]) / 255.0f;
+                param.weight.y = 0.5f - 0.5f * param.weight.x;
+                param.weight.z = 0.0f;
+                param.weight.w = 0.0f;
+            }
+            else if (s_blurWeights[5] < 0.02f)
+            {
+                param.tap = 5;
+                float a = 0.5f / (0.5f * s_blurWeights[0] + s_blurWeights[1] + s_blurWeights[2] + s_blurWeights[3] + s_blurWeights[4]);
+                param.weight.x = Mathf.Round(255 * a * s_blurWeights[0]) / 255.0f;
+                param.weight.y = Mathf.Round(255 * a * (s_blurWeights[1] + s_blurWeights[2])) / 255.0f;
+                param.weight.z = 0.5f - (0.5f * param.weight.x + param.weight.y);
+                param.weight.w = 0.0f;
+            }
+            else
+            {
+                param.tap = 7;
+                param.weight.x = Mathf.Round(255 * s_blurWeights[0]) / 255.0f;
+                param.weight.y = Mathf.Round(255 * (s_blurWeights[1] + s_blurWeights[2])) / 255.0f;
+                param.weight.z = Mathf.Round(255 * (s_blurWeights[3] + s_blurWeights[4])) / 255.0f;
+                param.weight.w = 0.5f - (0.5f * param.weight.x + param.weight.y + param.weight.z);
+            }
+            return param;
+        }
+        static BlurParam GetDownsampleBlurParam(float blurSize, BlurFilter filter)
+        {
+            BlurParam param = new BlurParam();
+            param.tap = 4;
+            if (blurSize < 0.1f)
+            {
+                param.offset.x = 0.0f;
+                param.offset.y = 0.0f;
+                param.offset.z = 0.0f;
+                param.offset.w = 0.0f;
+                param.weight.x = 1.0f;
+                param.weight.y = 0.0f;
+                param.weight.z = 0.0f;
+                param.weight.w = 0.0f;
+                return param;
+            }
+            // calculate weights
+            if (filter == BlurFilter.Gaussian)
+            {
+                // gaussian filter
+                float a = 1.0f / (2.0f * blurSize * blurSize);
+                float totalWeight = 0.0f;
+                for (int i = 0; i < param.tap; ++i)
+                {
+                    float x = i + 0.5f;
+                    s_blurWeights[i] = Mathf.Exp(-x * x * a);
+                    totalWeight += 2.0f * s_blurWeights[i];
+                }
+                float w = 1.0f / totalWeight;
+                for (int i = 0; i < param.tap; ++i)
+                {
+                    s_blurWeights[i] *= w;
+                }
+            }
+            else
+            {
+                // uniform filter
+                float a = 0.5f / blurSize;
+                for (int i = 0; i < param.tap; ++i)
+                {
+                    if (i + 1 <= blurSize)
+                    {
+                        s_blurWeights[i] = a;
+                    }
+                    else if (i < blurSize)
+                    {
+                        s_blurWeights[i] = a * (blurSize - i);
+                    }
+                    else
+                    {
+                        s_blurWeights[i] = 0.0f;
+                    }
+                }
+            }
+            param.offset.x = 0.5f + s_blurWeights[1] / (s_blurWeights[0] + s_blurWeights[1]);
+            param.offset.y = 2.5f + s_blurWeights[3] / (s_blurWeights[2] + s_blurWeights[3]);
+            param.offset.z = 0.0f;
+            param.offset.w = 0.0f;
 
-			return param;
-		}
-		void OnPostRender()
-		{
+            param.weight.x = s_blurWeights[0] + s_blurWeights[1];
+            param.weight.y = s_blurWeights[2] + s_blurWeights[3];
+            param.weight.z = 0.0f;
+            param.weight.w = 0.0f;
+
+            return param;
+        }
+        void OnPostRender()
+        {
 #if UNITY_EDITOR
-			if (!(Application.isPlaying || m_isRenderingFromUpdate)) {
-				return;
-			}
+            if (!(Application.isPlaying || m_isRenderingFromUpdate))
+            {
+                return;
+            }
 #endif
-			m_camera.clearFlags = CameraClearFlags.Nothing;
-			if (!m_isVisible) {
-				return;
-			}
-			RenderTexture srcRT = m_camera.targetTexture;
+            m_camera.clearFlags = CameraClearFlags.Nothing;
+            if (!m_isVisible)
+            {
+                return;
+            }
+            RenderTexture srcRT = m_camera.targetTexture;
 #if UNITY_5_6
-			// workaround for Unity 5.6
-			// Unity 5.6 has a bug whereby a temporary render texture does not work if m_camera.targetTexture != null. This bug is fixed in Unity 2017.
-			// However, this workaround might conflict with VR support. If you have a problem with VR SDK, please let us know via e-mail (support@nyahoon.com).
-			if (srcRT != m_shadowTexture) {
-				m_camera.targetTexture = null;
-			}
+            // workaround for Unity 5.6
+            // Unity 5.6 has a bug whereby a temporary render texture does not work if m_camera.targetTexture != null. This bug is fixed in Unity 2017.
+            // However, this workaround might conflict with VR support. If you have a problem with VR SDK, please let us know via e-mail (support@nyahoon.com).
+            if (srcRT != m_shadowTexture)
+            {
+                m_camera.targetTexture = null;
+            }
 #else
 			m_camera.targetTexture = m_shadowTexture;
 #endif
-			if (m_superSampling != TextureSuperSample.x1 || HasShadowColor()) {
-				m_downsampleShader.color = m_shadowColor;
-				// downsample
-				RenderTexture dstRT;
-				if (0 < m_blurLevel) {
-					dstRT = RenderTexture.GetTemporary(m_textureWidth, m_textureHeight, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
-					dstRT.filterMode = FilterMode.Bilinear;
-				}
-				else {
-					dstRT = m_shadowTexture;
-				}
-				Graphics.SetRenderTarget(dstRT);
-				int pass = m_superSampling == TextureSuperSample.x16 ? 0 : 2;
-				Graphics.Blit(srcRT, dstRT, m_downsampleShader, HasShadowColor() ? pass + 1 : pass);
-				RenderTexture.ReleaseTemporary(srcRT);
-				srcRT = dstRT;
-			}
-			if (0 < m_blurLevel) {
-				// adjust blur size according to texel aspect
-				float texelAspect = (m_projector.aspectRatio * m_textureHeight)/(float)m_textureWidth;
-				float blurSizeH = m_blurSize;
-				float blurSizeV = m_blurSize;
-				if (texelAspect < 1.0f) {
-					blurSizeV *= texelAspect;
-				}
-				else {
-					blurSizeH /= texelAspect;
-				}
-				// blur parameters
-				BlurParam blurH = GetBlurParam(blurSizeH, m_blurFilter);
-				BlurParam blurV = GetBlurParam(blurSizeV, m_blurFilter);
-				blurH.tap = (blurH.tap - 3); // index of pass
-				blurV.tap = (blurV.tap - 3) + 1; // index of pass
-				m_blurShader.SetVector(s_blurOffsetHParamID, blurH.offset);
-				m_blurShader.SetVector(s_blurOffsetVParamID, blurV.offset);
-				m_blurShader.SetVector(s_blurWeightHParamID, blurH.weight);
-				m_blurShader.SetVector(s_blurWeightVParamID, blurV.weight);
+            if (m_superSampling != TextureSuperSample.x1 || HasShadowColor())
+            {
+                m_downsampleShader.color = m_shadowColor;
+                // downsample
+                RenderTexture dstRT;
+                if (0 < m_blurLevel)
+                {
+                    dstRT = RenderTexture.GetTemporary(m_textureWidth, m_textureHeight, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
+                    dstRT.filterMode = FilterMode.Bilinear;
+                }
+                else
+                {
+                    dstRT = m_shadowTexture;
+                }
+                Graphics.SetRenderTarget(dstRT);
+                int pass = m_superSampling == TextureSuperSample.x16 ? 0 : 2;
+                Graphics.Blit(srcRT, dstRT, m_downsampleShader, HasShadowColor() ? pass + 1 : pass);
+                RenderTexture.ReleaseTemporary(srcRT);
+                srcRT = dstRT;
+            }
+            if (0 < m_blurLevel)
+            {
+                // adjust blur size according to texel aspect
+                float texelAspect = (m_projector.aspectRatio * m_textureHeight) / (float)m_textureWidth;
+                float blurSizeH = m_blurSize;
+                float blurSizeV = m_blurSize;
+                if (texelAspect < 1.0f)
+                {
+                    blurSizeV *= texelAspect;
+                }
+                else
+                {
+                    blurSizeH /= texelAspect;
+                }
+                // blur parameters
+                BlurParam blurH = GetBlurParam(blurSizeH, m_blurFilter);
+                BlurParam blurV = GetBlurParam(blurSizeV, m_blurFilter);
+                blurH.tap = (blurH.tap - 3); // index of pass
+                blurV.tap = (blurV.tap - 3) + 1; // index of pass
+                m_blurShader.SetVector(s_blurOffsetHParamID, blurH.offset);
+                m_blurShader.SetVector(s_blurOffsetVParamID, blurV.offset);
+                m_blurShader.SetVector(s_blurWeightHParamID, blurH.weight);
+                m_blurShader.SetVector(s_blurWeightVParamID, blurV.weight);
 
-				RenderTexture dstRT = RenderTexture.GetTemporary(m_textureWidth, m_textureHeight, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
-				dstRT.filterMode = FilterMode.Bilinear;
-				srcRT.wrapMode = TextureWrapMode.Clamp;
-				dstRT.wrapMode = TextureWrapMode.Clamp;
-				Graphics.Blit(srcRT, dstRT, m_blurShader, blurH.tap);
-				if (1 < srcRT.antiAliasing) {
-					RenderTexture.ReleaseTemporary(srcRT);
-					srcRT = RenderTexture.GetTemporary(m_textureWidth, m_textureHeight, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
-				}
-				else {
-					srcRT.DiscardContents();
-				}
-				for (int i = 1; i < m_blurLevel - 1; ++i) {
-					Graphics.Blit(dstRT, srcRT, m_blurShader, blurV.tap);
-					dstRT.DiscardContents();
-					Graphics.Blit(srcRT, dstRT, m_blurShader, blurH.tap);
-					srcRT.DiscardContents();
-				}
-				RenderTexture.ReleaseTemporary(srcRT);
-				srcRT = m_shadowTexture;
-				Graphics.Blit(dstRT, srcRT, m_blurShader, blurV.tap);
-				RenderTexture.ReleaseTemporary(dstRT);
-			}
-			Graphics.SetRenderTarget(m_shadowTexture);
-			if (srcRT != m_shadowTexture) {
-				Graphics.Blit(srcRT, m_downsampleShader, 2);
-				if (m_mipLevel == 0) {
-					RenderTexture.ReleaseTemporary(srcRT);
-				}
-			}
-			EraseShadowOnBoarder(m_textureWidth, m_textureHeight);
-			if (0 < m_mipLevel) {
-				// setup blur parameters
-				BlurParam blurH = new BlurParam(), blurV = new BlurParam();
-				if (0.1f < m_mipmapBlurSize) {
-					// adjust blur size according to texel aspect
-					float texelAspect = (m_projector.aspectRatio * m_textureHeight)/(float)m_textureWidth;
-					float blurSizeH = m_mipmapBlurSize;
-					float blurSizeV = m_mipmapBlurSize;
-					if (texelAspect < 1.0f) {
-						blurSizeV *= texelAspect;
-					}
-					else {
-						blurSizeH /= texelAspect;
-					}
-					// blur parameters
-					if (m_singlePassMipmapBlur) {
-						blurH = GetDownsampleBlurParam(2.0f + 2.0f*blurSizeH, m_blurFilter);
-						blurV = GetDownsampleBlurParam(2.0f + 2.0f*blurSizeV, m_blurFilter);
-						Vector4 weight = new Vector4(blurH.weight.x * blurV.weight.x, blurH.weight.x * blurV.weight.y, blurH.weight.y * blurV.weight.x, blurH.weight.y * blurV.weight.y);
-						float a = 0.25f/(weight.x + weight.y + weight.z + weight.w);
-						weight.x = Mathf.Round(255*a*weight.x)/255.0f;
-						weight.y = Mathf.Round(255*a*weight.y)/255.0f;
-						weight.z = Mathf.Round(255*a*weight.z)/255.0f;
-						weight.w = 0.25f - weight.x - weight.y - weight.z;
-						m_downsampleShader.SetVector(s_downSampleBlurWeightParamID, weight);
-					}
-					else {
-						blurH = GetBlurParam(blurSizeH, m_blurFilter);
-						blurV = GetBlurParam(blurSizeV, m_blurFilter);
-						blurH.tap = (blurH.tap - 3); // index of pass
-						blurV.tap = (blurV.tap - 3) + 1; // index of pass
-						m_blurShader.SetVector(s_blurOffsetHParamID, blurH.offset);
-						m_blurShader.SetVector(s_blurOffsetVParamID, blurV.offset);
-						m_blurShader.SetVector(s_blurWeightHParamID, blurH.weight);
-						m_blurShader.SetVector(s_blurWeightVParamID, blurV.weight);
-					}
-				}
-				int w = m_textureWidth >> 1;
-				int h = m_textureHeight >> 1;
-				RenderTexture tempRT = RenderTexture.GetTemporary(w, h, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
-				tempRT.filterMode = FilterMode.Bilinear;
-				bool downSampleWithBlur = m_singlePassMipmapBlur && 0.1f < m_mipmapBlurSize;
-				if (downSampleWithBlur) {
-					SetDownsampleBlurOffsetParams(blurH, blurV, w, h);
-				}
-				if (srcRT == m_shadowTexture) {
-					if (downSampleWithBlur) {
-						Graphics.Blit(srcRT, tempRT, m_downsampleShader, 5);
-					}
-					else {
-						Graphics.Blit(srcRT, tempRT, m_copyMipmapShader, 1);
-					}
-				}
-				else {
-					Graphics.Blit(srcRT, tempRT, m_downsampleShader, downSampleWithBlur ? 4 : 0);
-					RenderTexture.ReleaseTemporary(srcRT);
-				}
-				srcRT = tempRT;
-				int i = 0;
-				float falloff = 1.0f;
-				for ( ; ; ) {
-					if (0.1f < m_mipmapBlurSize && !m_singlePassMipmapBlur) {
-						tempRT = RenderTexture.GetTemporary(w, h, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
-						tempRT.filterMode = FilterMode.Bilinear;
-						tempRT.wrapMode = TextureWrapMode.Clamp;
-						srcRT.wrapMode = TextureWrapMode.Clamp;
-						Graphics.Blit(srcRT, tempRT, m_blurShader, blurH.tap);
-						srcRT.DiscardContents();
-						Graphics.Blit(tempRT, srcRT, m_blurShader, blurV.tap);
-						RenderTexture.ReleaseTemporary(tempRT);
-					}
-					if (m_mipmapFalloff == MipmapFalloff.Linear) {
-						falloff = ((float)(m_mipLevel - i))/(m_mipLevel + 1.0f);
-					}
-					else if (m_mipmapFalloff == MipmapFalloff.Custom && m_customMipmapFalloff != null && 0 < m_customMipmapFalloff.Length) {
-						falloff = m_customMipmapFalloff[Mathf.Min(i, m_customMipmapFalloff.Length-1)];
-					}
-					m_copyMipmapShader.SetFloat(s_falloffParamID, falloff);
-					m_copyMipmapShader.SetFloat(s_falloffParamID, falloff);
-					m_shadowTexture.DiscardContents(); // To avoid Tiled GPU perf warning. It just tells GPU not to copy back the rendered image to a tile buffer. It won't destroy the rendered image.
-					++i;
-					Graphics.SetRenderTarget(m_shadowTexture, i);
-					Graphics.Blit(srcRT, m_copyMipmapShader, 0);
-					EraseShadowOnBoarder(w, h);
-					w = Mathf.Max(1, w >> 1);
-					h = Mathf.Max(1, h >> 1);
-					if (i == m_mipLevel || w <= 4 || h <= 4) {
-						RenderTexture.ReleaseTemporary(srcRT);
-						break;
-					}
-					tempRT = RenderTexture.GetTemporary(w, h, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
-					tempRT.filterMode = FilterMode.Bilinear;
-					if (downSampleWithBlur) {
-						SetDownsampleBlurOffsetParams(blurH, blurV, w, h);
-						Graphics.Blit(srcRT, tempRT, m_downsampleShader, 4);
-					}
-					else {
-						Graphics.Blit(srcRT, tempRT, m_downsampleShader, 0);
-					}
-					RenderTexture.ReleaseTemporary(srcRT);
-					srcRT = tempRT;
-				}
-				while (1 <= w || 1 <= h) {
-					++i;
-					Graphics.SetRenderTarget(m_shadowTexture, i);
-					GL.Clear(false, true, new Color(1,1,1,0));
-					w = w >> 1;
-					h = h >> 1;
-				}
-			}
-			m_shadowTextureValid = true;
-		}
-		void EraseShadowOnBoarder(int w, int h)
-		{
-			float x = 1.0f - 1.0f/w;
-			float y = 1.0f - 1.0f/h;
-			m_eraseShadowShader.SetPass(0);
-			GL.Begin(GL.LINES);
-			GL.Vertex3(-x,-y,0);
-			GL.Vertex3( x,-y,0);
-			GL.Vertex3( x,-y,0);
-			GL.Vertex3( x, y,0);
-			GL.Vertex3( x, y,0);
-			GL.Vertex3(-x, y,0);
-			GL.Vertex3(-x, y,0);
-			GL.Vertex3(-x,-y,0);
-			GL.End();
-		}
-		void SetDownsampleBlurOffsetParams(BlurParam blurH, BlurParam blurV, int w, int h)
-		{
-			float invW = 0.5f/w;
-			float invH = 0.5f/h;
-			float offsetX0 = invW * blurH.offset.x;
-			float offsetX1 = invW * blurH.offset.y;
-			float offsetY0 = invH * blurV.offset.x;
-			float offsetY1 = invH * blurV.offset.y;
-			m_downsampleShader.SetVector(s_downSampleBlurOffset0ParamID, new Vector4(offsetX0, offsetY0, -offsetX0, -offsetY0));
-			m_downsampleShader.SetVector(s_downSampleBlurOffset1ParamID, new Vector4(offsetX0, offsetY1, -offsetX0, -offsetY1));
-			m_downsampleShader.SetVector(s_downSampleBlurOffset2ParamID, new Vector4(offsetX1, offsetY0, -offsetX1, -offsetY0));
-			m_downsampleShader.SetVector(s_downSampleBlurOffset3ParamID, new Vector4(offsetX1, offsetY1, -offsetX1, -offsetY1));
-		}
-	}
+                RenderTexture dstRT = RenderTexture.GetTemporary(m_textureWidth, m_textureHeight, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
+                dstRT.filterMode = FilterMode.Bilinear;
+                srcRT.wrapMode = TextureWrapMode.Clamp;
+                dstRT.wrapMode = TextureWrapMode.Clamp;
+                Graphics.Blit(srcRT, dstRT, m_blurShader, blurH.tap);
+                if (1 < srcRT.antiAliasing)
+                {
+                    RenderTexture.ReleaseTemporary(srcRT);
+                    srcRT = RenderTexture.GetTemporary(m_textureWidth, m_textureHeight, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
+                }
+                else
+                {
+                    srcRT.DiscardContents();
+                }
+                for (int i = 1; i < m_blurLevel - 1; ++i)
+                {
+                    Graphics.Blit(dstRT, srcRT, m_blurShader, blurV.tap);
+                    dstRT.DiscardContents();
+                    Graphics.Blit(srcRT, dstRT, m_blurShader, blurH.tap);
+                    srcRT.DiscardContents();
+                }
+                RenderTexture.ReleaseTemporary(srcRT);
+                srcRT = m_shadowTexture;
+                Graphics.Blit(dstRT, srcRT, m_blurShader, blurV.tap);
+                RenderTexture.ReleaseTemporary(dstRT);
+            }
+            Graphics.SetRenderTarget(m_shadowTexture);
+            if (srcRT != m_shadowTexture)
+            {
+                Graphics.Blit(srcRT, m_downsampleShader, 2);
+                if (m_mipLevel == 0)
+                {
+                    RenderTexture.ReleaseTemporary(srcRT);
+                }
+            }
+            EraseShadowOnBoarder(m_textureWidth, m_textureHeight);
+            if (0 < m_mipLevel)
+            {
+                // setup blur parameters
+                BlurParam blurH = new BlurParam(), blurV = new BlurParam();
+                if (0.1f < m_mipmapBlurSize)
+                {
+                    // adjust blur size according to texel aspect
+                    float texelAspect = (m_projector.aspectRatio * m_textureHeight) / (float)m_textureWidth;
+                    float blurSizeH = m_mipmapBlurSize;
+                    float blurSizeV = m_mipmapBlurSize;
+                    if (texelAspect < 1.0f)
+                    {
+                        blurSizeV *= texelAspect;
+                    }
+                    else
+                    {
+                        blurSizeH /= texelAspect;
+                    }
+                    // blur parameters
+                    if (m_singlePassMipmapBlur)
+                    {
+                        blurH = GetDownsampleBlurParam(2.0f + 2.0f * blurSizeH, m_blurFilter);
+                        blurV = GetDownsampleBlurParam(2.0f + 2.0f * blurSizeV, m_blurFilter);
+                        Vector4 weight = new Vector4(blurH.weight.x * blurV.weight.x, blurH.weight.x * blurV.weight.y, blurH.weight.y * blurV.weight.x, blurH.weight.y * blurV.weight.y);
+                        float a = 0.25f / (weight.x + weight.y + weight.z + weight.w);
+                        weight.x = Mathf.Round(255 * a * weight.x) / 255.0f;
+                        weight.y = Mathf.Round(255 * a * weight.y) / 255.0f;
+                        weight.z = Mathf.Round(255 * a * weight.z) / 255.0f;
+                        weight.w = 0.25f - weight.x - weight.y - weight.z;
+                        m_downsampleShader.SetVector(s_downSampleBlurWeightParamID, weight);
+                    }
+                    else
+                    {
+                        blurH = GetBlurParam(blurSizeH, m_blurFilter);
+                        blurV = GetBlurParam(blurSizeV, m_blurFilter);
+                        blurH.tap = (blurH.tap - 3); // index of pass
+                        blurV.tap = (blurV.tap - 3) + 1; // index of pass
+                        m_blurShader.SetVector(s_blurOffsetHParamID, blurH.offset);
+                        m_blurShader.SetVector(s_blurOffsetVParamID, blurV.offset);
+                        m_blurShader.SetVector(s_blurWeightHParamID, blurH.weight);
+                        m_blurShader.SetVector(s_blurWeightVParamID, blurV.weight);
+                    }
+                }
+                int w = m_textureWidth >> 1;
+                int h = m_textureHeight >> 1;
+                RenderTexture tempRT = RenderTexture.GetTemporary(w, h, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
+                tempRT.filterMode = FilterMode.Bilinear;
+                bool downSampleWithBlur = m_singlePassMipmapBlur && 0.1f < m_mipmapBlurSize;
+                if (downSampleWithBlur)
+                {
+                    SetDownsampleBlurOffsetParams(blurH, blurV, w, h);
+                }
+                if (srcRT == m_shadowTexture)
+                {
+                    if (downSampleWithBlur)
+                    {
+                        Graphics.Blit(srcRT, tempRT, m_downsampleShader, 5);
+                    }
+                    else
+                    {
+                        Graphics.Blit(srcRT, tempRT, m_copyMipmapShader, 1);
+                    }
+                }
+                else
+                {
+                    Graphics.Blit(srcRT, tempRT, m_downsampleShader, downSampleWithBlur ? 4 : 0);
+                    RenderTexture.ReleaseTemporary(srcRT);
+                }
+                srcRT = tempRT;
+                int i = 0;
+                float falloff = 1.0f;
+                for (; ; )
+                {
+                    if (0.1f < m_mipmapBlurSize && !m_singlePassMipmapBlur)
+                    {
+                        tempRT = RenderTexture.GetTemporary(w, h, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
+                        tempRT.filterMode = FilterMode.Bilinear;
+                        tempRT.wrapMode = TextureWrapMode.Clamp;
+                        srcRT.wrapMode = TextureWrapMode.Clamp;
+                        Graphics.Blit(srcRT, tempRT, m_blurShader, blurH.tap);
+                        srcRT.DiscardContents();
+                        Graphics.Blit(tempRT, srcRT, m_blurShader, blurV.tap);
+                        RenderTexture.ReleaseTemporary(tempRT);
+                    }
+                    if (m_mipmapFalloff == MipmapFalloff.Linear)
+                    {
+                        falloff = ((float)(m_mipLevel - i)) / (m_mipLevel + 1.0f);
+                    }
+                    else if (m_mipmapFalloff == MipmapFalloff.Custom && m_customMipmapFalloff != null && 0 < m_customMipmapFalloff.Length)
+                    {
+                        falloff = m_customMipmapFalloff[Mathf.Min(i, m_customMipmapFalloff.Length - 1)];
+                    }
+                    m_copyMipmapShader.SetFloat(s_falloffParamID, falloff);
+                    m_copyMipmapShader.SetFloat(s_falloffParamID, falloff);
+                    m_shadowTexture.DiscardContents(); // To avoid Tiled GPU perf warning. It just tells GPU not to copy back the rendered image to a tile buffer. It won't destroy the rendered image.
+                    ++i;
+                    Graphics.SetRenderTarget(m_shadowTexture, i);
+                    Graphics.Blit(srcRT, m_copyMipmapShader, 0);
+                    EraseShadowOnBoarder(w, h);
+                    w = Mathf.Max(1, w >> 1);
+                    h = Mathf.Max(1, h >> 1);
+                    if (i == m_mipLevel || w <= 4 || h <= 4)
+                    {
+                        RenderTexture.ReleaseTemporary(srcRT);
+                        break;
+                    }
+                    tempRT = RenderTexture.GetTemporary(w, h, 0, m_shadowTexture.format, RenderTextureReadWrite.Linear);
+                    tempRT.filterMode = FilterMode.Bilinear;
+                    if (downSampleWithBlur)
+                    {
+                        SetDownsampleBlurOffsetParams(blurH, blurV, w, h);
+                        Graphics.Blit(srcRT, tempRT, m_downsampleShader, 4);
+                    }
+                    else
+                    {
+                        Graphics.Blit(srcRT, tempRT, m_downsampleShader, 0);
+                    }
+                    RenderTexture.ReleaseTemporary(srcRT);
+                    srcRT = tempRT;
+                }
+                while (1 <= w || 1 <= h)
+                {
+                    ++i;
+                    Graphics.SetRenderTarget(m_shadowTexture, i);
+                    GL.Clear(false, true, new Color(1, 1, 1, 0));
+                    w = w >> 1;
+                    h = h >> 1;
+                }
+            }
+            m_shadowTextureValid = true;
+        }
+        void EraseShadowOnBoarder(int w, int h)
+        {
+            float x = 1.0f - 1.0f / w;
+            float y = 1.0f - 1.0f / h;
+
+            if (m_eraseShadowShader != null)
+            {
+                m_eraseShadowShader.SetPass(0);
+            }
+
+            GL.Begin(GL.LINES);
+            GL.Vertex3(-x, -y, 0);
+            GL.Vertex3(x, -y, 0);
+            GL.Vertex3(x, -y, 0);
+            GL.Vertex3(x, y, 0);
+            GL.Vertex3(x, y, 0);
+            GL.Vertex3(-x, y, 0);
+            GL.Vertex3(-x, y, 0);
+            GL.Vertex3(-x, -y, 0);
+            GL.End();
+        }
+        void SetDownsampleBlurOffsetParams(BlurParam blurH, BlurParam blurV, int w, int h)
+        {
+            float invW = 0.5f / w;
+            float invH = 0.5f / h;
+            float offsetX0 = invW * blurH.offset.x;
+            float offsetX1 = invW * blurH.offset.y;
+            float offsetY0 = invH * blurV.offset.x;
+            float offsetY1 = invH * blurV.offset.y;
+            m_downsampleShader.SetVector(s_downSampleBlurOffset0ParamID, new Vector4(offsetX0, offsetY0, -offsetX0, -offsetY0));
+            m_downsampleShader.SetVector(s_downSampleBlurOffset1ParamID, new Vector4(offsetX0, offsetY1, -offsetX0, -offsetY1));
+            m_downsampleShader.SetVector(s_downSampleBlurOffset2ParamID, new Vector4(offsetX1, offsetY0, -offsetX1, -offsetY0));
+            m_downsampleShader.SetVector(s_downSampleBlurOffset3ParamID, new Vector4(offsetX1, offsetY1, -offsetX1, -offsetY1));
+        }
+    }
 }

--
Gitblit v1.8.0