190 lines
5.7 KiB
HLSL
190 lines
5.7 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#define SUPPORT_CONTACT_SHADOWS 0
|
|
#define ALLOW_LOCAL_LIGHT_DISTANCE_ATTENUATION 1
|
|
#define MAX_UINT 4294967295
|
|
|
|
#if !COMPUTE_SHADER
|
|
#include "Common.ush"
|
|
#include "SceneTextureParameters.ush"
|
|
#include "DeferredLightingCommon.ush"
|
|
#define MERGED_LOCAL_LIGHTS_MOBILE 1
|
|
#include "MobileLightingCommon.ush"
|
|
#endif
|
|
|
|
#if LIGHT_FUNCTION
|
|
#include "/Engine/Generated/Material.ush"
|
|
#include "LightDataUniforms.ush"
|
|
#include "LightFunctionCommon.ush"
|
|
#else
|
|
#include "LightGridCommon.ush"
|
|
#endif
|
|
|
|
#if COMPUTE_SHADER
|
|
|
|
uint2 GroupSize;
|
|
RWBuffer<uint> RWTileInfo;
|
|
[numthreads(THREADGROUP_SIZEX, 1, 1)]
|
|
void MainCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
if(DispatchThreadId.x > (GroupSize.x * GroupSize.y))
|
|
{
|
|
return;
|
|
}
|
|
|
|
const uint GridX = DispatchThreadId.x % GroupSize.x;
|
|
const uint GridY = DispatchThreadId.x / GroupSize.x;
|
|
const uint EyeIndex = 0;
|
|
const FLightGridData GridData = GetLightGridData();
|
|
uint NumLightsInGridCell = 0;
|
|
LOOP
|
|
for (int SliceIt = 0; SliceIt < GridData.CulledGridSize.z; SliceIt++)
|
|
{
|
|
const uint GridIndex = ComputeLightGridCellIndex(uint3(GridX, GridY, SliceIt), EyeIndex);
|
|
const FCulledLightsGridHeader CulledLightsGridHeader = GetCulledLightsGridHeader(GridIndex);
|
|
|
|
NumLightsInGridCell = CulledLightsGridHeader.NumLights;
|
|
|
|
if(NumLightsInGridCell > 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(NumLightsInGridCell > 0)
|
|
{
|
|
RWTileInfo[2 * DispatchThreadId.x] = GridX;
|
|
RWTileInfo[2 * DispatchThreadId.x + 1] = GridY;
|
|
}
|
|
else
|
|
{
|
|
RWTileInfo[2 * DispatchThreadId.x] = MAX_UINT;
|
|
RWTileInfo[2 * DispatchThreadId.x + 1] = MAX_UINT;
|
|
}
|
|
}
|
|
|
|
#else // COMPUTE_SHADER
|
|
|
|
#if !LIGHT_FUNCTION
|
|
|
|
int LightGridPixelSize;
|
|
Buffer<uint> TileInfo;
|
|
void MainVS(
|
|
float2 TexCoord : ATTRIBUTE0,
|
|
uint VertexId : SV_VertexID,
|
|
uint InstanceId : SV_InstanceID,
|
|
out float4 OutPosition : SV_POSITION)
|
|
{
|
|
float YPos = TileInfo[2 * InstanceId + 1] + TexCoord.y;
|
|
float XPos = TileInfo[2 * InstanceId] + TexCoord.x;
|
|
|
|
float2 ScreenUV = float2(XPos, YPos) * LightGridPixelSize * View.BufferSizeAndInvSize.zw;
|
|
float2 ScreenPosition = (ScreenUV.xy - View.ScreenPositionScaleBias.wz) / View.ScreenPositionScaleBias.xy;
|
|
OutPosition = float4(ScreenPosition, 0, 1);
|
|
|
|
if(TileInfo[2 * InstanceId] == MAX_UINT)
|
|
{
|
|
OutPosition.xy = 0;
|
|
}
|
|
}
|
|
|
|
void Main(float4 SvPosition : SV_POSITION
|
|
, out float3 OutColorA : SV_Target0
|
|
, out float4 OutColorB : SV_Target1
|
|
)
|
|
{
|
|
const uint2 PixelPos = SvPosition.xy;
|
|
const float2 ScreenPosition = SvPositionToScreenPosition(SvPosition).xy;
|
|
const uint EyeIndex = 0;
|
|
|
|
float2 ScreenUV = ScreenPosition * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz;
|
|
float DeviceZ = LookupDeviceZ(ScreenUV);
|
|
float SceneDepth = ConvertFromDeviceZ(DeviceZ);
|
|
|
|
float3 TranslatedWorldPosition = mul(float4(ScreenPosition * SceneDepth, SceneDepth, 1), PrimaryView.ScreenToTranslatedWorld).xyz;
|
|
float3 CameraVector = normalize(TranslatedWorldPosition);
|
|
|
|
uint GridIndex = ComputeLightGridCellIndex(uint2(PixelPos.x, PixelPos.y), SceneDepth, EyeIndex);
|
|
const FCulledLightsGridHeader CulledLightsGridHeader = GetCulledLightsGridHeader(GridIndex);
|
|
|
|
float3 MergedLightColor = uint3(0.f, 0.f , 0.f);
|
|
float3 MergedLightL = float3(0,0,0);
|
|
float MergedSpecularScale = 0.f;
|
|
float MergedTotalWeight = 0;
|
|
MergeLocalLights(CulledLightsGridHeader, TranslatedWorldPosition, EyeIndex, true, MergedLightColor, MergedLightL, MergedSpecularScale, MergedTotalWeight);
|
|
|
|
if (MergedTotalWeight > 0)
|
|
{
|
|
MergedLightL = (MergedLightL / MergedTotalWeight);
|
|
OutColorA = float3(MergedLightColor.x, MergedLightColor.y, MergedLightColor.z);
|
|
OutColorB.rgb = Pack1212To888(UnitVectorToOctahedron(MergedLightL) * 0.5 + 0.5);
|
|
OutColorB.a = MergedSpecularScale / MergedTotalWeight;
|
|
}
|
|
else
|
|
{
|
|
OutColorA = float3(0, 0, 0);
|
|
OutColorB = float4(0.5f, 0.5f, 0.5f, 0.f);
|
|
#if GENERATE_LIGHT_FUNCTION_DEPTH_STENCIL
|
|
// Clip to avoid writing to stencil
|
|
clip(-1);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#else // !LIGHT_FUNCTION
|
|
|
|
float4x4 SvPositionToLight;
|
|
/** Fade distance in x, disabled brightness in y */
|
|
float2 LightFunctionParameters2;
|
|
|
|
void MainLightFunction(
|
|
float4 InScreenPosition : TEXCOORD0,
|
|
float4 SvPosition : SV_POSITION,
|
|
out float3 OutColorA : SV_Target0
|
|
)
|
|
{
|
|
float2 ScreenUV = SvPositionToBufferUV(SvPosition);
|
|
SvPosition.z = LookupDeviceZ(ScreenUV);
|
|
float3 TranslatedWorldPosition = SvPositionToTranslatedWorld(SvPosition);
|
|
|
|
FDeferredLightData LightData = InitDeferredLightFromUniforms();
|
|
float3 L = LightData.Direction; // Already normalized
|
|
float3 ToLight = LightData.TranslatedWorldPosition - TranslatedWorldPosition;
|
|
float LightMask = 1;
|
|
// At the moment directional lights are not supported
|
|
// if (LightData.bRadialLight)
|
|
{
|
|
LightMask = GetLocalLightAttenuation( TranslatedWorldPosition, LightData, ToLight, L );
|
|
}
|
|
|
|
if (LightMask <= 0)
|
|
{
|
|
OutColorA = float3(0, 0, 0);
|
|
return;
|
|
}
|
|
|
|
float EncodedLightAttenuation;
|
|
{
|
|
float ViewDistance = length(GetPrimaryView().TranslatedWorldCameraOrigin - TranslatedWorldPosition);
|
|
float4 Hom = mul(float4(SvPosition.xyz, 1), SvPositionToLight);
|
|
float3 LightVector = Hom.xyz / Hom.w;
|
|
float3 Color = GetLightFunctionColor(LightVector, TranslatedWorldPosition);
|
|
float GreyScale = dot(Color, .3333f);
|
|
|
|
float DistanceFadeAlpha = saturate((LightFunctionParameters2.x - ViewDistance) / (LightFunctionParameters2.x * .2f));
|
|
GreyScale = lerp(LightFunctionParameters2.y, GreyScale, DistanceFadeAlpha);
|
|
GreyScale = lerp(LightFunctionParameters2.y, GreyScale, LightFunctionParameters.y);
|
|
EncodedLightAttenuation = EncodeLightAttenuation(GreyScale);
|
|
}
|
|
|
|
float3 Color = LightData.Color * LightMask * EncodedLightAttenuation;
|
|
|
|
OutColorA = Color;
|
|
}
|
|
#endif // !LIGHT_FUNCTION
|
|
|
|
#endif // COMPUTE_SHADER
|