Files
FlaxEngine/Source/Shaders/ShadowsCommon.hlsl
2024-04-04 12:54:07 +02:00

89 lines
2.7 KiB
HLSL

// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#ifndef __SHADOWS_COMMON__
#define __SHADOWS_COMMON__
#include "./Flax/Common.hlsl"
// Maximum number of directional light shadows cascaded splits
#define MaxNumCascades 4
// Set default macros if not provided
#ifndef SHADOWS_QUALITY
#define SHADOWS_QUALITY 0
#endif
// Shadow data for the light
struct ShadowData
{
float Sharpness;
float Fade;
float FadeDistance;
float NormalOffsetScale;
float Bias;
uint TilesCount;
float4 CascadeSplits;
};
// Shadow projection tile data for the light
struct ShadowTileData
{
float4 ShadowToAtlas;
float4x4 WorldToShadow;
};
// Loads the shadow data of the light in the shadow buffer
ShadowData LoadShadowsBuffer(Buffer<float4> shadowsBuffer, uint shadowsBufferAddress)
{
// This must match C++
float4 vector0 = shadowsBuffer.Load(shadowsBufferAddress + 0);
float4 vector1 = shadowsBuffer.Load(shadowsBufferAddress + 1);
ShadowData shadow;
uint packed0x = asuint(vector0.x);
shadow.Sharpness = (packed0x & 0x000000ff) * (10.0f / 255.0f);
shadow.Fade = ((packed0x & 0x0000ff00) >> 8) * (1.0f / 255.0f);
shadow.TilesCount = ((packed0x & 0x00ff0000) >> 16);
shadow.FadeDistance = vector0.y;
shadow.NormalOffsetScale = vector0.z;
shadow.Bias = vector0.w;
shadow.CascadeSplits = vector1;
return shadow;
}
// Loads the shadow tile data of the light in the shadow buffer
ShadowTileData LoadShadowsBufferTile(Buffer<float4> shadowsBuffer, uint shadowsBufferAddress, uint tileIndex)
{
// This must match C++
shadowsBufferAddress += tileIndex * 5 + 2;
ShadowTileData tile;
tile.ShadowToAtlas = shadowsBuffer.Load(shadowsBufferAddress + 0);
tile.WorldToShadow[0] = shadowsBuffer.Load(shadowsBufferAddress + 1);
tile.WorldToShadow[1] = shadowsBuffer.Load(shadowsBufferAddress + 2);
tile.WorldToShadow[2] = shadowsBuffer.Load(shadowsBufferAddress + 3);
tile.WorldToShadow[3] = shadowsBuffer.Load(shadowsBufferAddress + 4);
return tile;
}
float3 GetShadowPositionOffset(float offsetScale, float NoL, float3 normal)
{
float normalOffsetScale = saturate(1.0f - NoL);
return normal * (offsetScale * normalOffsetScale);
}
float CalculateSubsurfaceOcclusion(float opacity, float sceneDepth, float shadowMapDepth)
{
float thickness = max(sceneDepth - shadowMapDepth, 0);
float occlusion = 1 - saturate(thickness * lerp(1.0f, 100.0f, opacity));
return shadowMapDepth > 0.99f ? 1 : occlusion;
}
float PostProcessShadow(ShadowData lightShadow, float shadow)
{
// Apply shadow fade and sharpness
shadow = saturate((shadow - 0.5) * lightShadow.Sharpness + 0.5);
shadow = lerp(1.0f, shadow, lightShadow.Fade);
return shadow;
}
#endif