102 lines
2.8 KiB
HLSL
102 lines
2.8 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================================
|
|
SkyLight.usf: Light sampling functions for SkyLight implementation
|
|
===============================================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "../../RayTracing/RayTracingSkyLightCommon.ush"
|
|
|
|
// By default, assume MIS is performed in the integrator.
|
|
// However in some cases like RTGI we may want to have _some_ basic MIS
|
|
// without introducing complexity in the integrator.
|
|
#ifndef PATHTRACING_SKY_MIS
|
|
#define PATHTRACING_SKY_MIS 0
|
|
#endif
|
|
|
|
float SkyLight_EstimateLight(
|
|
int LightId,
|
|
float3 WorldNormal,
|
|
bool IsTransmissiveMaterial
|
|
)
|
|
{
|
|
#if PATHTRACING_SKY_MIS == 0
|
|
return SkyLight_Estimate();
|
|
#else
|
|
return 2 * PI;
|
|
#endif
|
|
}
|
|
|
|
FLightHit SkyLight_TraceLight(FRayDesc Ray, int LightId)
|
|
{
|
|
if (Ray.TMax == RAY_DEFAULT_T_MAX)
|
|
{
|
|
float4 Result = SkyLight_EvalLight(Ray.Direction);
|
|
return CreateLightHit(Result.xyz, Result.w, RAY_DEFAULT_T_MAX);
|
|
}
|
|
return NullLightHit();
|
|
}
|
|
|
|
FLightSample SkyLight_SampleLight(
|
|
int LightId,
|
|
float2 RandSample,
|
|
float3 WorldNormal
|
|
)
|
|
{
|
|
#if PATHTRACING_SKY_MIS == 0
|
|
FSkyLightSample Sample = SkyLight_SampleLight(RandSample);
|
|
return CreateLightSample(Sample.Radiance / Sample.Pdf, Sample.Pdf, Sample.Direction, RAY_DEFAULT_T_MAX);
|
|
#else
|
|
// account for the fact that with MIS compensation, we could have a 0 probability of choosing the sky
|
|
float SkyLightSamplingStrategyPdf = SkyLight_Estimate() > 0.0 ? 0.5 : 0.0;
|
|
|
|
// Do a simple one-sample MIS between the skylight and cosine sampling on the assumption that
|
|
// the shading loop is only sampling the light and not doing its own MIS.
|
|
float3 SkyLightRadiance = 0;
|
|
float3 Direction = 0;
|
|
float CosinePdf = 0;
|
|
float SkyLightPdf = 0;
|
|
BRANCH if (RandSample.x < SkyLightSamplingStrategyPdf)
|
|
{
|
|
RandSample.x /= SkyLightSamplingStrategyPdf;
|
|
|
|
FSkyLightSample SkySample = SkyLight_SampleLight(RandSample);
|
|
|
|
SkyLightRadiance = SkySample.Radiance;
|
|
Direction = SkySample.Direction;
|
|
SkyLightPdf = SkySample.Pdf;
|
|
CosinePdf = saturate(dot(WorldNormal, Direction)) / PI;
|
|
}
|
|
else
|
|
{
|
|
RandSample.x = (RandSample.x - SkyLightSamplingStrategyPdf) / (1.0 - SkyLightSamplingStrategyPdf);
|
|
|
|
float4 CosSample = CosineSampleHemisphere(RandSample, WorldNormal);
|
|
|
|
Direction = CosSample.xyz;
|
|
CosinePdf = CosSample.w;
|
|
|
|
float4 SkyEval = SkyLight_EvalLight(Direction);
|
|
SkyLightRadiance = SkyEval.xyz;
|
|
SkyLightPdf = SkyEval.w;
|
|
}
|
|
|
|
float Pdf = lerp(CosinePdf, SkyLightPdf, SkyLightSamplingStrategyPdf);
|
|
|
|
return CreateLightSample(SkyLightRadiance / Pdf, Pdf, Direction, RAY_DEFAULT_T_MAX);
|
|
#endif
|
|
}
|
|
|
|
// NOTE: unused
|
|
FVolumeLightSampleSetup SkyLight_PrepareLightVolumeSample(
|
|
int LightId,
|
|
float3 RayOrigin,
|
|
float3 RayDirection,
|
|
float TMin,
|
|
float TMax
|
|
)
|
|
{
|
|
return CreateUniformSampler(4 * PI, TMin, TMax);
|
|
}
|