-
Notifications
You must be signed in to change notification settings - Fork 878
Expand file tree
/
Copy pathDrawLight2DPass.cs
More file actions
233 lines (185 loc) · 10.8 KB
/
Copy pathDrawLight2DPass.cs
File metadata and controls
233 lines (185 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
using System;
using System.Collections.Generic;
using UnityEngine.Rendering.RenderGraphModule;
using CommonResourceData = UnityEngine.Rendering.Universal.UniversalResourceData;
namespace UnityEngine.Rendering.Universal
{
internal class DrawLight2DPass : ScriptableRenderPass
{
static readonly string k_LightPass = "Light2D Pass";
static readonly string k_LightSRTPass = "Light2D SRT Pass";
static readonly string k_LightVolumetricPass = "Light2D Volumetric Pass";
private static readonly ProfilingSampler m_ProfilingSampler = new ProfilingSampler(k_LightPass);
private static readonly ProfilingSampler m_ProfilingSampleSRT = new ProfilingSampler(k_LightSRTPass);
private static readonly ProfilingSampler m_ProfilingSamplerVolume = new ProfilingSampler(k_LightVolumetricPass);
internal static readonly int k_InverseHDREmulationScaleID = Shader.PropertyToID("_InverseHDREmulationScale");
internal static readonly string k_NormalMapID = "_NormalMap";
internal static readonly string k_ShadowMapID = "_ShadowTex";
TextureHandle[] intermediateTexture = new TextureHandle[1];
internal static MaterialPropertyBlock s_PropertyBlock = new MaterialPropertyBlock();
internal void Setup(RenderGraph renderGraph, ref Renderer2DData rendererData)
{
foreach (var light in rendererData.lightCullResult.visibleLights)
{
if (light.useCookieSprite && light.m_CookieSpriteTexture != null)
light.m_CookieSpriteTextureHandle = renderGraph.ImportTexture(light.m_CookieSpriteTexture);
}
}
static bool TryGetShadowIndex(ref LayerBatch layerBatch, int lightIndex, out int shadowIndex)
{
shadowIndex = 0;
for (int i = 0; i < layerBatch.shadowIndices.Count; ++i)
{
if (layerBatch.shadowIndices[i] == lightIndex)
{
shadowIndex = i;
return true;
}
}
return false;
}
[Obsolete(DeprecationMessage.CompatibilityScriptingAPIObsolete, false)]
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
throw new NotImplementedException();
}
private static void Execute(RasterCommandBuffer cmd, PassData passData, ref LayerBatch layerBatch, int lightTextureIndex)
{
cmd.SetGlobalFloat(k_InverseHDREmulationScaleID, 1.0f / passData.rendererData.hdrEmulationScale);
var blendStyleIndex = layerBatch.activeBlendStylesIndices[lightTextureIndex];
var blendOpName = passData.rendererData.lightBlendStyles[blendStyleIndex].name;
cmd.BeginSample(blendOpName);
var indicesIndex = Renderer2D.supportsMRT ? lightTextureIndex : 0;
if (!passData.isVolumetric)
RendererLighting.EnableBlendStyle(cmd, indicesIndex, true);
var lights = passData.layerBatch.lights;
for (int j = 0; j < lights.Count; ++j)
{
var light = lights[j];
// Check if light is valid
if (light == null ||
light.lightType == Light2D.LightType.Global ||
light.blendStyleIndex != blendStyleIndex)
continue;
// Check if light is volumetric
if (passData.isVolumetric &&
(light.volumeIntensity <= 0.0f ||
!light.volumetricEnabled ||
layerBatch.endLayerValue != light.GetTopMostLitLayer()))
continue;
var useShadows = (!passData.isVolumetric && passData.layerBatch.lightStats.useShadows) || (passData.isVolumetric && passData.layerBatch.lightStats.useVolumetricShadowLights);
useShadows &= layerBatch.shadowIndices.Contains(j);
var lightMaterial = passData.rendererData.GetLightMaterial(light, passData.isVolumetric, useShadows);
var lightMesh = light.lightMesh;
// For Batching.
var index = light.batchSlotIndex;
var slotIndex = RendererLighting.lightBatch.SlotIndex(index);
bool canBatch = RendererLighting.lightBatch.CanBatch(light, lightMaterial, index, out int lightHash);
bool breakBatch = !canBatch;
if (breakBatch && LightBatch.isBatchingSupported)
RendererLighting.lightBatch.Flush(cmd);
if (passData.layerBatch.lightStats.useNormalMap)
s_PropertyBlock.SetTexture(k_NormalMapID, passData.normalMap);
if (useShadows && TryGetShadowIndex(ref layerBatch, j, out var shadowIndex))
s_PropertyBlock.SetTexture(k_ShadowMapID, passData.shadowTextures[shadowIndex]);
if (!passData.isVolumetric || (passData.isVolumetric && light.volumetricEnabled))
RendererLighting.SetCookieShaderProperties(light, s_PropertyBlock);
// Set shader global properties
RendererLighting.SetPerLightShaderGlobals(cmd, light, slotIndex, passData.isVolumetric, useShadows, LightBatch.isBatchingSupported);
if (light.normalMapQuality != Light2D.NormalMapQuality.Disabled || light.lightType == Light2D.LightType.Point)
RendererLighting.SetPerPointLightShaderGlobals(cmd, light, slotIndex, LightBatch.isBatchingSupported);
if (LightBatch.isBatchingSupported)
{
RendererLighting.lightBatch.AddBatch(light, lightMaterial, light.GetMatrix(), lightMesh, 0, lightHash, index);
RendererLighting.lightBatch.Flush(cmd);
}
else
{
cmd.DrawMesh(lightMesh, light.GetMatrix(), lightMaterial, 0, 0, s_PropertyBlock);
}
}
RendererLighting.EnableBlendStyle(cmd, indicesIndex, false);
cmd.EndSample(blendOpName);
}
internal class PassData
{
internal LayerBatch layerBatch;
internal Renderer2DData rendererData;
internal bool isVolumetric;
internal TextureHandle normalMap;
internal TextureHandle[] shadowTextures;
internal int lightTextureIndex;
}
void InitializeRenderPass(IRasterRenderGraphBuilder builder, ContextContainer frameData, PassData passData, Renderer2DData rendererData, ref LayerBatch layerBatch, int batchIndex, bool isVolumetric = false)
{
Universal2DResourceData universal2DResourceData = frameData.Get<Universal2DResourceData>();
CommonResourceData commonResourceData = frameData.Get<CommonResourceData>();
intermediateTexture[0] = commonResourceData.activeColorTexture;
if (layerBatch.lightStats.useNormalMap)
builder.UseTexture(universal2DResourceData.normalsTexture[batchIndex]);
if (layerBatch.lightStats.useShadows)
{
passData.shadowTextures = universal2DResourceData.shadowTextures[batchIndex];
for (var i = 0; i < passData.shadowTextures.Length; i++)
builder.UseTexture(passData.shadowTextures[i]);
}
foreach (var light in layerBatch.lights)
{
if (light == null || !light.m_CookieSpriteTextureHandle.IsValid())
continue;
if (!isVolumetric || (isVolumetric && light.volumetricEnabled))
builder.UseTexture(light.m_CookieSpriteTextureHandle);
}
passData.layerBatch = layerBatch;
passData.rendererData = rendererData;
passData.isVolumetric = isVolumetric;
passData.normalMap = layerBatch.lightStats.useNormalMap ? universal2DResourceData.normalsTexture[batchIndex] : TextureHandle.nullHandle;
builder.AllowGlobalStateModification(true);
}
internal void Render(RenderGraph graph, ContextContainer frameData, Renderer2DData rendererData, ref LayerBatch layerBatch, int batchIndex, bool isVolumetric = false)
{
Universal2DResourceData universal2DResourceData = frameData.Get<Universal2DResourceData>();
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
// Check for lighting in scene/prefab/preview camera
var isLightingActive = Renderer2D.s_IsLightingActive;
if (!layerBatch.lightStats.useLights ||
isVolumetric && !layerBatch.lightStats.useVolumetricLights ||
!isLightingActive)
return;
// Render single RTs by for apis that don't support MRTs
if (!isVolumetric && !Renderer2D.supportsMRT)
{
for (var i = 0; i < layerBatch.activeBlendStylesIndices.Length; ++i)
{
using (var builder = graph.AddRasterRenderPass<PassData>(k_LightSRTPass, out var passData, m_ProfilingSampleSRT))
{
InitializeRenderPass(builder, frameData, passData, rendererData, ref layerBatch, batchIndex, isVolumetric);
var lightTextures = universal2DResourceData.lightTextures[batchIndex];
builder.SetRenderAttachment(lightTextures[i], 0);
passData.lightTextureIndex = i;
builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
{
Execute(context.cmd, data, ref data.layerBatch, data.lightTextureIndex);
});
}
}
}
// Default Raster Pass with MRTs
else
{
using (var builder = graph.AddRasterRenderPass<PassData>(!isVolumetric ? k_LightPass : k_LightVolumetricPass, out var passData, !isVolumetric ? m_ProfilingSampler : m_ProfilingSamplerVolume))
{
InitializeRenderPass(builder, frameData, passData, rendererData, ref layerBatch, batchIndex, isVolumetric);
var lightTextures = !isVolumetric ? universal2DResourceData.lightTextures[batchIndex] : intermediateTexture;
for (var i = 0; i < lightTextures.Length; i++)
builder.SetRenderAttachment(lightTextures[i], i);
builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
{
for (var i = 0; i < data.layerBatch.activeBlendStylesIndices.Length; ++i)
Execute(context.cmd, data, ref data.layerBatch, i);
});
}
}
}
}
}