#ifndef UNIVERSAL_DEFERRED_INCLUDED
#define UNIVERSAL_DEFERRED_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/SurfaceInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityGBuffer.hlsl"
#define PREFERRED_CBUFFER_SIZE (64 * 1024)
#define SIZEOF_VEC4_TILEDATA 1 // uint4
#define SIZEOF_VEC4_PUNCTUALLIGHTDATA 5 // 5 * float4
#define MAX_DEPTHRANGE_PER_CBUFFER_BATCH (PREFERRED_CBUFFER_SIZE / 4) // Should be ushort, but extra unpacking code is "too expensive"
#define MAX_TILES_PER_CBUFFER_PATCH (PREFERRED_CBUFFER_SIZE / (16 * SIZEOF_VEC4_TILEDATA))
#define MAX_PUNCTUALLIGHT_PER_CBUFFER_BATCH (PREFERRED_CBUFFER_SIZE / (16 * SIZEOF_VEC4_PUNCTUALLIGHTDATA))
#define MAX_REL_LIGHT_INDICES_PER_CBUFFER_BATCH (PREFERRED_CBUFFER_SIZE / 4) // Should be ushort, but extra unpacking code is "too expensive"
// Keep in sync with kUseCBufferForDepthRange.
// Keep in sync with kUseCBufferForTileData.
// Keep in sync with kUseCBufferForLightData.
// Keep in sync with kUseCBufferForLightList.
#if defined(SHADER_API_SWITCH)
#define USE_CBUFFER_FOR_DEPTHRANGE 0
#define USE_CBUFFER_FOR_TILELIST 0
#define USE_CBUFFER_FOR_LIGHTDATA 1
#define USE_CBUFFER_FOR_LIGHTLIST 0
#elif defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) || defined(SHADER_API_GLCORE)
#define USE_CBUFFER_FOR_DEPTHRANGE 1
#define USE_CBUFFER_FOR_TILELIST 1
#define USE_CBUFFER_FOR_LIGHTDATA 1
#define USE_CBUFFER_FOR_LIGHTLIST 1
#else
#define USE_CBUFFER_FOR_DEPTHRANGE 0
#define USE_CBUFFER_FOR_TILELIST 0
#define USE_CBUFFER_FOR_LIGHTDATA 1
#define USE_CBUFFER_FOR_LIGHTLIST 0
#endif
struct PunctualLightData
{
float3 posWS;
float radius2; // squared radius
half4 color;
half4 attenuation; // .xy are used by DistanceAttenuation - .zw are used by AngleAttenuation (for SpotLights)
half3 spotDirection; // spotLights support
int flags; // Light flags (enum kLightFlags and LightFlag in C# code)
half4 occlusionProbeInfo;
int shadowLightIndex;
};
Light UnityLightFromPunctualLightDataAndWorldSpacePosition(PunctualLightData punctualLightData, float3 positionWS, half4 shadowMask, bool materialFlagReceiveShadowsOff)
{
// Keep in sync with GetAdditionalPerObjectLight in Lighting.hlsl
half4 probesOcclusion = shadowMask;
Light light;
float3 lightVector = punctualLightData.posWS - positionWS.xyz;
float distanceSqr = max(dot(lightVector, lightVector), HALF_MIN);
half3 lightDirection = half3(lightVector * rsqrt(distanceSqr));
half attenuation = DistanceAttenuation(distanceSqr, punctualLightData.attenuation.xy) * AngleAttenuation(punctualLightData.spotDirection.xyz, lightDirection, punctualLightData.attenuation.zw);
light.direction = lightDirection;
light.color = punctualLightData.color.rgb;
light.distanceAttenuation = attenuation;
// Baked lighting has been set to subtractive, which means:
// -static geometry do not receive any realtime lighting
// -dynamic geometry receive realtime lighting and any baked shadows are approximated using occlusion probes.
#if defined(_DEFERRED_SUBTRACTIVE_LIGHTING)
// First find the probe channel from the light.
// Then sample `unity_ProbesOcclusion` for the baked occlusion.
// If the light is not baked, the channel is -1, and we need to apply no occlusion.
// probeChannel is the index in 'unity_ProbesOcclusion' that holds the proper occlusion value.
int probeChannel = punctualLightData.occlusionProbeInfo.x;
// lightProbeContribution is set to 0 if we are indeed using a probe, otherwise set to 1.
half lightProbeContribution = punctualLightData.occlusionProbeInfo.y;
half probeOcclusionValue = probesOcclusion[probeChannel];
light.distanceAttenuation *= max(probeOcclusionValue, lightProbeContribution);
#endif
[branch] if (materialFlagReceiveShadowsOff)
light.shadowAttenuation = 1.0;
else
{
light.shadowAttenuation = AdditionalLightRealtimeShadow(punctualLightData.shadowLightIndex, positionWS);
light.shadowAttenuation = ApplyShadowFade(light.shadowAttenuation, positionWS);
}
return light;
}
#endif