143 lines
5.0 KiB
HLSL
143 lines
5.0 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
RayTracingHitGroupCommon.ush: common header used in all hit group shaders
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#ifndef RAYTRACINGHITGROUPCOMMON_USH_INCLUDED
|
|
#define RAYTRACINGHITGROUPCOMMON_USH_INCLUDED // Workarround for UE-66460
|
|
|
|
#include "/Engine/Private/RayTracing/RayTracingCommon.ush"
|
|
#include "/Engine/Shared/RayTracingBuiltInResources.h"
|
|
|
|
#if NANITE_RAY_TRACING
|
|
#include "../Nanite/NaniteRayTrace.ush"
|
|
#endif
|
|
|
|
uint3 LoadIndices16Bit(ByteAddressBuffer SourceBuffer, uint OffsetInBytes)
|
|
{
|
|
uint3 Result;
|
|
|
|
// ByteAddressBuffer loads must be aligned to DWORD boundary.
|
|
// We can load 2 DWORDs (4 SHORTs) at a time and extract 3 SHORTs (first 3 or second 3).
|
|
uint AlignedOffsetInBytes = OffsetInBytes & (~3);
|
|
const uint2 PackedIndices = SourceBuffer.Load2(AlignedOffsetInBytes);
|
|
|
|
if (AlignedOffsetInBytes == OffsetInBytes)
|
|
{
|
|
// Extract first 3 SHORTs from 2 DWORDs
|
|
Result[0] = PackedIndices[0] & 0xffff;
|
|
Result[1] = PackedIndices[0] >> 16;
|
|
Result[2] = PackedIndices[1] & 0xffff;
|
|
}
|
|
else
|
|
{
|
|
// Extract second 3 SHORTs from 2 DWORDs
|
|
Result[0] = PackedIndices[0] >> 16;
|
|
Result[1] = PackedIndices[1] & 0xffff;
|
|
Result[2] = PackedIndices[1] >> 16;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
uint3 LoadIndices32Bit(ByteAddressBuffer SourceBuffer, uint OffsetInBytes)
|
|
{
|
|
return SourceBuffer.Load3(OffsetInBytes);
|
|
}
|
|
|
|
float3 LoadVertexPositionFloat3(ByteAddressBuffer SourceBuffer, uint BaseOffsetInBytes, uint Index, uint StrideInBytes)
|
|
{
|
|
uint OffsetInBytes = BaseOffsetInBytes + Index * StrideInBytes;
|
|
return asfloat(SourceBuffer.Load3(OffsetInBytes));
|
|
}
|
|
|
|
// Explicitly declare "system" resources that will be available to all hit group shaders.
|
|
|
|
FTriangleBaseAttributes LoadTriangleBaseAttributes(
|
|
ByteAddressBuffer IndexBuffer, uint IndexBufferOffsetInBytes, uint IndexBufferStride,
|
|
ByteAddressBuffer VertexBuffer, uint VertexBufferOffsetInBytes, uint VertexBufferStride,
|
|
uint PrimitiveId)
|
|
{
|
|
FTriangleBaseAttributes Result = (FTriangleBaseAttributes)0;
|
|
|
|
// Fetch vertex indices and positions, then compute local space normal and transform it to world space
|
|
|
|
const uint BaseIndex = PrimitiveId * 3;
|
|
|
|
if (IndexBufferStride == 0)
|
|
{
|
|
// Non-indexed geometry (implicit triangle list indices)
|
|
Result.Indices = uint3(BaseIndex, BaseIndex + 1, BaseIndex + 2);
|
|
}
|
|
else if (IndexBufferStride == 2)
|
|
{
|
|
Result.Indices = LoadIndices16Bit(IndexBuffer, IndexBufferOffsetInBytes + BaseIndex * IndexBufferStride);
|
|
}
|
|
else
|
|
{
|
|
Result.Indices = LoadIndices32Bit(IndexBuffer, IndexBufferOffsetInBytes + BaseIndex * IndexBufferStride);
|
|
}
|
|
|
|
// Fetch vertex positions (in local space)
|
|
// #dxr_todo: UE-72160 handle various vertex formats, for now only supporting float3
|
|
Result.LocalPositions[0] = LoadVertexPositionFloat3(VertexBuffer, VertexBufferOffsetInBytes, Result.Indices[0], VertexBufferStride);
|
|
Result.LocalPositions[1] = LoadVertexPositionFloat3(VertexBuffer, VertexBufferOffsetInBytes, Result.Indices[1], VertexBufferStride);
|
|
Result.LocalPositions[2] = LoadVertexPositionFloat3(VertexBuffer, VertexBufferOffsetInBytes, Result.Indices[2], VertexBufferStride);
|
|
|
|
return Result;
|
|
}
|
|
|
|
FTriangleBaseAttributes LoadTriangleBaseAttributes(uint PrimitiveId)
|
|
{
|
|
uint IndexBufferOffsetInBytes = HitGroupSystemRootConstants.IndexBufferOffsetInBytes;
|
|
uint IndexBufferStride = HitGroupSystemRootConstants.GetIndexStride();
|
|
uint VertexStride = HitGroupSystemRootConstants.GetVertexStride();
|
|
uint VertexBufferOffsetInBytes = 0; // Base offset is already applied when the buffer is bound to the hit group
|
|
return LoadTriangleBaseAttributes(HitGroupSystemIndexBuffer, IndexBufferOffsetInBytes, IndexBufferStride, HitGroupSystemVertexBuffer, VertexBufferOffsetInBytes, VertexStride, PrimitiveId);
|
|
}
|
|
|
|
uint GetInstanceUserData()
|
|
{
|
|
return InstanceID();
|
|
}
|
|
|
|
uint GetHitGroupUserData()
|
|
{
|
|
return HitGroupSystemRootConstants.UserData;
|
|
}
|
|
|
|
float3 GetGeometryNormalFromTriangleBaseAttributes(uint PrimitiveIndex)
|
|
{
|
|
float3 LocalEdges[2];
|
|
|
|
#if NANITE_RAY_TRACING
|
|
const uint GPUSceneInstanceIndex = GetInstanceUserData();
|
|
|
|
FInstanceSceneData InstanceData = GetInstanceSceneData(GPUSceneInstanceIndex);
|
|
FPrimitiveSceneData PrimitiveData = GetPrimitiveData(InstanceData.PrimitiveId);
|
|
|
|
if (PrimitiveData.NaniteRayTracingDataOffset != uint(-1))
|
|
{
|
|
GetNaniteTriangleEdges(PrimitiveData.NaniteRayTracingDataOffset + HitGroupSystemRootConstants.FirstPrimitive + PrimitiveIndex, LocalEdges[0], LocalEdges[1]);
|
|
}
|
|
else
|
|
#endif // NANITE_RAY_TRACING
|
|
{
|
|
FTriangleBaseAttributes Tri = LoadTriangleBaseAttributes(PrimitiveIndex);
|
|
|
|
LocalEdges[0] = Tri.LocalPositions[1] - Tri.LocalPositions[0];
|
|
LocalEdges[1] = Tri.LocalPositions[2] - Tri.LocalPositions[0];
|
|
}
|
|
|
|
float3x3 InverseTranspose3x3 = (float3x3)WorldToObject4x3();
|
|
float3 LocalNormal = cross(LocalEdges[1], LocalEdges[0]);
|
|
float3 WorldNormal = normalize(mul(InverseTranspose3x3, LocalNormal));
|
|
|
|
return WorldNormal;
|
|
}
|
|
|
|
#endif // RAYTRACINGHITGROUPCOMMON_USH_INCLUDED // Workarround for UE-66460
|