Implement shadows rendering to direct light atlas (with Glboal SDF tracing)
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#define GLOBAL_SDF_RASTERIZE_CHUNK_SIZE 32
|
||||
#define GLOBAL_SDF_RASTERIZE_CHUNK_MARGIN 4
|
||||
#define GLOBAL_SDF_MIP_FLOODS 5
|
||||
#define GLOBAL_SDF_WORLD_SIZE 60000.0f
|
||||
|
||||
// Global SDF data for a constant buffer
|
||||
struct GlobalSDFData
|
||||
@@ -61,7 +62,7 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4], float3
|
||||
{
|
||||
float distance = data.CascadePosDistance[3].w * 2.0f;
|
||||
if (distance <= 0.0f)
|
||||
return 60000;
|
||||
return GLOBAL_SDF_WORLD_SIZE;
|
||||
UNROLL
|
||||
for (uint cascade = 0; cascade < 4; cascade++)
|
||||
{
|
||||
@@ -83,7 +84,7 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4], float3
|
||||
float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex[4], float3 worldPosition, out float distance)
|
||||
{
|
||||
float3 gradient = float3(0, 0.00001f, 0);
|
||||
distance = 60000;
|
||||
distance = GLOBAL_SDF_WORLD_SIZE;
|
||||
if (data.CascadePosDistance[3].w <= 0.0f)
|
||||
return gradient;
|
||||
UNROLL
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
META_CB_BEGIN(0, Data)
|
||||
float3 ViewWorldPos;
|
||||
float ViewNearPlane;
|
||||
float3 Padding00;
|
||||
float2 Padding00;
|
||||
float LightShadowsStrengthOneMinus;
|
||||
float ViewFarPlane;
|
||||
float4 ViewFrustumWorldRays[4];
|
||||
GlobalSDFData GlobalSDF;
|
||||
@@ -66,6 +67,8 @@ void PS_Clear(out float4 Light : SV_Target0, out float4 RT0 : SV_Target1, out fl
|
||||
|
||||
// GBuffer+Depth at 0-3 slots
|
||||
Buffer<float4> GlobalSurfaceAtlasObjects : register(t4);
|
||||
Texture3D<float> GlobalSDFTex[4] : register(t5);
|
||||
Texture3D<float> GlobalSDFMip[4] : register(t9);
|
||||
|
||||
// Pixel shader for Global Surface Atlas shading with direct light contribution
|
||||
META_PS(true, FEATURE_LEVEL_SM5)
|
||||
@@ -81,11 +84,10 @@ float4 PS_DirectLighting(AtlasVertexOutput input) : SV_Target
|
||||
// Load GBuffer sample from atlas
|
||||
GBufferData gBufferData = (GBufferData)0;
|
||||
GBufferSample gBuffer = SampleGBuffer(gBufferData, atlasUV);
|
||||
|
||||
// Skip unlit pixels
|
||||
BRANCH
|
||||
if (gBuffer.ShadingModel == SHADING_MODEL_UNLIT)
|
||||
{
|
||||
// Skip unlit pixels
|
||||
discard;
|
||||
return 0;
|
||||
}
|
||||
@@ -102,11 +104,43 @@ float4 PS_DirectLighting(AtlasVertexOutput input) : SV_Target
|
||||
float4x4 tileLocalToWorld = Inverse(tile.WorldToLocal);
|
||||
gBuffer.WorldPos = mul(float4(gBufferTilePos, 1), tileLocalToWorld).xyz;
|
||||
|
||||
// Calculate shadowing
|
||||
float3 L = Light.Direction;
|
||||
#if RADIAL_LIGHT
|
||||
float3 toLight = Light.Position - gBuffer.WorldPos;
|
||||
float toLightDst = length(toLight);
|
||||
if (toLightDst >= Light.Radius)
|
||||
{
|
||||
// Skip texels outside the light influence range
|
||||
discard;
|
||||
return 0;
|
||||
}
|
||||
L = toLight / toLightDst;
|
||||
#else
|
||||
float toLightDst = GLOBAL_SDF_WORLD_SIZE;
|
||||
#endif
|
||||
float4 shadowMask = 1;
|
||||
BRANCH
|
||||
if (Light.CastShadows > 0)
|
||||
{
|
||||
// TODO: calculate shadow for the light (use Global SDF)
|
||||
float NoL = dot(gBuffer.Normal, L);
|
||||
float shadowBias = 10.0f;
|
||||
float bias = 2 * shadowBias * saturate(1 - NoL) + shadowBias;
|
||||
BRANCH
|
||||
if (NoL > 0)
|
||||
{
|
||||
// TODO: try using shadow map for on-screen pixels
|
||||
// TODO: try using cone trace with Global SDF for smoother shadow (eg. for sun shadows or for area lights)
|
||||
|
||||
// Shot a ray from light into texel to see if there is any occluder
|
||||
GlobalSDFTrace trace;
|
||||
trace.Init(gBuffer.WorldPos + gBuffer.Normal * shadowBias, L, bias, toLightDst - bias);
|
||||
GlobalSDFHit hit = RayTraceGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, trace);
|
||||
shadowMask = hit.IsHit() ? LightShadowsStrengthOneMinus : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
shadowMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate lighting
|
||||
|
||||
Reference in New Issue
Block a user