489 lines
18 KiB
HLSL
489 lines
18 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#define PATH_TRACING 1
|
|
#define ENABLE_SKY_LIGHT 1
|
|
#define NEEDS_LIGHTMAP_COORDINATE 0
|
|
#ifdef NEEDS_VERTEX_FACTORY_INTERPOLATION
|
|
#undef NEEDS_VERTEX_FACTORY_INTERPOLATION
|
|
#endif
|
|
// Needed for VertexFactoryInterpolate to interpolate attributes from vertices to hit point
|
|
#define NEEDS_VERTEX_FACTORY_INTERPOLATION 1
|
|
|
|
// This should be good enough for path tracing and avoids having to bind an extra buffer
|
|
#define EYE_ADAPTATION_PREV_FRAME_EXPOSURE 1
|
|
|
|
// Ensure that SSS albedo comes through in the material
|
|
#define SUBSTRATE_SSS_MATERIAL_OVERRIDE 0
|
|
|
|
// Not using precomputed lighting
|
|
#define MATERIAL_SUBSTRATE_OPAQUE_PRECOMPUTED_LIGHTING 0
|
|
|
|
#include "/Engine/Private/Common.ush"
|
|
#include "/Engine/Private/RayTracing/RayTracingCommon.ush"
|
|
#include "/Engine/Private/RayTracing/RayTracingHitGroupCommon.ush"
|
|
#include "/Engine/Private/PathTracing/PathTracingShaderUtils.ush"
|
|
#include "/Engine/Generated/Material.ush"
|
|
#include "/Engine/Generated/VertexFactory.ush"
|
|
|
|
#include "/Engine/Private/RayTracing/RayTracingCalcInterpolants.ush"
|
|
#include "/Engine/Private/ShadingCommon.ush"
|
|
#include "/Engine/Private/DeferredShadingCommon.ush"
|
|
#include "/Engine/Private/SubsurfaceProfileCommon.ush"
|
|
#include "/Engine/Private/BurleyNormalizedSSSCommon.ush"
|
|
#include "/Engine/Private/PathTracing/Material/PathTracingFresnel.ush"
|
|
|
|
#if SUBSTRATE_ENABLED
|
|
#define SUBSTRATE_GPU_LIGHTMASS 1
|
|
#include "/Engine/Private/Substrate/Substrate.ush"
|
|
|
|
#if MATERIAL_IS_SUBSTRATE // SUBSTRATE_TODO: Should this header be guarded from inside instead?
|
|
#include "/Engine/Private/Substrate/SubstrateExport.ush"
|
|
#endif
|
|
|
|
#endif
|
|
|
|
RAY_TRACING_ENTRY_CLOSEST_HIT(GPULightmassMaterialCHS,
|
|
FPackedPathTracingPayload, PackedPayload,
|
|
FRayTracingIntersectionAttributes, Attributes)
|
|
{
|
|
PackedPayload.HitT = RayTCurrent();
|
|
ResolvedView = ResolveView();
|
|
|
|
const float3 TranslatedWorldPosition = TranslatedWorldRayOrigin() + RayTCurrent() * WorldRayDirection();
|
|
const float4 SvPosition = TranslatedWorldPositionToSvPosition(TranslatedWorldPosition);
|
|
|
|
CurrentPayloadInputFlags = PackedPayload.GetFlags();
|
|
|
|
#if VF_SUPPORTS_RAYTRACING_PREPARE_MATERIAL_PIXEL_PARAMETERS
|
|
// this is a newer codepath that is both more flexible and allows for more direct calculation compared to the other codepath
|
|
// TODO: implement such a method for all vertex factories
|
|
float3 GeoNormal = 0;
|
|
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(TranslatedWorldRayOrigin(), WorldRayDirection(), RayTCurrent(), PrimitiveIndex(), Attributes, HitKind(), SvPosition, GeoNormal);
|
|
#else
|
|
FVertexFactoryInterpolantsVSToPS Interpolants;
|
|
float3 GeoNormal = 0;
|
|
CalcInterpolants((FRayCone)0, Attributes, Interpolants, GeoNormal);
|
|
|
|
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, SvPosition);
|
|
#endif
|
|
|
|
FPixelMaterialInputs PixelMaterialInputs;
|
|
|
|
const bool bIsFrontFace = HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE;
|
|
{
|
|
const float4 ScreenPosition = SvPositionToResolvedScreenPosition(SvPosition);
|
|
MaterialParameters.CameraVector = -WorldRayDirection();
|
|
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, TranslatedWorldPosition, TranslatedWorldPosition);
|
|
}
|
|
|
|
#if SUBSTRATE_ENABLED
|
|
|
|
float Coverage = 0;
|
|
float3 TransmittancePreCoverage = 0;
|
|
float3 BaseColorPostCoverage = 0;
|
|
float3 WorldNormal = 0;
|
|
float3 EmissiveLuminance = 0;
|
|
|
|
#if MATERIAL_IS_SUBSTRATE
|
|
FSubstrateData SubstrateData = PixelMaterialInputs.GetFrontSubstrateData();
|
|
FSubstratePixelHeader SubstratePixelHeader = MaterialParameters.GetFrontSubstrateHeader();
|
|
FSubstrateIntegrationSettings Settings = InitSubstrateIntegrationSettings(true /*bForceFullyRough*/, false /*SubstrateStruct.bRoughDiffuse*/, -1/*SubstrateStruct.PeelLayersAboveDepth*/, false/*SubstrateStruct.bRoughnessTracking*/);
|
|
|
|
const float3 SurfaceWorldNormal = GeoNormal;
|
|
FExportResult Export = SubstrateMaterialExportOut(
|
|
Settings,
|
|
SubstratePixelHeader,
|
|
SubstrateData,
|
|
SurfaceWorldNormal,
|
|
MaterialParameters.WorldPosition_CamRelative,
|
|
0.0f /*MobileShadingPathCurvature*/);
|
|
|
|
Coverage = Export.Coverage;
|
|
TransmittancePreCoverage = Export.TransmittancePreCoverage;
|
|
BaseColorPostCoverage = Export.BaseColorPostCoverage;
|
|
WorldNormal = Export.WorldNormal;
|
|
EmissiveLuminance = Export.EmissiveLuminance;
|
|
#endif // MATERIAL_IS_SUBSTRATE
|
|
|
|
|
|
#if MATERIALBLENDING_ANY_TRANSLUCENT
|
|
// SUBSTRATE_TODO: Make sure this is correct for all blend modes/glass cases
|
|
float3 TransparencyColor = saturate((1.0f - Coverage) + Coverage * TransmittancePreCoverage);
|
|
#else
|
|
float3 TransparencyColor = 0.0;
|
|
#endif
|
|
|
|
FPathTracingPayload Payload = (FPathTracingPayload)0;
|
|
|
|
Payload.BSDFOpacity = Coverage;
|
|
Payload.BaseColor = BaseColorPostCoverage;
|
|
Payload.SubsurfaceColor = 0; // SUBSTRATE_TODO: Figure out how to support old two-sided foliage approximation
|
|
Payload.ShadingModelID = any(BaseColorPostCoverage > 0.0) ? SHADINGMODELID_DEFAULT_LIT : SHADINGMODELID_UNLIT;
|
|
Payload.TransparencyColor = TransparencyColor;
|
|
|
|
const uint PrimitiveFlags = GetPrimitiveData(MaterialParameters.PrimitiveId).Flags;
|
|
Payload.PrimitiveLightingChannelMask = GetPrimitive_LightingChannelMask_FromFlags(PrimitiveFlags);
|
|
Payload.HitT = RayTCurrent();
|
|
if (HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE)
|
|
{
|
|
Payload.SetFrontFace();
|
|
}
|
|
|
|
#if MATERIAL_IS_SKY
|
|
if (!PackedPayload.IsCameraRay())
|
|
{
|
|
// avoid double counting what was captured by the skylight
|
|
// also avoid noise from hot spots (they can be properly
|
|
// importance sampled if a capturing skylight is added)
|
|
PackedPayload = PackPathTracingPayload(Payload);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
Payload.TranslatedWorldPos = DFFastToTranslatedWorld(MaterialParameters.AbsoluteWorldPosition, ResolvedView.PreViewTranslation);
|
|
float GeoNormalSign = MaterialParameters.TwoSidedSign;
|
|
#if !VF_SUPPORTS_RAYTRACING_PREPARE_MATERIAL_PIXEL_PARAMETERS
|
|
// Because the geometric normal is computed directly in world space
|
|
// it doesn't reflect the sign flip from the object transform, so apply it here
|
|
GeoNormalSign *= GetPrimitive_DeterminantSign(MaterialParameters.PrimitiveId);
|
|
#endif
|
|
Payload.WorldGeoNormal = GeoNormalSign * GeoNormal;
|
|
Payload.WorldNormal = WorldNormal;
|
|
|
|
Payload.Radiance = EmissiveLuminance;
|
|
|
|
#if MATERIAL_TWOSIDED
|
|
Payload.SetMaterialTwoSided();
|
|
#else
|
|
if (MaterialParameters.TwoSidedSign < 0)
|
|
{
|
|
// when viewing the surface from "inside", don't include emission
|
|
Payload.Radiance = 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
#else // SUBSTRATE_ENABLED
|
|
|
|
|
|
|
|
|
|
|
|
FPathTracingPayload Payload = (FPathTracingPayload)0;
|
|
|
|
/**
|
|
* Set common material attributes for both full and simplified materials
|
|
**/
|
|
Payload.ShadingModelID = GetMaterialShadingModel(PixelMaterialInputs);
|
|
|
|
#if MATERIALBLENDING_ALPHACOMPOSITE
|
|
Payload.BSDFOpacity = 1.0;
|
|
Payload.TransparencyColor = 1.0 - GetMaterialOpacity(PixelMaterialInputs);
|
|
#elif MATERIALBLENDING_ALPHAHOLDOUT
|
|
Payload.BSDFOpacity = GetMaterialOpacity(PixelMaterialInputs);
|
|
Payload.TransparencyColor = 1.0 - GetMaterialOpacity(PixelMaterialInputs);
|
|
Payload.SetHoldout();
|
|
HLSL_STATIC_ASSERT(MATERIAL_SHADINGMODEL_UNLIT == 1, "Alpha holdout blend mode requires unlit shading model");
|
|
Payload.ShadingModelID = SHADINGMODELID_UNLIT;
|
|
#elif MATERIALBLENDING_TRANSLUCENT
|
|
Payload.BSDFOpacity = GetMaterialOpacity(PixelMaterialInputs);
|
|
Payload.TransparencyColor = 1.0 - Payload.BSDFOpacity;
|
|
#elif MATERIALBLENDING_ADDITIVE
|
|
Payload.BSDFOpacity = GetMaterialOpacity(PixelMaterialInputs);
|
|
Payload.TransparencyColor = 1.0;
|
|
#elif MATERIALBLENDING_MODULATE
|
|
Payload.BSDFOpacity = 0.0;
|
|
Payload.TransparencyColor = GetMaterialEmissive(PixelMaterialInputs);
|
|
HLSL_STATIC_ASSERT(MATERIAL_SHADINGMODEL_UNLIT == 1 ||
|
|
MATERIAL_SHADINGMODEL_DEFAULT_LIT, "Modulate blend mode requires unlit shading model");
|
|
Payload.ShadingModelID = SHADINGMODELID_UNLIT;
|
|
#elif MATERIALBLENDING_MASKED && MATERIAL_DITHER_OPACITY_MASK
|
|
// dithering emulates real transparency, so switch to translucent
|
|
// NOTE: the raster path technically takes into account the opacity mask clip value, so the effective transparency should be:
|
|
// saturate(MaskRaw - ClipValue + 0.5)
|
|
// (See derivation in DitheredOpacityMaskToOpacity)
|
|
// However this behavior is surprising to most users and does not exactly match the rasterizer anyway due to how the realtime AA
|
|
// code performs blending.
|
|
// Since the goal of dithered opacity is to emulate ordinary transparency, just use the mask input as opacity directly and
|
|
// ignore the configured clip value.
|
|
Payload.BSDFOpacity = saturate(GetMaterialMaskInputRaw(PixelMaterialInputs));
|
|
Payload.TransparencyColor = 1.0 - Payload.BSDFOpacity;
|
|
#elif MATERIALBLENDING_SOLID || MATERIALBLENDING_MASKED
|
|
Payload.BSDFOpacity = 1.0;
|
|
Payload.TransparencyColor = 0.0;
|
|
#else
|
|
#error Unknown material blending mode
|
|
#endif
|
|
|
|
// fetch primitive flags only once
|
|
// TODO: would be nice to keep this inside MaterialParameters as it is also needed there as well
|
|
const uint PrimitiveFlags = GetPrimitiveData(MaterialParameters.PrimitiveId).Flags;
|
|
|
|
Payload.PrimitiveLightingChannelMask = GetPrimitive_LightingChannelMask_FromFlags(PrimitiveFlags);
|
|
|
|
Payload.HitT = RayTCurrent();
|
|
if (HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE)
|
|
{
|
|
Payload.SetFrontFace();
|
|
}
|
|
|
|
#if MATERIAL_IS_SKY
|
|
if (!PackedPayload.IsCameraRay())
|
|
{
|
|
// avoid double counting what was captured by the skylight
|
|
// also avoid noise from hot spots (they can be properly
|
|
// importance sampled if a capturing skylight is added)
|
|
PackedPayload = PackPathTracingPayload(Payload);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
// Store the results in local variables and reuse instead of calling the functions multiple times.
|
|
half3 BaseColor = GetMaterialBaseColor(PixelMaterialInputs);
|
|
half Metallic = GetMaterialMetallic(PixelMaterialInputs);
|
|
half Specular = GetMaterialSpecular(PixelMaterialInputs);
|
|
half Roughness = GetMaterialRoughness(PixelMaterialInputs);
|
|
float Ior = 0.0;
|
|
|
|
Payload.TranslatedWorldPos = DFFastToTranslatedWorld(MaterialParameters.AbsoluteWorldPosition, ResolvedView.PreViewTranslation);
|
|
float GeoNormalSign = MaterialParameters.TwoSidedSign;
|
|
#if !VF_SUPPORTS_RAYTRACING_PREPARE_MATERIAL_PIXEL_PARAMETERS
|
|
// Because the geometric normal is computed directly in world space
|
|
// it doesn't reflect the sign flip from the object transform, so apply it here
|
|
GeoNormalSign *= GetPrimitive_DeterminantSign(MaterialParameters.PrimitiveId);
|
|
#endif
|
|
Payload.WorldGeoNormal = GeoNormalSign * GeoNormal;
|
|
Payload.WorldNormal = MaterialParameters.WorldNormal;
|
|
#if !MATERIAL_TANGENTSPACENORMAL
|
|
// already flipped if the material was in tangent space, so add the flip if it wasn't
|
|
Payload.WorldNormal *= MaterialParameters.TwoSidedSign;
|
|
#endif
|
|
|
|
/**
|
|
* Set material attributes for simplified materials
|
|
**/
|
|
#if MATERIALBLENDING_TRANSLUCENT && !MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
|
|
// Force opacity to 0 so it is ignored for path hits and only evaluated in AHS as a modulation to throughput
|
|
Payload.BSDFOpacity = 0;
|
|
Payload.TransparencyColor = 1;
|
|
#else
|
|
Payload.BSDFOpacity = GetMaterialOpacity(PixelMaterialInputs);
|
|
Payload.TransparencyColor = 1 - Payload.BSDFOpacity;
|
|
#endif
|
|
|
|
// Anything unsupported will be forced to default lit
|
|
#if MATERIAL_SHADINGMODEL_TWOSIDED_FOLIAGE
|
|
if (Payload.ShadingModelID == SHADINGMODELID_TWOSIDED_FOLIAGE)
|
|
{
|
|
Payload.SubsurfaceColor = GetMaterialSubsurfaceData(PixelMaterialInputs).rgb;
|
|
}
|
|
else
|
|
#endif
|
|
#if MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
|
|
if (Payload.ShadingModelID == SHADINGMODELID_THIN_TRANSLUCENT)
|
|
{
|
|
const float3 Transmission = GetThinTranslucentMaterialOutput0(MaterialParameters);
|
|
const float3 V = WorldRayDirection();
|
|
const float3 N = normalize(MaterialParameters.WorldNormal);
|
|
const float VoN = abs(dot(V, N));
|
|
// simplified logic with no bending at the interface and no fresnel
|
|
Payload.TransparencyColor *= pow(Transmission, 1.0 / VoN);
|
|
}
|
|
else
|
|
#endif
|
|
#if MATERIAL_SHADINGMODEL_UNLIT
|
|
if (Payload.ShadingModelID == SHADINGMODELID_UNLIT)
|
|
{
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
// Redirect translucent blending mode to thin translucent
|
|
#if MATERIALBLENDING_TRANSLUCENT
|
|
Payload.ShadingModelID = SHADINGMODELID_THIN_TRANSLUCENT;
|
|
#else
|
|
Payload.ShadingModelID = SHADINGMODELID_DEFAULT_LIT;
|
|
#endif
|
|
}
|
|
Payload.Radiance = GetMaterialEmissive(PixelMaterialInputs);
|
|
Payload.Radiance *= Payload.BSDFOpacity; // premultiply
|
|
#if MATERIAL_TWOSIDED
|
|
Payload.SetMaterialTwoSided();
|
|
#else
|
|
if (MaterialParameters.TwoSidedSign < 0)
|
|
{
|
|
// when viewing the surface from "inside", don't include emission
|
|
Payload.Radiance = 0;
|
|
}
|
|
#endif
|
|
Payload.BaseColor = BaseColor;
|
|
|
|
|
|
|
|
#endif // SUBSTRATE_ENABLED
|
|
|
|
|
|
|
|
PackedPayload = PackPathTracingPayload(Payload);
|
|
}
|
|
|
|
#if USE_MATERIAL_ANY_HIT_SHADER
|
|
|
|
RAY_TRACING_ENTRY_ANY_HIT(GPULightmassMaterialAHS,
|
|
FPackedPathTracingPayload, PackedPayload,
|
|
FRayTracingIntersectionAttributes, Attributes)
|
|
{
|
|
#if MATERIALBLENDING_MODULATE || (MATERIALBLENDING_MASKED && MATERIAL_DITHER_OPACITY_MASK) || MATERIALBLENDING_ALPHACOMPOSITE || MATERIALBLENDING_TRANSLUCENT
|
|
if (!PackedPayload.IsVisibilityRay())
|
|
{
|
|
// not a shadow ray -- don't need to run the AHS logic
|
|
return;
|
|
}
|
|
if (PackedPayload.HitT == RayTCurrent())
|
|
{
|
|
// We just processed this exact hit, don't double-count it
|
|
IgnoreHit();
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
ResolvedView = ResolveView();
|
|
|
|
const float3 TranslatedWorldPosition = TranslatedWorldRayOrigin() + RayTCurrent() * WorldRayDirection();
|
|
const float4 SvPosition = TranslatedWorldPositionToSvPosition(TranslatedWorldPosition);
|
|
|
|
CurrentPayloadInputFlags = PackedPayload.GetFlags();
|
|
|
|
#if VF_SUPPORTS_RAYTRACING_PREPARE_MATERIAL_PIXEL_PARAMETERS
|
|
// this is a newer codepath that is both more flexible and allows for more direct calculation compared to the other codepath
|
|
// TODO: implement such a method for all vertex factories
|
|
float3 GeoNormal = 0;
|
|
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(TranslatedWorldRayOrigin(), WorldRayDirection(), RayTCurrent(), PrimitiveIndex(), Attributes, HitKind(), SvPosition, GeoNormal);
|
|
#else
|
|
FVertexFactoryInterpolantsVSToPS Interpolants;
|
|
float3 GeoNormal = 0;
|
|
CalcInterpolants((FRayCone)0, Attributes, Interpolants, GeoNormal);
|
|
|
|
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Interpolants, SvPosition);
|
|
#endif
|
|
|
|
FPixelMaterialInputs PixelMaterialInputs;
|
|
|
|
const bool bIsFrontFace = HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE;
|
|
|
|
{
|
|
const float4 ScreenPosition = SvPositionToResolvedScreenPosition(SvPosition);
|
|
|
|
MaterialParameters.CameraVector = -WorldRayDirection();
|
|
|
|
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, TranslatedWorldPosition, TranslatedWorldPosition);
|
|
}
|
|
|
|
#if MATERIALBLENDING_MASKED && !MATERIAL_DITHER_OPACITY_MASK
|
|
// Regardless of payload flags -- we always apply this
|
|
if (GetMaterialMask(PixelMaterialInputs) < 0)
|
|
{
|
|
IgnoreHit();
|
|
}
|
|
#endif
|
|
|
|
#if MATERIALBLENDING_MODULATE || (MATERIALBLENDING_MASKED && MATERIAL_DITHER_OPACITY_MASK) || MATERIALBLENDING_ALPHACOMPOSITE || MATERIALBLENDING_TRANSLUCENT
|
|
|
|
#if SUBSTRATE_ENABLED
|
|
|
|
float Coverage = 0;
|
|
float3 TransmittancePreCoverage = 0;
|
|
float3 BaseColorPostCoverage = 0;
|
|
float3 WorldNormal = 0;
|
|
float3 EmissiveLuminance = 0;
|
|
|
|
#if MATERIAL_IS_SUBSTRATE
|
|
FSubstrateData SubstrateData = PixelMaterialInputs.GetFrontSubstrateData();
|
|
FSubstratePixelHeader SubstratePixelHeader = MaterialParameters.GetFrontSubstrateHeader();
|
|
|
|
|
|
FSubstrateIntegrationSettings Settings = InitSubstrateIntegrationSettings(true /*bForceFullyRough*/, false /*SubstrateStruct.bRoughDiffuse*/, -1/*SubstrateStruct.PeelLayersAboveDepth*/, false/*SubstrateStruct.bRoughnessTracking*/);
|
|
|
|
const float3 SurfaceWorldNormal = GeoNormal;
|
|
FExportResult Export = SubstrateMaterialExportOut(
|
|
Settings,
|
|
SubstratePixelHeader,
|
|
SubstrateData,
|
|
SurfaceWorldNormal,
|
|
MaterialParameters.WorldPosition_CamRelative,
|
|
0.0f /*MobileShadingPathCurvature*/);
|
|
|
|
Coverage = Export.Coverage;
|
|
TransmittancePreCoverage = Export.TransmittancePreCoverage;
|
|
BaseColorPostCoverage = Export.BaseColorPostCoverage;
|
|
WorldNormal = Export.WorldNormal;
|
|
EmissiveLuminance = Export.EmissiveLuminance;
|
|
|
|
float3 Transparency = saturate((1.0f - Coverage) + Coverage * TransmittancePreCoverage);
|
|
#else
|
|
#error "Shouldn't need to compile AHS for non-substrate material"
|
|
#endif
|
|
|
|
#else // SUBSTRATE_ENABLED
|
|
|
|
// the following blend modes need to process shadows after having executed the material
|
|
#if MATERIALBLENDING_MODULATE
|
|
const float3 Transparency = GetMaterialEmissive(PixelMaterialInputs);
|
|
#elif MATERIALBLENDING_ALPHACOMPOSITE
|
|
const float Opacity = GetMaterialOpacity(PixelMaterialInputs);
|
|
const float Transparency = 1 - Opacity;
|
|
#elif MATERIALBLENDING_MASKED && MATERIAL_DITHER_OPACITY_MASK
|
|
// See MATERIAL_DITHER_OPACITY_MASK comment below
|
|
const float Opacity = saturate(GetMaterialMaskInputRaw(PixelMaterialInputs));
|
|
const float Transparency = 1 - Opacity;
|
|
#elif MATERIALBLENDING_TRANSLUCENT
|
|
const float Opacity = GetMaterialOpacity(PixelMaterialInputs);
|
|
// GPULM has backwards compatibility with some cpu lightmass tricks
|
|
float3 Transparency = 1 - Opacity;
|
|
uint ShadingModelID = GetMaterialShadingModel(PixelMaterialInputs);
|
|
|
|
#if MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
|
|
if (ShadingModelID == SHADINGMODELID_THIN_TRANSLUCENT)
|
|
{
|
|
float3 Transmission = GetThinTranslucentMaterialOutput0(MaterialParameters);
|
|
float Ior = 0.0;
|
|
float3 V = WorldRayDirection();
|
|
float3 N = normalize(MaterialParameters.WorldNormal);
|
|
float VoN = abs(dot(V, N));
|
|
// simplified logic with no bending at the interface and no fresnel
|
|
Transparency *= pow(Transmission, 1.0 / VoN);
|
|
}
|
|
else
|
|
#endif // MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
|
|
#if MATERIAL_SHADINGMODEL_DEFAULT_LIT
|
|
if (ShadingModelID == SHADINGMODELID_DEFAULT_LIT)
|
|
{
|
|
// CPU Lightmass translucency behavior emulation
|
|
Transparency = lerp(float3(1, 1, 1), GetMaterialBaseColor(PixelMaterialInputs), Opacity);
|
|
}
|
|
else
|
|
#endif// MATERIAL_SHADINGMODEL_DEFAULT_LIT
|
|
{
|
|
// base case for shadingmodel if/else
|
|
}
|
|
#else // MATERIALBLENDING_*
|
|
#error Unhandled blending mode!
|
|
#endif
|
|
|
|
#endif // !SUBSTRATE_ENABLED
|
|
|
|
// Update the ray throughput (it is packed simply into the payload since we don't need to carry any other information across hits)
|
|
float3 RayThroughput = PackedPayload.GetRayThroughput();
|
|
RayThroughput *= Transparency;
|
|
PackedPayload.SetRayThroughput(RayThroughput);
|
|
if (any(RayThroughput > 0))
|
|
{
|
|
// if there is energy left in the ray,
|
|
IgnoreHit();
|
|
}
|
|
#endif // MATERIALBLENDING_MODULATE || (MATERIALBLENDING_MASKED && MATERIAL_DITHER_OPACITY_MASK) || MATERIALBLENDING_ALPHACOMPOSITE || MATERIALBLENDING_TRANSLUCENT
|
|
}
|
|
|
|
#endif // USE_MATERIAL_ANY_HIT_SHADER
|