Tanoda
LightShafts.cs
Go to the documentation of this file.
1using UnityEngine;
2using System.Collections;
3
4[ExecuteInEditMode]
5[RequireComponent(typeof(Light))]
6public partial class LightShafts : MonoBehaviour
7{
8 public void Start()
9 {
11
12 if (m_Cameras == null || m_Cameras.Length == 0)
13 m_Cameras = new Camera[]{Camera.main};
14
16 }
17
18 void UpdateShadowmap()
19 {
20 if (m_ShadowmapMode == LightShaftsShadowmapMode.Static && !m_ShadowmapDirty)
21 return;
22
23 InitShadowmap();
24
25 if (m_ShadowmapCamera == null)
26 {
27 GameObject go = new GameObject("Depth Camera");
28 go.AddComponent(typeof(Camera));
29 m_ShadowmapCamera = go.GetComponent<Camera>();
30 go.hideFlags = HideFlags.HideAndDontSave;
31 m_ShadowmapCamera.enabled = false;
32 m_ShadowmapCamera.clearFlags = CameraClearFlags.SolidColor;
33 }
34 Transform cam = m_ShadowmapCamera.transform;
35 cam.position = transform.position;
36 cam.rotation = transform.rotation;
37
38 if (directional)
39 {
40 m_ShadowmapCamera.orthographic = true;
41 m_ShadowmapCamera.nearClipPlane = 0;
42 m_ShadowmapCamera.farClipPlane = m_Size.z;
43 m_ShadowmapCamera.orthographicSize = m_Size.y * 0.5f;
44 m_ShadowmapCamera.aspect = m_Size.x / m_Size.y;
45 }
46 else
47 {
48 m_ShadowmapCamera.orthographic = false;
49 m_ShadowmapCamera.nearClipPlane = m_SpotNear * m_Light.range;
50 m_ShadowmapCamera.farClipPlane = m_SpotFar * m_Light.range;
51 m_ShadowmapCamera.fieldOfView = m_Light.spotAngle;
52 m_ShadowmapCamera.aspect = 1.0f;
53 }
54 m_ShadowmapCamera.renderingPath = RenderingPath.Forward;
55 m_ShadowmapCamera.targetTexture = m_Shadowmap;
56 m_ShadowmapCamera.cullingMask = m_CullingMask;
57 m_ShadowmapCamera.backgroundColor = Color.white;
58
59 m_ShadowmapCamera.RenderWithShader(m_DepthShader, "RenderType");
60
61 if (m_Colored)
62 {
63 m_ShadowmapCamera.targetTexture = m_ColorFilter;
64 m_ShadowmapCamera.cullingMask = m_ColorFilterMask;
65 m_ShadowmapCamera.backgroundColor = new Color(m_ColorBalance, m_ColorBalance, m_ColorBalance);
66 m_ShadowmapCamera.RenderWithShader(m_ColorFilterShader, "");
67 }
68
69 m_ShadowmapDirty = false;
70 }
71
72 void RenderCoords(int width, int height, Vector4 lightPos)
73 {
74 SetFrustumRays(m_CoordMaterial);
75
76 RenderBuffer[] buffers = {m_CoordEpi.colorBuffer, m_DepthEpi.colorBuffer};
77 Graphics.SetRenderTarget(buffers, m_DepthEpi.depthBuffer);
78 m_CoordMaterial.SetVector("_LightPos", lightPos);
79 m_CoordMaterial.SetVector("_CoordTexDim", new Vector4(m_CoordEpi.width, m_CoordEpi.height, 1.0f / m_CoordEpi.width, 1.0f / m_CoordEpi.height));
80 m_CoordMaterial.SetVector("_ScreenTexDim", new Vector4(width, height, 1.0f / width, 1.0f / height));
81 m_CoordMaterial.SetPass(0);
82 RenderQuad();
83 }
84
85 void RenderInterpolationTexture(Vector4 lightPos)
86 {
87 Graphics.SetRenderTarget(m_InterpolationEpi.colorBuffer, m_RaymarchedLightEpi.depthBuffer);
88 if (!m_DX11Support && (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer))
89 {
90 // Looks like in dx9 stencil is not cleared properly with GL.Clear()
91 // Edit: fixed in 4.5, so this hack can be removed
92 m_DepthBreaksMaterial.SetPass(1);
93 RenderQuad();
94 }
95 else
96 {
97 GL.Clear(true, true, new Color(0, 0, 0, 1));
98 }
99 m_DepthBreaksMaterial.SetFloat("_InterpolationStep", m_InterpolationStep);
100 m_DepthBreaksMaterial.SetFloat("_DepthThreshold", GetDepthThresholdAdjusted());
101 m_DepthBreaksMaterial.SetTexture("_DepthEpi", m_DepthEpi);
102 m_DepthBreaksMaterial.SetVector("_DepthEpiTexDim", new Vector4(m_DepthEpi.width, m_DepthEpi.height, 1.0f / m_DepthEpi.width, 1.0f / m_DepthEpi.height));
103 m_DepthBreaksMaterial.SetPass(0);
104 RenderQuadSections(lightPos);
105 }
106
107 void InterpolateAlongRays(Vector4 lightPos)
108 {
109 Graphics.SetRenderTarget(m_InterpolateAlongRaysEpi);
110 m_InterpolateAlongRaysMaterial.SetFloat("_InterpolationStep", m_InterpolationStep);
111 m_InterpolateAlongRaysMaterial.SetTexture("_InterpolationEpi", m_InterpolationEpi);
112 m_InterpolateAlongRaysMaterial.SetTexture("_RaymarchedLightEpi", m_RaymarchedLightEpi);
113 m_InterpolateAlongRaysMaterial.SetVector("_RaymarchedLightEpiTexDim", new Vector4(m_RaymarchedLightEpi.width, m_RaymarchedLightEpi.height, 1.0f / m_RaymarchedLightEpi.width, 1.0f / m_RaymarchedLightEpi.height));
114 m_InterpolateAlongRaysMaterial.SetPass(0);
115 RenderQuadSections(lightPos);
116 }
117
118 void RenderSamplePositions(int width, int height, Vector4 lightPos)
119 {
120 InitRenderTexture (ref m_SamplePositions, width, height, 0, RenderTextureFormat.ARGB32, false);
121 // Unfortunately can't be a temporary RT if we want random write
122 m_SamplePositions.enableRandomWrite = true;
123 m_SamplePositions.filterMode = FilterMode.Point;
124
125 Graphics.SetRenderTarget (m_SamplePositions);
126 GL.Clear (false, true, new Color(0,0,0,1));
127
128 Graphics.ClearRandomWriteTargets();
129 Graphics.SetRandomWriteTarget(1, m_SamplePositions);
130
131 //We need a render target with m_Coord dimensions, but reading and writing
132 //to the same target produces wrong read results, so using a dummy.
133 Graphics.SetRenderTarget(m_RaymarchedLightEpi);
134
135 m_SamplePositionsMaterial.SetVector("_OutputTexDim", new Vector4(width-1, height-1, 0, 0));
136 m_SamplePositionsMaterial.SetVector("_CoordTexDim", new Vector4(m_CoordEpi.width, m_CoordEpi.height, 0, 0));
137 m_SamplePositionsMaterial.SetTexture("_Coord", m_CoordEpi);
138 m_SamplePositionsMaterial.SetTexture("_InterpolationEpi", m_InterpolationEpi);
139
141 {
142 m_SamplePositionsMaterial.SetFloat("_SampleType", 1);
143 m_SamplePositionsMaterial.SetVector("_Color", new Vector4(0.4f, 0.4f, 0, 0));
144 m_SamplePositionsMaterial.SetPass(0);
145 RenderQuad();
146 }
147
148 m_SamplePositionsMaterial.SetFloat("_SampleType", 0);
149 m_SamplePositionsMaterial.SetVector("_Color", new Vector4(1, 0, 0, 0));
150 m_SamplePositionsMaterial.SetPass(0);
151 RenderQuadSections(lightPos);
152
153 Graphics.ClearRandomWriteTargets();
154 }
155
156 void ShowSamples(int width, int height, Vector4 lightPos)
157 {
158 bool showSamples = m_ShowSamples && m_DX11Support && m_SamplePositionsShaderCompiles;
159 SetKeyword(showSamples, "SHOW_SAMPLES_ON", "SHOW_SAMPLES_OFF");
160 if (showSamples)
161 RenderSamplePositions(width, height, lightPos);
162
163 m_FinalInterpolationMaterial.SetFloat("_ShowSamplesBackgroundFade", m_ShowSamplesBackgroundFade);
164 }
165
166 void Raymarch(int width, int height, Vector4 lightPos)
167 {
168 SetFrustumRays(m_RaymarchMaterial);
169
170 int shadowmapWidth = m_Shadowmap.width;
171 int shadowmapHeight = m_Shadowmap.height;
172
173 Graphics.SetRenderTarget(m_RaymarchedLightEpi.colorBuffer, m_RaymarchedLightEpi.depthBuffer);
174 GL.Clear(false, true, new Color(0, 0, 0, 1));
175 m_RaymarchMaterial.SetTexture("_Coord", m_CoordEpi);
176 m_RaymarchMaterial.SetTexture("_InterpolationEpi", m_InterpolationEpi);
177 m_RaymarchMaterial.SetTexture("_Shadowmap", m_Shadowmap);
179 brightness *= m_Light.intensity;
180 m_RaymarchMaterial.SetFloat("_Brightness", brightness);
181 m_RaymarchMaterial.SetFloat("_Extinction", -m_Extinction);
182 m_RaymarchMaterial.SetVector("_ShadowmapDim", new Vector4(shadowmapWidth, shadowmapHeight, 1.0f / shadowmapWidth, 1.0f / shadowmapHeight));
183 m_RaymarchMaterial.SetVector("_ScreenTexDim", new Vector4(width, height, 1.0f / width, 1.0f / height));
184 m_RaymarchMaterial.SetVector("_LightColor", m_Light.color.linear);
185 m_RaymarchMaterial.SetFloat("_MinDistFromCamera", m_MinDistFromCamera);
186 SetKeyword(m_Colored, "COLORED_ON", "COLORED_OFF");
187 m_RaymarchMaterial.SetTexture("_ColorFilter", m_ColorFilter);
188 SetKeyword(m_AttenuationCurveOn, "ATTENUATION_CURVE_ON", "ATTENUATION_CURVE_OFF");
189 m_RaymarchMaterial.SetTexture("_AttenuationCurveTex", m_AttenuationCurveTex);
190 Texture cookie = m_Light.cookie;
191 SetKeyword(cookie != null, "COOKIE_TEX_ON", "COOKIE_TEX_OFF");
192 if (cookie != null)
193 m_RaymarchMaterial.SetTexture("_Cookie", cookie);
194 m_RaymarchMaterial.SetPass(0);
195
196 RenderQuadSections(lightPos);
197 }
198
199 public void OnRenderObject ()
200 {
201 m_CurrentCamera = Camera.current;
202 if (!m_MinRequirements || !CheckCamera() || !IsVisible())
203 return;
204
205 // Prepare
206 RenderBuffer depthBuffer = Graphics.activeDepthBuffer;
207 RenderBuffer colorBuffer = Graphics.activeColorBuffer;
208 InitResources();
209 Vector4 lightPos = GetLightViewportPos();
210 bool lightOnScreen = lightPos.x >= -1 && lightPos.x <= 1 && lightPos.y >= -1 && lightPos.y <= 1;
211 SetKeyword(lightOnScreen, "LIGHT_ON_SCREEN", "LIGHT_OFF_SCREEN");
212 int width = Screen.width;
213 int height = Screen.height;
214
215 // Render the buffers, raymarch, interpolate along rays
216 UpdateShadowmap();
217 SetKeyword(directional, "DIRECTIONAL_SHAFTS", "SPOT_SHAFTS");
218 RenderCoords(width, height, lightPos);
219 RenderInterpolationTexture(lightPos);
220 Raymarch(width, height, lightPos);
221 InterpolateAlongRays(lightPos);
222
223 ShowSamples(width, height, lightPos);
224
225 // Final interpolation and blending onto the screen
226 SetFrustumRays(m_FinalInterpolationMaterial);
227 m_FinalInterpolationMaterial.SetTexture("_InterpolationEpi", m_InterpolationEpi);
228 m_FinalInterpolationMaterial.SetTexture("_DepthEpi", m_DepthEpi);
229 m_FinalInterpolationMaterial.SetTexture("_Shadowmap", m_Shadowmap);
230 m_FinalInterpolationMaterial.SetTexture("_Coord", m_CoordEpi);
231 m_FinalInterpolationMaterial.SetTexture("_SamplePositions", m_SamplePositions);
232 m_FinalInterpolationMaterial.SetTexture("_RaymarchedLight", m_InterpolateAlongRaysEpi);
233 m_FinalInterpolationMaterial.SetVector("_CoordTexDim", new Vector4(m_CoordEpi.width, m_CoordEpi.height, 1.0f / m_CoordEpi.width, 1.0f / m_CoordEpi.height));
234 m_FinalInterpolationMaterial.SetVector("_ScreenTexDim", new Vector4(width, height, 1.0f / width, 1.0f / height));
235 m_FinalInterpolationMaterial.SetVector("_LightPos", lightPos);
236 m_FinalInterpolationMaterial.SetFloat("_DepthThreshold", GetDepthThresholdAdjusted());
237 bool renderAsQuad = directional || IntersectsNearPlane();
238 m_FinalInterpolationMaterial.SetFloat("_ZTest", (float)(renderAsQuad ? UnityEngine.Rendering.CompareFunction.Always : UnityEngine.Rendering.CompareFunction.Less));
239 SetKeyword(renderAsQuad, "QUAD_SHAFTS", "FRUSTUM_SHAFTS");
240
241 Graphics.SetRenderTarget(colorBuffer, depthBuffer);
242 m_FinalInterpolationMaterial.SetPass(0);
243 if (renderAsQuad)
244 RenderQuad();
245 else
246 RenderSpotFrustum();
247
248 ReleaseResources();
249 }
250}
LightShaftsShadowmapMode
UnityEngine.Color Color
Definition: TestScript.cs:32
void UpdateCameraDepthMode()
void Start()
Definition: LightShafts.cs:8
LayerMask m_CullingMask
LayerMask m_ColorFilterMask
void OnRenderObject()
Definition: LightShafts.cs:199
float m_ShowSamplesBackgroundFade
LightShaftsShadowmapMode m_ShadowmapMode