34#include <memory_resource>
42 #define JPL_PROFILE(...)
45#ifndef JPL_PROFILE_SET_INT
46 #define JPL_PROFILE_SET_INT(Stat, Value)
49#ifndef JPL_PROFILE_SET_FLOAT
50 #define JPL_PROFILE_SET_FLOAT(Stat, Value)
54#ifndef JPL_HAS_FUNCTION
55#define JPL_HAS_FUNCTION(Type, MemberFunctionCallPrototype)\
56requires(Type Object){ Object.MemberFunctionCallPrototype; }
59#ifndef JPL_HAS_FUNCTION_R
60#define JPL_HAS_FUNCTION_R(Type, MemberFunctionCallPrototype, ReturnType)\
61requires(Type Object) { { Object.MemberFunctionCallPrototype } -> std::same_as<ReturnType>; }
82 template<
class IntersectionType>
93 template<
class IntersectionType>
96 std::pmr::vector<TraceNode<IntersectionType>>
Nodes;
100 template<
class IntersectionType>
103 std::pmr::vector<TracedPath<IntersectionType>>
Paths;
142 static constexpr std::size_t cMaxOrder = 16;
151 template<
class SceneType,
bool bPathHashCombine = true>
152 static void Trace(
const SceneType& sceneInterface,
153 const typename SceneType::Vec3& origin,
169 template<
class SceneType,
class SpecularPathCacheContainer>
170 static void ProcessTraces(SceneType& sceneInterface,
171 const typename SceneType::SourceData& sourceData,
173 std::span<const typename SceneType::ReceiverData> receiverData,
174 SpecularPathCacheContainer& caches);
189 template<
class SceneType,
class SpecularPathCacheContainer>
190 static void ProcessTraces(SceneType& sceneInterface,
191 const typename SceneType::SourceData& sourceData,
193 std::span<const typename SceneType::ReceiverData> receiverData,
195 SpecularPathCacheContainer& caches);
204 uint32 TotalNumImageSources;
206 template<
class IntersectionType>
211 struct ImageSourceBuffer
213 std::pmr::vector<Vec3> ImageSources;
214 std::pmr::vector<uint32> IndexTable;
216 static ImageSourceBuffer MakeFor(
const auto& subpathsList);
217 std::span<Vec3> GetImageSourcesFor(
const auto& subpath,
uint32 subpathIndex);
220 template<
class PathNodeType,
class Vec3>
221 struct alignas(JPL_CACHE_LINE_SIZE) NewSubpath
227 std::span<const PathNodeType> Subpath;
228 ETraceDirection Direction;
231 Vec3 LastImageSource;
237 template<
class SceneType,
class SpecularPathCacheContainer>
240 using Vec3 =
typename SceneType::Vec3;
241 using Intersection =
typename SceneType::Intersection;
242 using PathNodeType = TraceNode<Intersection>;
243 using NewSubpathEntry = NewSubpath<PathNodeType, Vec3>;
244 using SourceData =
typename SceneType::SourceData;
245 using ReceiverData =
typename SceneType::ReceiverData;
247 SceneType& mSceneInterface;
248 const SourceData& mSourceData;
249 TraceResults<Intersection>& mSourceTraces;
250 std::span<const ReceiverData> mReceiverData;
251 std::span<TraceResults<Intersection>> mReceiverTraces;
252 SpecularPathCacheContainer& mCaches;
255 ProcessRoutine(SceneType& sceneInterface,
256 const SourceData& sourceData,
257 TraceResults<Intersection>& sourceTraces,
258 std::span<const ReceiverData> receiverData,
259 std::span<TraceResults<Intersection>> receiverTraces,
260 SpecularPathCacheContainer& caches);
265 std::pair<uint32, uint32> GetSubpathCountAndMaxOrder()
const;
268 static TraceInfo PreprocessTraces(TraceResults<Intersection>& traces);
270 void CreateForwardSubpathsEntries(TraceResults<Intersection>& traces,
271 ScratchHashSetIdentity& uniqueCheckSet,
272 std::pmr::vector<NewSubpathEntry>& outNewSubpaths)
const;
274 void CreateBackwardSubpathsEntries(std::span<TraceResults<Intersection>> traces,
275 ScratchHashSetIdentity& uniqueCheckSet,
276 std::pmr::vector<NewSubpathEntry>& outNewSubpaths)
const;
279 template<ETraceDirection PathDirection>
280 void ConstructImageSources(
const Vec3& sourcePosition,
281 std::span<
const TraceNode<Intersection>> path,
282 std::span<Vec3> outImageSources)
const;
285 template<ETraceDirection TraceDirection>
286 void ConstructImageSources(
const Vec3& sourcePosition,
287 std::span<
const TraceNode<Intersection>> path,
288 ETraceDirection pathDirection,
289 std::span<Vec3> outImageSources)
const;
292 template<ETraceDirection PathDirection>
293 bool ValidatePathForListener(std::span<
const TraceNode<Intersection>> nodes,
294 std::span<const Vec3> imageSources,
295 const Vec3& listenerPosition)
const;
298 template<ETraceDirection TraceDirection>
299 bool ValidatePathForListener(std::span<
const TraceNode<Intersection>> nodes,
300 ETraceDirection pathDirection,
301 std::span<const Vec3> imageSources,
302 const Vec3& listenerPosition)
const;
305 void ValidateNewSubpaths(std::span<NewSubpathEntry> newSubpaths,
306 const Vec3 listenerPosition)
const;
310 void AccumulateMaterialAbsorption(std::span<
const TraceNode<Intersection>> surfaces,
311 EnergyBands& outEnergyLoss)
const;
314 void CacheValidatedSubpaths(std::span<NewSubpathEntry> validatedSubpaths,
315 uint32 maxPathOrderHint)
const;
335 template<
class SceneType,
bool bPathHashCombine>
336 inline void SpecularRayTracing::Trace(
const SceneType& sceneInterface,
337 const typename SceneType::Vec3& origin,
341 using Vec3 =
typename SceneType::Vec3;
342 using Ray =
typename SceneType::Ray;
343 using Intersection =
typename SceneType::Intersection;
347 for (PathType& path : outTraceResults.
Paths)
352 auto traceRay = [&](
int32 index)
354 PathType& path = outTraceResults.
Paths[index];
357 Ray ray(origin, Math::InternalUtils::RandDirection<Vec3>());
358 uint32 hash = Hash::cStartSeed;
364 if (not sceneInterface.Intersect(ray, parameters.
MaxRayLength, hit))
369 if constexpr (bPathHashCombine)
376 hash = sceneInterface.GetHash(hit);
380 path.Nodes.push_back({ .Hit = hit, .Hash = hash });
383 static constexpr float offset = 0.001f;
386 ray.Origin = sceneInterface.GetPosition(hit) + sceneInterface.GetNormal(hit) * offset;
387 ray.Direction = Math::SpecularReflection(ray.Direction, sceneInterface.GetNormal(hit));
397 sceneInterface.PreTrace();
414 sceneInterface.PostTrace();
421 inline auto SpecularRayTracing::ImageSourceBuffer<Vec3>::MakeFor(
const auto& subpathsList) -> ImageSourceBuffer<Vec3>
424 const uint32 totalNumberOfImageSources = Algo::Accumulate(subpathsList, 0u, [](
uint32 acc,
const auto& entry)
426 return acc +
static_cast<uint32>(entry.Subpath.size() + 1);
429 ImageSourceBuffer ISBuffer
435 for (uint32 entryIndex = 0, ISCacheOffset = 0; entryIndex < subpathsList.size(); ++entryIndex)
437 ISBuffer.IndexTable[entryIndex] = ISCacheOffset;
438 const auto& entry = subpathsList[entryIndex];
439 const uint32 imageSourcePathSize = entry.Subpath.size() + 1;
440 ISCacheOffset += imageSourcePathSize;
442 JPL_ASSERT(ISCacheOffset <= ISBuffer.ImageSources.size());
449 inline std::span<Vec3> SpecularRayTracing::ImageSourceBuffer<Vec3>::GetImageSourcesFor(
const auto& subpath, uint32 subpathIndex)
451 const uint32 imageSourcePathSize = subpath.size() + 1;
452 return std::span<Vec3>(&ImageSources[IndexTable[subpathIndex]], imageSourcePathSize);
456 template<
class IntersectionType>
457 auto SpecularRayTracing::TraceInfo::Parse(
const TraceResults<IntersectionType>& traces) -> TraceInfo
460 info.PathCount =
static_cast<uint32>(traces.Paths.size());
462 info.TotalNumSubpaths = 0;
464 for (
const auto& path : traces.Paths)
466 info.TotalNumSubpaths += path.Nodes.size();
467 info.MaxOrder = std::max(info.MaxOrder,
static_cast<uint32>(path.Nodes.size()));
470 info.TotalNumImageSources = info.TotalNumSubpaths + info.PathCount;
476 template<
class SceneType,
class SpecularPathCacheContainer>
477 inline void SpecularRayTracing::ProcessTraces(SceneType& sceneInterface,
478 const typename SceneType::SourceData& sourceData,
480 std::span<const typename SceneType::ReceiverData> receiverData,
481 SpecularPathCacheContainer& caches)
485 ProcessRoutine(sceneInterface, sourceData, traces, receiverData, {}, caches).Process();
489 template<
class SceneType,
class SpecularPathCacheContainer>
490 inline void SpecularRayTracing::ProcessTraces(SceneType& sceneInterface,
491 const typename SceneType::SourceData& sourceData,
493 std::span<const typename SceneType::ReceiverData> receiverData,
495 SpecularPathCacheContainer& caches)
499 ProcessRoutine(sceneInterface, sourceData, sourceTraces, receiverData, receiverTraces, caches).Process();
503 template<
class SceneType,
class SpecularPathCacheContainer>
504 inline SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::
505 ProcessRoutine(SceneType& sceneInterface,
506 const SourceData& sourceData,
508 std::span<const ReceiverData> receiverData,
510 SpecularPathCacheContainer& caches)
511 : mSceneInterface(sceneInterface)
512 , mSourceData(sourceData)
513 , mSourceTraces(sourceTraces)
514 , mReceiverData(receiverData)
515 , mReceiverTraces(receiverTraces)
521 template<
class SceneType,
class SpecularPathCacheContainer>
522 inline void SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::Process()
545 if (
not mReceiverTraces.empty())
552 ValidateNewSubpaths(std::span(
newSubpaths), mSourceData.Position);
558 template<
class SceneType,
class SpecularPathCacheContainer>
559 inline std::pair<uint32, uint32> SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::GetSubpathCountAndMaxOrder()
const
581 template<
class SceneType,
class SpecularPathCacheContainer>
582 inline auto SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::PreprocessTraces(TraceResults<Intersection>&
traces) -> TraceInfo
585 std::erase_if(
traces.Paths, [](
const auto&
path) { return path.Nodes.empty(); });
613 return TraceInfo::Parse(
traces);
617 template<
class SceneType,
class SpecularPathCacheContainer>
618 inline void SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::CreateForwardSubpathsEntries(TraceResults<Intersection>&
traces,
668 template<
class SceneType,
class SpecularPathCacheContainer>
669 inline void SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::CreateBackwardSubpathsEntries(std::span<TraceResults<Intersection>>
traces,
683 return hash.GetCurrent();
730 template<
class SceneType,
class SpecularPathCacheContainer>
731 template<ETraceDirection PathDirection>
732 inline void SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::ConstructImageSources(
const Vec3&
sourcePosition,
746 mSceneInterface.GetNormal(
node.Hit),
747 mSceneInterface.GetPosition(
node.Hit));
756 mSceneInterface.GetNormal(
node.Hit),
757 mSceneInterface.GetPosition(
node.Hit));
762 template<
class SceneType,
class SpecularPathCacheContainer>
763 template<ETraceDirection TraceDirection>
764 inline void SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::ConstructImageSources(
const Vec3&
sourcePosition,
781 template<
class SceneType,
class SpecularPathCacheContainer>
782 template<ETraceDirection PathDirection>
783 inline bool SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::ValidatePathForListener(std::span<
const TraceNode<Intersection>>
nodes,
803 static constexpr float offset = 0.001f;
805 R = mSceneInterface.GetPosition(
hit) + mSceneInterface.GetNormal(
hit) *
offset;
815 not mSceneInterface.IsSameSurface(
hit,
nodes[
i - 1].Hit))
819 static constexpr float offset = 0.001f;
821 R = mSceneInterface.GetPosition(
hit) + mSceneInterface.GetNormal(
hit) *
offset;
830 template<
class SceneType,
class SpecularPathCacheContainer>
831 template<ETraceDirection TraceDirection>
832 inline bool SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::ValidatePathForListener(std::span<
const TraceNode<Intersection>>
nodes,
849 template<
class SceneType,
class SpecularPathCacheContainer>
850 inline void SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::ValidateNewSubpaths(std::span<NewSubpathEntry>
newSubpaths,
864 const ReceiverData&
receiver = mReceiverData[
entry.ReceiverIdx];
882 AccumulateMaterialAbsorption(
entry.Subpath,
entry.EnergyLoss);
890 mSceneInterface.PreTrace();
907 mSceneInterface.PostTrace();
911 template<
class SceneType,
class SpecularPathCacheContainer>
912 inline void SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::AccumulateMaterialAbsorption(std::span<
const TraceNode<Intersection>>
surfaces,
926 template<
class SceneType,
class SpecularPathCacheContainer>
927 inline void SpecularRayTracing::ProcessRoutine<SceneType, SpecularPathCacheContainer>::CacheValidatedSubpaths(std::span<NewSubpathEntry>
validatedSubpaths,
#define JPL_ASSERT(inExpression,...)
Main assert macro, usage: JPL_ASSERT(condition, message) or JPL_ASSERT(condition)
Definition ErrorReporting.h:76
#define JPL_PROFILE_SET_INT(Stat, Value)
Definition SpecularRayTracing.h:46
#define JPL_PROFILE(...)
Definition SpecularRayTracing.h:42
#define JPL_HAS_FUNCTION(Type, MemberFunctionCallPrototype)
Definition SpecularRayTracing.h:55
#define JPL_PROFILE_SET_FLOAT(Stat, Value)
Definition SpecularRayTracing.h:50
static JPL_INLINE std::size_t GetRequiredMemorySize(uint32 expectedCount)
Definition ScratchHashSet.h:105
A very experimental specular path cache.
Definition SpecularPathCache.h:49
Definition SpecularRayTracing.h:140
Definition AcousticMaterial.h:36
ScratchHashSet32< uint32, std::identity > ScratchHashSetIdentity
Definition ScratchHashSet.h:38
std::int32_t int32
Definition Core.h:316
JPL_INLINE constexpr void HashCombine32(uint32_t &seed, uint32_t id32)
Definition Hash.h:42
ETraceDirection
Definition SpecularRayTracing.h:68
JPL_INLINE simd reverse(const simd &vec) noexcept
Reverse the order of the lanes.
Definition SIMD.h:2005
std::uint32_t uint32
Definition Core.h:311
std::pmr::memory_resource * GetDefaultMemoryResource() noexcept
Definition Memory.h:42
simd EnergyBands
Definition FrequencyBands.h:36
JPL_INLINE simd min(const simd &a, const simd &b) noexcept
Element-wise min.
Definition SIMD.h:1813
Definition ChannelMap.h:268
A very experimental specular path definition.
Definition SpecularPath.h:40
Node of a traced paths.
Definition SpecularRayTracing.h:84
uint32 Hash
Definition SpecularRayTracing.h:89
IntersectionType Hit
Definition SpecularRayTracing.h:86
Generic parameters used in different kinds of traces.
Definition SpecularRayTracing.h:75
uint32 MaxTraceOrder
Definition SpecularRayTracing.h:77
float MaxRayLength
Definition SpecularRayTracing.h:78
uint32 NumPrimaryRays
Definition SpecularRayTracing.h:76
Result of tracing paths.
Definition SpecularRayTracing.h:102
std::pmr::vector< TracedPath< IntersectionType > > Paths
Definition SpecularRayTracing.h:103
Sequence of traced path intersections.
Definition SpecularRayTracing.h:95
std::pmr::vector< TraceNode< IntersectionType > > Nodes
Definition SpecularRayTracing.h:96
Minimal 4-wide 32-bit float vector implementation for SIMD.
Definition SIMD.h:60
static constexpr std::size_t size() noexcept
Get number of element of the vector.
Definition SIMD.h:97