Files
UnrealEngineUWP/Engine/Shaders/Private/PathTracing/Material/PathTracingMedium.ush
chris kulla 100676517b Path Tracer: Add basic Substrate support
Implement the core slab BSDF in the path tracer. When Strata is enabled, enlarge the payload slightly to be able to encode a slab without needing to rely on Substrate's packing routines. This allows the path tracer to be more independent of the project settings. Multiple slabs are handled by stochastically returning a single slab from the hit shader. This approaches greatly simplifies the handling of SSS slabs and refractive/translucent cases in the future.

Also added a cvar that lets you toggle (at runtime) to the fully simplified form of the material. This doesn't appear that much faster, but it could be interesting to validate the appearance of the simplification procedure. It is gated by an extra cvar to avoid compiling extra permutations by default.

#rb Sebastien.Hillaire, Charles.deRousiers
#jira UE-173840
#preflight 642709ca91589478cd1575ed

[CL 24874059 by chris kulla in ue5-main branch]
2023-03-31 13:00:22 -04:00

70 lines
2.7 KiB
Plaintext

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================================
PathTracingMedium.usf: Volumetric phase function
To support atmosphere, we represent a blend of two components: rayleigh scattering and an HG lobe
In the future, we may add additional HG lobe for cases like cloud rendering
===============================================================================================*/
#pragma once
#include "../../ParticipatingMediaCommon.ush"
#define USE_UNIFORM_PHASE_FUNCTION 0
FMaterialSample Medium_SampleMaterial(
float3 V_World,
FPathTracingPayload Payload,
float3 RandSample)
{
const float3 RayleighWeight = Payload.GetBaseColor();
const float3 HGWeight = Payload.GetHGWeight();
const float G = Payload.GetHGPhaseG();
#if USE_UNIFORM_PHASE_FUNCTION
const float4 Result = UniformSampleSphere(RandSample.xy);
// uniform scattering
return CreateMaterialSample(Result.xyz, RayleighWeight + HGWeight, Result.w, 1.0, 1.0, PATHTRACER_SCATTER_VOLUME);
#else
const float LobeProb = LobeSelectionProb(RayleighWeight, HGWeight);
const float CosTheta = RandSample.x < LobeProb ?
RayleighPhaseInvertCdf(RescaleRandomNumber(RandSample.x, 0.0, LobeProb)) :
HenyeyGreensteinPhaseInvertCDF(RescaleRandomNumber(RandSample.x, LobeProb, 1.0), G);
const float SinTheta = sqrt(saturate(1.0 - CosTheta * CosTheta));
const float Phi = RandSample.y * (2.0 * PI);
const float3 L_World = TangentToWorld(float3(cos(Phi) * SinTheta, sin(Phi) * SinTheta, CosTheta), -V_World);
FMaterialSample Result = CreateMaterialSample(L_World, 0.0, 0.0, 1.0, 1.0, PATHTRACER_SCATTER_VOLUME);
Result.AddLobeWithMIS(RayleighWeight, RayleighPhase(CosTheta), LobeProb);
Result.AddLobeWithMIS(HGWeight , HenyeyGreensteinPhase(G, CosTheta ) , 1.0 - LobeProb);
return Result;
#endif
}
FMaterialEval Medium_EvalMaterial(
float3 V_World,
float3 L_World,
FPathTracingPayload Payload,
float2 DiffuseSpecularScale
)
{
const float3 RayleighWeight = Payload.GetBaseColor();
const float3 HGWeight = Payload.GetHGWeight();
const float G = Payload.GetHGPhaseG();
#if USE_UNIFORM_PHASE_FUNCTION
// simple omni-directional evaluation
return CreateMaterialEval((RayleighWeight + HGWeight) * DiffuseSpecularScale.x, 1.0 / (4 * PI));
#else
const float LobeProb = LobeSelectionProb(RayleighWeight, HGWeight);
const float CosTheta = dot(V_World, L_World);
FMaterialEval Result = NullMaterialEval();
Result.AddLobeWithMIS(RayleighWeight, RayleighPhase(CosTheta), LobeProb);
Result.AddLobeWithMIS(HGWeight , HenyeyGreensteinPhase(G, CosTheta), 1.0 - LobeProb);
Result.Weight *= DiffuseSpecularScale.x;
return Result;
#endif
}