Files
Shopping_UnityVR/Packages/com.baddog.rendering.arealight/Runtime/Passes/AreaLightingPass.Legacy.cs
2026-04-16 04:58:10 +09:00

309 lines
15 KiB
C#

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace BadDog.Rendering.AreaLight
{
public partial class AreaLightingPass
{
partial void AllocateShadowmapIfNeeded()
{
if (m_CreateEmptyShadowmap)
{
// Allocate minimal 1x1 shadowmap for shader compatibility
ShadowUtils.ShadowRTReAllocateIfNeeded(ref m_AreaLightsShadowmapHandle, 1, 1, k_ShadowmapBufferBits, name: "_AreaLightsShadowmapTexture");
}
else
{
// Allocate actual shadowmap atlas for rendering shadows
ShadowUtils.ShadowRTReAllocateIfNeeded(ref m_AreaLightsShadowmapHandle, m_RenderTargetWidth, m_RenderTargetHeight, k_ShadowmapBufferBits, name: "_AreaLightsShadowmapTexture");
}
}
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
if (m_AreaLightsShadowmapHandle != null)
{
ConfigureTarget(m_AreaLightsShadowmapHandle);
if (m_EmptyShadowmapNeedsClear || !m_CreateEmptyShadowmap)
{
ConfigureClear(ClearFlag.All, Color.black);
m_EmptyShadowmapNeedsClear = false;
}
}
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get();
using (new ProfilingScope(cmd, m_ProfilingSampler))
{
// Enable global shader keyword for BG Area Lighting
CoreUtils.SetKeyword(cmd, AreaLightingShaderIDs.ENABLE_BG_AREA_LIGHTING_KEYWORD, true);
// Build LTC data texture (uses reference counting, safe to call multiple times)
LTCAreaLight.instance.Build();
LTCAreaLight.instance.Bind(cmd);
// GGX + Disney Diffuse
PreIntegratedFGD.instance.Build(PreIntegratedFGD.FGDIndex.FGD_GGXAndDisneyDiffuse);
PreIntegratedFGD.instance.RenderInit(PreIntegratedFGD.FGDIndex.FGD_GGXAndDisneyDiffuse, cmd);
PreIntegratedFGD.instance.Bind(cmd, PreIntegratedFGD.FGDIndex.FGD_GGXAndDisneyDiffuse);
// Charlie + Fabric Lambert
PreIntegratedFGD.instance.Build(PreIntegratedFGD.FGDIndex.FGD_CharlieAndFabricLambert);
PreIntegratedFGD.instance.RenderInit(PreIntegratedFGD.FGDIndex.FGD_CharlieAndFabricLambert, cmd);
PreIntegratedFGD.instance.Bind(cmd, PreIntegratedFGD.FGDIndex.FGD_CharlieAndFabricLambert);
// Marschner
PreIntegratedFGD.instance.Build(PreIntegratedFGD.FGDIndex.FGD_Marschner);
PreIntegratedFGD.instance.RenderInit(PreIntegratedFGD.FGDIndex.FGD_Marschner, cmd);
PreIntegratedFGD.instance.Bind(cmd, PreIntegratedFGD.FGDIndex.FGD_Marschner);
var lightData = renderingData.lightData;
var visibleLights = lightData.visibleLights;
var areaLightDataArray = BGAreaLightManager.BuildAreaLightDataArray(visibleLights, lightData.mainLightIndex, m_LightSettings.maxAreaLights);
var areaLightBuffer = BGAreaLightManager.UpdateGraphicsBuffer(areaLightDataArray);
if (areaLightBuffer != null)
{
cmd.SetGlobalBuffer(AreaLightingShaderIDs._AreaLightDataBuffer, areaLightBuffer);
cmd.SetGlobalInt(AreaLightingShaderIDs._AreaLightDataBufferCount,
areaLightDataArray.IsCreated ? areaLightDataArray.Length : 0);
}
else
{
var emptyBuffer = BGAreaLightManager.GetEmptyBuffer();
cmd.SetGlobalBuffer(AreaLightingShaderIDs._AreaLightDataBuffer, emptyBuffer);
cmd.SetGlobalInt(AreaLightingShaderIDs._AreaLightDataBufferCount, 0);
}
}
if (m_CreateEmptyShadowmap)
{
SetShadowParamsForEmptyShadowmap(cmd);
if (m_AreaLightsShadowmapHandle != null)
{
cmd.SetGlobalTexture(AreaLightingShaderIDs._AreaLightsShadowmapTexture, m_AreaLightsShadowmapHandle.nameID);
}
}
else
{
RenderAreaLightShadows(context, ref renderingData, cmd);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
private void InitRendererLists(ref CullingResults cullResults, ref PassData passData, ScriptableRenderContext context)
{
if (m_CreateEmptyShadowmap)
{
return;
}
for (int shadowSliceIndex = 0; shadowSliceIndex < m_ValidShadowCastingLightsCount; ++shadowSliceIndex)
{
int areaLightIndex = m_ShadowSliceToAreaLightIndex[shadowSliceIndex];
int visibleLightIndex = m_AreaLightIndexToVisibleLightIndex[areaLightIndex];
if (visibleLightIndex < 0 || visibleLightIndex >= passData.visibleLights.Length)
{
passData.shadowRendererLists[shadowSliceIndex] = default;
continue;
}
Light shadowLight = passData.visibleLights[visibleLightIndex].light;
int layerMask = shadowLight != null ? shadowLight.cullingMask : ~0;
bool useRenderingLayers = UniversalRenderPipeline.asset != null && UniversalRenderPipeline.asset.useRenderingLayers;
uint renderingLayerMask = useRenderingLayers && shadowLight != null
? (uint)shadowLight.renderingLayerMask
: uint.MaxValue;
var sorting = new SortingSettings(passData.camera) { criteria = SortingCriteria.None };
var ds = new DrawingSettings(new ShaderTagId("ShadowCaster"), sorting);
var fs = new FilteringSettings(RenderQueueRange.all, layerMask, renderingLayerMask);
RendererListParams param = new RendererListParams(cullResults, ds, fs);
passData.shadowRendererLists[shadowSliceIndex] = context.CreateRendererList(ref param);
}
}
private void RenderAreaLightShadowmapAtlas(CommandBuffer cmd, ref PassData data)
{
using (new ProfilingScope(cmd, m_ShadowProfilingSampler))
{
SetBGAreaLightShadowQualityKeywords(cmd);
bool anyShadowSliceRendered = false;
int shadowSlicesCount = m_ShadowSliceToAreaLightIndex.Count;
Vector4 lastShadowBias = new Vector4(-10f, -10f, -10f, -10f);
for (int globalShadowSliceIndex = 0; globalShadowSliceIndex < shadowSlicesCount; ++globalShadowSliceIndex)
{
int areaLightIndex = m_ShadowSliceToAreaLightIndex[globalShadowSliceIndex];
if (areaLightIndex < 0)
{
continue;
}
Vector4 shadowParams = m_AreaLightIndexToShadowParams[areaLightIndex];
// Check if shadow is valid: w != -1 and shadowStrength > 0
if (Mathf.Approximately(shadowParams.x, 0.0f) || Mathf.Approximately(shadowParams.w, -1.0f))
{
continue;
}
int visibleLightIndex = m_AreaLightIndexToVisibleLightIndex[areaLightIndex];
if (visibleLightIndex < 0 || visibleLightIndex >= data.visibleLights.Length)
{
continue;
}
VisibleLight shadowLight = data.visibleLights[visibleLightIndex];
ShadowSliceData shadowSliceData = m_AreaLightsShadowSlices[globalShadowSliceIndex];
// Get nearPlane for this light (matching the logic in TryComputeAreaLightShadowSlice)
Light unityLight = shadowLight.light;
float nearPlane;
if (unityLight != null &&
BGAreaLightManager.TryGetRegisteredAreaLight(unityLight, out var areaLightComp))
{
nearPlane = areaLightComp.GetShadowNearPlane();
}
else
{
nearPlane = unityLight != null ? unityLight.shadowNearPlane : 0.1f;
}
Vector4 shadowBias = AreaShadowUtils.GetRectangleLightShadowBias(ref shadowLight,
ref m_ShadowDataCache, shadowSliceData.resolution, nearPlane, m_ShadowSettings.shadowFilter);
if (globalShadowSliceIndex == 0 || !AreaShadowUtils.FastApproximately(shadowBias, lastShadowBias))
{
SetShadowBias(cmd, shadowBias);
lastShadowBias = shadowBias;
}
Vector3 lightPosition = shadowLight.localToWorldMatrix.GetColumn(3);
SetLightPosition(cmd, lightPosition);
RendererList shadowRendererList = data.shadowRendererLists[globalShadowSliceIndex];
RenderShadowSlice(cmd, ref shadowSliceData, ref shadowRendererList,
shadowSliceData.projectionMatrix, shadowSliceData.viewMatrix);
anyShadowSliceRendered = true;
}
if (anyShadowSliceRendered)
{
SetupAreaLightsShadowReceiverConstants(cmd, data.allocatedShadowAtlasSize);
cmd.SetViewProjectionMatrices(data.viewMatrix, data.projectionMatrix);
}
}
}
private void InitPassData(ref PassData passData, in CameraData cameraData, in LightData lightData)
{
passData.pass = this;
passData.emptyShadowmap = m_CreateEmptyShadowmap;
passData.visibleLights = lightData.visibleLights;
passData.viewMatrix = cameraData.GetViewMatrix();
passData.projectionMatrix = cameraData.GetProjectionMatrix();
passData.camera = cameraData.camera;
passData.shadowRendererLists = m_ShadowRendererLists;
}
private void RenderAreaLightShadows(ScriptableRenderContext context, ref RenderingData renderingData, CommandBuffer cmd)
{
var cameraData = renderingData.cameraData;
var lightData = renderingData.lightData;
InitPassData(ref m_PassData, cameraData, lightData);
InitRendererLists(ref renderingData.cullResults, ref m_PassData, context);
m_PassData.allocatedShadowAtlasSize = new Vector2Int(m_RenderTargetWidth, m_RenderTargetHeight);
RenderAreaLightShadowmapAtlas(cmd, ref m_PassData);
if (m_AreaLightsShadowmapHandle != null)
{
cmd.SetGlobalTexture(AreaLightingShaderIDs._AreaLightsShadowmapTexture, m_AreaLightsShadowmapHandle.nameID);
}
}
private void SetShadowBias(CommandBuffer cmd, Vector4 shadowBias)
{
cmd.SetGlobalVector(AreaLightingShaderIDs._ShadowBias, shadowBias);
}
private void SetLightPosition(CommandBuffer cmd, Vector3 lightPosition)
{
cmd.SetGlobalVector(AreaLightingShaderIDs._LightPosition,
new Vector4(lightPosition.x, lightPosition.y, lightPosition.z, 1.0f));
}
private void RenderShadowSlice(CommandBuffer cmd, ref ShadowSliceData shadowSliceData, ref RendererList shadowRendererList,
Matrix4x4 proj, Matrix4x4 view)
{
cmd.SetGlobalDepthBias(1.0f, 2.5f);
cmd.SetViewport(new Rect(shadowSliceData.offsetX, shadowSliceData.offsetY, shadowSliceData.resolution,
shadowSliceData.resolution));
cmd.SetViewProjectionMatrices(view, proj);
cmd.DrawRendererList(shadowRendererList);
cmd.DisableScissorRect();
cmd.SetGlobalDepthBias(0.0f, 0.0f);
}
private void SetupAreaLightsShadowReceiverConstants(CommandBuffer cmd, Vector2Int atlasSize)
{
cmd.SetGlobalMatrixArray(AreaLightingShaderIDs._AreaLightsWorldToShadow, m_AreaLightShadowSliceIndexTo_WorldShadowMatrix);
cmd.SetGlobalVectorArray(AreaLightingShaderIDs._AreaLightShadowParams, m_AreaLightIndexToShadowParams);
cmd.SetGlobalVector(AreaLightingShaderIDs._AreaLightShadowmapSize, new Vector4(1f / atlasSize.x, 1f / atlasSize.y, atlasSize.x, atlasSize.y));
float pcssShadowSoftness = Mathf.Max(0f, m_ShadowSettings.pcssShadowSoftness);
int pcssBlockerSampleCount = Mathf.Clamp(m_ShadowSettings.pcssBlockerSampleCount, 1, 64);
int pcssFilterSampleCount = Mathf.Clamp(m_ShadowSettings.pcssFilterSampleCount, 1, 64);
cmd.SetGlobalVector(AreaLightingShaderIDs._PCSSAdditionalLightParams, new Vector4(pcssShadowSoftness, pcssBlockerSampleCount, pcssFilterSampleCount, 1.0f));
}
private static void SetShadowParamsForEmptyShadowmap(CommandBuffer cmd)
{
cmd.SetGlobalMatrixArray(AreaLightingShaderIDs._AreaLightsWorldToShadow, s_EmptyShadowMatrices);
cmd.SetGlobalVectorArray(AreaLightingShaderIDs._AreaLightShadowParams, s_EmptyShadowParams);
cmd.SetGlobalVector(AreaLightingShaderIDs._AreaLightShadowmapSize, new Vector4(0f, 0f, 1f, 1f));
cmd.SetGlobalVector(AreaLightingShaderIDs._PCSSAdditionalLightParams, Vector4.zero);
}
private void SetBGAreaLightShadowQualityKeywords(CommandBuffer cmd)
{
cmd.SetKeyword(ShaderGlobalKeywords.BGAreaLightShadowsPCF2x2, false);
cmd.SetKeyword(ShaderGlobalKeywords.BGAreaLightShadowsTent5x5, false);
cmd.SetKeyword(ShaderGlobalKeywords.BGAreaLightShadowsTent7x7, false);
cmd.SetKeyword(ShaderGlobalKeywords.BGAreaLightShadowsPCSS, false);
switch (m_ShadowSettings.shadowFilter)
{
case AreaLightShadowSettings.BGAreaLightShadowMode.PCF2x2:
cmd.SetKeyword(ShaderGlobalKeywords.BGAreaLightShadowsPCF2x2, true);
break;
case AreaLightShadowSettings.BGAreaLightShadowMode.Tent5x5:
cmd.SetKeyword(ShaderGlobalKeywords.BGAreaLightShadowsTent5x5, true);
break;
case AreaLightShadowSettings.BGAreaLightShadowMode.Tent7x7:
cmd.SetKeyword(ShaderGlobalKeywords.BGAreaLightShadowsTent7x7, true);
break;
case AreaLightShadowSettings.BGAreaLightShadowMode.PCSS:
cmd.SetKeyword(ShaderGlobalKeywords.BGAreaLightShadowsPCSS, true);
break;
case AreaLightShadowSettings.BGAreaLightShadowMode.Off:
default:
// All keywords disabled (handled above)
break;
}
}
}
}