111 lines
4.0 KiB
HLSL
111 lines
4.0 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#ifndef VOXEL_TRAVERSAL_DEBUG
|
|
#define VOXEL_TRAVERSAL_DEBUG 0
|
|
#endif
|
|
#define VOXEL_TRAVERSAL_TYPE VOXEL_TRAVERSAL_LINEAR_MIPMAP
|
|
//#define VOXEL_TRAVERSAL_TYPE VOXEL_TRAVERSAL_LINEAR
|
|
|
|
#include "../HairStrands/HairStrandsVoxelPageCommon.ush"
|
|
#include "../HairStrands/HairStrandsVoxelPageTraversal.ush"
|
|
|
|
|
|
// RayOrigin is in translated world space
|
|
float InternalTraverseHair(uint2 PixelCoord, float3 RayOrigin, float3 RayDirection, float InMinT, float InOcclusionThreshold, float3 VoxelRandom, float RayRandom)
|
|
{
|
|
float HitT = InMinT;
|
|
|
|
// Depth bias
|
|
// Origin is shifted voxels away towards the light + a constant bias of the size of the voxel
|
|
const float3 NormalizedDepthBias = (RayRandom * RayDirection + VoxelRandom);
|
|
|
|
#if VOXEL_TRAVERSAL_DEBUG
|
|
const bool bDebugEnabled = PixelCoord.x == GetCursorPos().x && PixelCoord.y == GetCursorPos().y;
|
|
#else
|
|
const bool bDebugEnabled = false;
|
|
#endif
|
|
|
|
FHairTraversalResult Result = InitHairTraversalResult();
|
|
|
|
const float DistanceThreshold = 1000.0f;
|
|
const float CoverageThreshold = 0.995f; // When Coverage is high, we do not trace shadow on opaque since hair/fur is covering the background.
|
|
|
|
FVirtualVoxelCommonDesc CommonDesc;
|
|
CommonDesc.PageCountResolution = VirtualVoxel.PageCountResolution;
|
|
CommonDesc.PageTextureResolution = VirtualVoxel.PageTextureResolution;
|
|
CommonDesc.PageResolution = VirtualVoxel.PageResolution;
|
|
CommonDesc.PageResolutionLog2 = VirtualVoxel.PageResolutionLog2;
|
|
|
|
const float3 P0 = RayOrigin;
|
|
const float3 P1 = RayOrigin + RayDirection * (HitT>=0 ? min(HitT, DistanceThreshold) : DistanceThreshold);
|
|
|
|
for (uint MacroGroupId = 0; MacroGroupId < VirtualVoxel.NodeDescCount; ++MacroGroupId)
|
|
{
|
|
const FPackedVirtualVoxelNodeDesc PackedNode = VirtualVoxel.NodeDescBuffer[MacroGroupId];
|
|
const FVirtualVoxelNodeDesc NodeDesc = UnpackVoxelNode(PackedNode, VirtualVoxel.PageResolution);
|
|
|
|
FHairTraversalSettings TraversalSettings = InitHairTraversalSettings();
|
|
TraversalSettings.DensityScale = VirtualVoxel.DensityScale_Raytracing;
|
|
TraversalSettings.CountThreshold = InOcclusionThreshold;
|
|
TraversalSettings.DistanceThreshold = DistanceThreshold;
|
|
TraversalSettings.bDebugEnabled = bDebugEnabled;
|
|
TraversalSettings.SteppingScale = VirtualVoxel.SteppingScale_Raytracing;
|
|
TraversalSettings.Random = VoxelRandom;
|
|
TraversalSettings.bUseOpaqueVisibility = false;
|
|
TraversalSettings.bCastShadow = true;
|
|
|
|
const float3 DepthBias = NormalizedDepthBias * NodeDesc.VoxelWorldSize;
|
|
Result = ComputeHairCountVirtualVoxel(
|
|
P0 + DepthBias,
|
|
P1 + DepthBias,
|
|
CommonDesc,
|
|
NodeDesc,
|
|
VirtualVoxel.PageIndexBuffer,
|
|
VirtualVoxel.PageTexture,
|
|
TraversalSettings);
|
|
|
|
if (Result.HitT >= 0)
|
|
{
|
|
const float WorldHitT = Result.HitT;
|
|
HitT = HitT >= 0 ? min(HitT, WorldHitT) : WorldHitT;
|
|
}
|
|
}
|
|
|
|
return HitT;
|
|
}
|
|
|
|
float TraverseHair(uint2 PixelCoord, float3 RayOrigin, float3 RayDirection, float InMinT, float InOcclusionThreshold)
|
|
{
|
|
float HitT = InMinT;
|
|
|
|
const float3 VoxelRandom = 0.5f;
|
|
const float RayRandom = 1;
|
|
return InternalTraverseHair(PixelCoord, RayOrigin, RayDirection, InMinT, InOcclusionThreshold, VoxelRandom, RayRandom);
|
|
}
|
|
|
|
float TraverseHair(uint2 PixelCoord, inout RandomSequence RandSequence, float3 RayOrigin, float3 RayDirection, float InMinT, float InOcclusionThreshold)
|
|
{
|
|
float HitT = InMinT;
|
|
|
|
// 0: No jitter, 1:Time-Random jitter, 2:Time-Constant jitter
|
|
float3 VoxelRandom = 0.5f;
|
|
float RayRandom = 1.0f;
|
|
if (VirtualVoxel.JitterMode == 1)
|
|
{
|
|
const float4 Rnd = RandomSequence_GenerateSample4D(RandSequence);
|
|
VoxelRandom = Rnd.xyz;
|
|
RayRandom = Rnd.w;
|
|
}
|
|
else
|
|
{
|
|
const uint2 Seed0 = Rand3DPCG16(int3(PixelCoord, 0)).xy;
|
|
const uint2 Seed1 = Rand3DPCG16(int3(PixelCoord + 17, 0)).xy;
|
|
const float4 Rnd = float4(Hammersley16(0, 8, Seed0), Hammersley16(0, 8, Seed1));
|
|
VoxelRandom = Rnd.xyz;
|
|
RayRandom = Rnd.w;
|
|
}
|
|
|
|
return InternalTraverseHair(PixelCoord, RayOrigin, RayDirection, InMinT, InOcclusionThreshold, VoxelRandom, RayRandom);
|
|
} |