TurnBasedStrategyCourse/Library/PackageCache/com.unity.render-pipelines..../Runtime/2D/Rendergraph/DrawLight2DPass.cs

200 lines
9.6 KiB
C#

using System;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.RenderGraphModule;
namespace UnityEngine.Rendering.Universal
{
internal class DrawLight2DPass : ScriptableRenderPass
{
private static readonly ProfilingSampler m_ProfilingSampler = new ProfilingSampler("Light2DPass");
private static readonly ProfilingSampler m_ProfilingSamplerVolume = new ProfilingSampler("LightVolume2DPass");
private static readonly ProfilingSampler m_ExecuteProfilingSampler = new ProfilingSampler("Draw Lights");
private static readonly int k_InverseHDREmulationScaleID = Shader.PropertyToID("_InverseHDREmulationScale");
private static readonly int k_NormalMapID = Shader.PropertyToID("_NormalMap");
private static readonly int k_ShadowMapID = Shader.PropertyToID("_ShadowTex");
private static readonly int k_LightLookupID = Shader.PropertyToID("_LightLookup");
private static readonly int k_FalloffLookupID = Shader.PropertyToID("_FalloffLookup");
TextureHandle[] intermediateTexture = new TextureHandle[1];
private RTHandle m_FallOffRTHandle = null;
private RTHandle m_LightLookupRTHandle = null;
private int lightLookupInstanceID;
public void Setup(RenderGraph renderGraph, ref Renderer2DData rendererData)
{
if (m_FallOffRTHandle == null)
m_FallOffRTHandle = RTHandles.Alloc(rendererData.fallOffLookup);
// Reallocate external texture if needed
var lightLookupTexture = Light2DLookupTexture.GetLightLookupTexture();
if (lightLookupInstanceID != lightLookupTexture.GetInstanceID())
{
m_LightLookupRTHandle = RTHandles.Alloc(lightLookupTexture);
lightLookupInstanceID = lightLookupTexture.GetInstanceID();
}
foreach (var light in rendererData.lightCullResult.visibleLights)
{
if (light.useCookieSprite && light.m_CookieSpriteTexture != null)
light.m_CookieSpriteTextureHandle = renderGraph.ImportTexture(light.m_CookieSpriteTexture);
}
}
public void Dispose()
{
m_FallOffRTHandle?.Release();
m_LightLookupRTHandle?.Release();
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
throw new NotImplementedException();
}
private static void Execute(RasterCommandBuffer cmd, PassData passData, ref LayerBatch layerBatch)
{
using (new ProfilingScope(cmd, m_ExecuteProfilingSampler))
{
cmd.SetGlobalFloat(k_InverseHDREmulationScaleID, 1.0f / passData.rendererData.hdrEmulationScale);
var lightBlendStyles = passData.rendererData.lightBlendStyles;
for (var blendStyleIndex = 0; blendStyleIndex < lightBlendStyles.Length; blendStyleIndex++)
{
var blendStyleMask = (uint)(1 << blendStyleIndex);
var blendStyleUsed = (layerBatch.lightStats.blendStylesUsed & blendStyleMask) > 0;
if (!blendStyleUsed)
continue;
var blendOpName = lightBlendStyles[blendStyleIndex].name;
cmd.BeginSample(blendOpName);
if (!passData.isVolumetric)
RendererLighting.EnableBlendStyle(cmd, blendStyleIndex, blendStyleUsed);
bool isShadow = passData.shadowIndex != -1;
var lights = isShadow ? passData.layerBatch.shadowLights : passData.layerBatch.lights;
for (int i = 0; i < lights.Count; ++i)
{
var light = lights[i];
// Check if light is valid
if (light == null ||
light.lightType == Light2D.LightType.Global ||
light.blendStyleIndex != blendStyleIndex ||
(isShadow && passData.shadowIndex != i) )
continue;
// Check if light is volumetric
if (passData.isVolumetric &&
(light.volumeIntensity <= 0.0f ||
!light.volumetricEnabled ||
layerBatch.endLayerValue != light.GetTopMostLitLayer()))
continue;
var lightMaterial = passData.rendererData.GetLightMaterial(light, passData.isVolumetric);
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);
// Set shader global properties
RendererLighting.SetPerLightShaderGlobals(cmd, light, slotIndex, passData.isVolumetric, isShadow, LightBatch.isBatchingSupported);
if (light.normalMapQuality != Light2D.NormalMapQuality.Disabled || light.lightType == Light2D.LightType.Point)
RendererLighting.SetPerPointLightShaderGlobals(passData.rendererData, cmd, light, slotIndex, LightBatch.isBatchingSupported);
RendererLighting.SetCookieShaderGlobals(cmd, light);
ShadowRendering.SetGlobalShadowProp(cmd);
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);
}
}
RendererLighting.EnableBlendStyle(cmd, blendStyleIndex, false);
cmd.EndSample(blendOpName);
}
}
}
class PassData
{
internal LayerBatch layerBatch;
internal Renderer2DData rendererData;
internal int shadowIndex;
internal bool isVolumetric;
}
public void Render(RenderGraph graph, ref Renderer2DData rendererData, ref LayerBatch layerBatch, in TextureHandle lightTexture, in TextureHandle normalTexture, in TextureHandle depthTexture, in TextureHandle shadowTexture, int shadowlightIndex = -1, bool isVolumetric = false)
{
intermediateTexture[0] = lightTexture;
Render(graph, ref rendererData, ref layerBatch, intermediateTexture, normalTexture, depthTexture, shadowTexture, shadowlightIndex, isVolumetric);
}
public void Render(RenderGraph graph, ref Renderer2DData rendererData, ref LayerBatch layerBatch, in TextureHandle[] lightTextures, in TextureHandle normalTexture, in TextureHandle depthTexture, in TextureHandle shadowTexture, int shadowlightIndex = -1, bool isVolumetric = false)
{
if (!layerBatch.lightStats.useLights ||
isVolumetric && !layerBatch.lightStats.useVolumetricLights)
return;
if (layerBatch.lightStats.useNormalMap)
RenderGraphUtils.SetGlobalTexture(graph, k_NormalMapID, normalTexture, "Set Normal");
if (layerBatch.lightStats.useShadows)
RenderGraphUtils.SetGlobalTexture(graph, k_ShadowMapID, shadowTexture, "Set Shadows");
RenderGraphUtils.SetGlobalTexture(graph, k_FalloffLookupID, graph.ImportTexture(m_FallOffRTHandle), "Set Global FalloffLookup");
RenderGraphUtils.SetGlobalTexture(graph, k_LightLookupID, graph.ImportTexture(m_LightLookupRTHandle), "Set Global LightLookup");
using (var builder = graph.AddRasterRenderPass<PassData>("Light 2D Pass", out var passData, !isVolumetric ? m_ProfilingSampler : m_ProfilingSamplerVolume))
{
for (var i = 0; i < lightTextures.Length; i++)
builder.UseTextureFragment(lightTextures[i], i);
builder.UseTextureFragmentDepth(depthTexture, IBaseRenderGraphBuilder.AccessFlags.Write);
if (layerBatch.lightStats.useNormalMap)
builder.UseTexture(normalTexture);
if (layerBatch.lightStats.useShadows)
builder.UseTexture(shadowTexture);
var lights = shadowlightIndex != -1 ? layerBatch.shadowLights : layerBatch.lights;
foreach (var light in lights)
{
if (light.m_CookieSpriteTextureHandle.IsValid())
builder.UseTexture(light.m_CookieSpriteTextureHandle);
}
passData.layerBatch = layerBatch;
passData.rendererData = rendererData;
passData.shadowIndex = shadowlightIndex;
passData.isVolumetric = isVolumetric;
builder.AllowPassCulling(false);
builder.AllowGlobalStateModification(true);
builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
{
Execute(context.cmd, data, ref data.layerBatch);
});
}
}
}
}