69 lines
3.2 KiB
HLSL
69 lines
3.2 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
NiagaraDistanceFieldQueries.ush
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
float GetDistanceToMeshDistanceField(int DFIndex, const FDFVector3 LWCWorldPosition, const float MaxDistance)
|
|
{
|
|
FDFObjectData DFObjectData = LoadDFObjectData(DFIndex);
|
|
|
|
// DistanceToNearestSurfaceForObject()
|
|
const float3 VolumePosition = DFMultiplyDemote(LWCWorldPosition, DFObjectData.WorldToVolume);
|
|
const float3 ClampedVolumePosition = clamp(VolumePosition, -DFObjectData.VolumePositionExtent, DFObjectData.VolumePositionExtent);
|
|
|
|
const float3 ToBox = (abs(ClampedVolumePosition) - DFObjectData.VolumePositionExtent) * DFObjectData.VolumeToWorldScale;
|
|
const float DistanceToBoxOutside = length(max(0.0f, ToBox));
|
|
const float DistanceToBoxInside = min(0.0f, max3(ToBox.x, ToBox.y, ToBox.z));
|
|
const float DistanceToBox = DistanceToBoxOutside + DistanceToBoxInside;
|
|
|
|
float DistanceToOccluder = MaxDistance;
|
|
|
|
BRANCH
|
|
if (DistanceToBox < MaxDistance)
|
|
{
|
|
uint NumMips = LoadDFAssetData(DFObjectData.AssetIndex, 0).NumMips;
|
|
FDFAssetData DFAssetData = LoadDFAssetData(DFObjectData.AssetIndex, NumMips - 1);
|
|
|
|
DistanceToOccluder = DistanceToMeshSurfaceStandalone(ClampedVolumePosition, DFObjectData) * DFObjectData.VolumeScale;
|
|
}
|
|
|
|
return DistanceToOccluder;
|
|
}
|
|
|
|
void ComputeClosestPointMeshDistanceField(int DFIndex, const FDFVector3 LWCWorldPosition, const float GridSampledDistance, out float3 OutClosestPosition, out float3 OutClosestNormal, out float MaxEncodedDistance, out bool bNormalIsValid)
|
|
{
|
|
FDFObjectData DFObjectData = LoadDFObjectData(DFIndex);
|
|
|
|
const float3 VolumePosition = DFMultiplyDemote(LWCWorldPosition, DFObjectData.WorldToVolume);
|
|
const float3 ClampedVolumePosition = clamp(VolumePosition, -DFObjectData.VolumePositionExtent, DFObjectData.VolumePositionExtent);
|
|
|
|
uint NumMips = LoadDFAssetData(DFObjectData.AssetIndex, 0).NumMips;
|
|
FDFAssetData DFAssetData = LoadDFAssetData(DFObjectData.AssetIndex, NumMips - 1);
|
|
|
|
MaxEncodedDistance = (DFAssetData.DistanceFieldToVolumeScaleBias.x + DFAssetData.DistanceFieldToVolumeScaleBias.y) * DFObjectData.VolumeScale;
|
|
|
|
float3 VolumeGradient = CalculateMeshSDFGradient(ClampedVolumePosition, DFAssetData);
|
|
float VolumeGradientLength = length(VolumeGradient);
|
|
float3 VolumeNormal = VolumeGradientLength > 0.0f ? VolumeGradient / VolumeGradientLength : 0;
|
|
|
|
// Transform by transposed inverse to handle non-uniform scaling
|
|
float4x4 WorldToVolume = DFHackToFloat(DFObjectData.WorldToVolume);
|
|
float3 WorldGradient = mul(VolumeNormal, transpose((float3x3)WorldToVolume));
|
|
float WorldGradientLength = length(WorldGradient);
|
|
|
|
// @note: we should include checking if we are within the range of max encoded distance, but this breaks backwards compatibility
|
|
bNormalIsValid = WorldGradientLength > 0.0f && (MaxEncodedDistance - abs(GridSampledDistance) > 1e-8);
|
|
|
|
// output
|
|
if (bNormalIsValid)
|
|
{
|
|
OutClosestNormal = WorldGradient / WorldGradientLength;
|
|
|
|
const float3 WorldClampedPosition = DFDemote(DFMultiply(ClampedVolumePosition, DFObjectData.VolumeToWorld));
|
|
OutClosestPosition = WorldClampedPosition - OutClosestNormal * GridSampledDistance;
|
|
}
|
|
}
|