11#ifndef _NBL_HLSL_RWMC_CASCADE_ACCUMULATOR_INCLUDED_
22#define _NBL_HLSL_RWMC_CASCADE_ACCUMULATOR_INCLUDED_
3- #include "nbl/builtin/hlsl/cpp_compat.hlsl"
3+ #include <nbl/builtin/hlsl/cpp_compat.hlsl>
4+ #include <nbl/builtin/hlsl/cpp_compat/promote.hlsl>
45#include <nbl/builtin/hlsl/vector_utils/vector_traits.hlsl>
56#include <nbl/builtin/hlsl/colorspace/encodeCIEXYZ.hlsl>
7+ #include <nbl/builtin/hlsl/rwmc/SplattingParameters.hlsl>
68
79namespace nbl
810{
@@ -11,86 +13,82 @@ namespace hlsl
1113namespace rwmc
1214{
1315
14- struct CascadeSettings
16+ template<typename CascadeLayerType, uint32_t CascadeCount NBL_PRIMARY_REQUIRES (concepts::Vector<CascadeLayerType>)
17+ struct CascadeAccumulator
1518{
16- uint32_t size;
17- uint32_t start;
18- uint32_t base ;
19- } ;
19+ struct CascadeEntry
20+ {
21+ uint32_t cascadeSampleCounter[CascadeCount] ;
22+ CascadeLayerType data[CascadeCount] ;
2023
21- template<typename CascadeLayerType, uint32_t CascadeSize>
22- struct CascadeEntry
23- {
24- CascadeLayerType data[CascadeSize];
25- };
24+ void addSampleIntoCascadeEntry (CascadeLayerType _sample, uint32_t lowerCascadeIndex, float lowerCascadeLevelWeight, float higherCascadeLevelWeight, uint32_t sampleCount)
25+ {
26+ const float reciprocalSampleCount = 1.0f / float (sampleCount);
27+
28+ uint32_t lowerCascadeSampleCount = cascadeSampleCounter[lowerCascadeIndex];
29+ data[lowerCascadeIndex] += (_sample * lowerCascadeLevelWeight - (sampleCount - lowerCascadeSampleCount) * data[lowerCascadeIndex]) * reciprocalSampleCount;
30+ cascadeSampleCounter[lowerCascadeIndex] = sampleCount;
31+
32+ uint32_t higherCascadeIndex = lowerCascadeIndex + 1u;
33+ if (higherCascadeIndex < CascadeCount)
34+ {
35+ uint32_t higherCascadeSampleCount = cascadeSampleCounter[higherCascadeIndex];
36+ data[higherCascadeIndex] += (_sample * higherCascadeLevelWeight - (sampleCount - higherCascadeSampleCount) * data[higherCascadeIndex]) * reciprocalSampleCount;
37+ cascadeSampleCounter[higherCascadeIndex] = sampleCount;
38+ }
39+ }
40+ };
2641
27- template<typename CascadeLayerType, uint32_t CascadeSize>
28- struct CascadeAccumulator
29- {
30- using output_storage_type = CascadeEntry<CascadeLayerType, CascadeSize>;
31- using initialization_data = CascadeSettings;
42+ using cascade_layer_scalar_type = typename vector_traits<CascadeLayerType>::scalar_type;
43+ using this_t = CascadeAccumulator<CascadeLayerType, CascadeCount>;
44+ using output_storage_type = CascadeEntry;
45+ using initialization_data = SplattingParameters;
3246 output_storage_type accumulation;
33- uint32_t cascadeSampleCounter[CascadeSize];
34- CascadeSettings cascadeSettings ;
47+
48+ SplattingParameters splattingParameters ;
3549
36- void initialize ( in CascadeSettings settings)
50+ static this_t create ( NBL_CONST_REF_ARG (SplattingParameters) settings)
3751 {
38- for (int i = 0 ; i < CascadeSize; ++i)
52+ this_t retval;
53+ for (int i = 0 ; i < CascadeCount; ++i)
3954 {
40- accumulation.data[i] = ( CascadeLayerType) 0.0f ;
41- cascadeSampleCounter[i] = 0u;
55+ retval. accumulation.data[i] = promote< CascadeLayerType, float32_t>( 0.0f ) ;
56+ retval.accumulation. cascadeSampleCounter[i] = 0u;
4257 }
58+ retval.splattingParameters = settings;
4359
44- cascadeSettings.size = settings.size;
45- cascadeSettings.start = settings.start;
46- cascadeSettings.base = settings.base;
60+ return retval;
4761 }
48-
49- typename vector_traits<CascadeLayerType>::scalar_type getLuma (NBL_CONST_REF_ARG (CascadeLayerType) col)
62+
63+ cascade_layer_scalar_type getLuma (NBL_CONST_REF_ARG (CascadeLayerType) col)
5064 {
5165 return hlsl::dot<CascadeLayerType>(hlsl::transpose (colorspace::scRGBtoXYZ)[1 ], col);
5266 }
5367
5468 // most of this code is stolen from https://cg.ivd.kit.edu/publications/2018/rwmc/tool/split.cpp
55- void addSample (uint32_t sampleIndex, float32_t3 sample )
69+ void addSample (uint32_t sampleCount, CascadeLayerType _sample )
5670 {
57- float lowerScale = cascadeSettings.start;
58- float upperScale = lowerScale * cascadeSettings.base;
59-
60- const float luma = getLuma (sample );
61-
62- uint32_t lowerCascadeIndex = 0u;
63- while (!(luma < upperScale) && lowerCascadeIndex < cascadeSettings.size - 2 )
64- {
65- lowerScale = upperScale;
66- upperScale *= cascadeSettings.base;
67- ++lowerCascadeIndex;
68- }
69-
70- float lowerCascadeLevelWeight;
71- float higherCascadeLevelWeight;
72-
73- if (luma <= lowerScale)
74- lowerCascadeLevelWeight = 1.0f ;
75- else if (luma < upperScale)
76- lowerCascadeLevelWeight = max (0.0f , (lowerScale / luma - lowerScale / upperScale) / (1.0f - lowerScale / upperScale));
77- else // Inf, NaN ...
78- lowerCascadeLevelWeight = 0.0f ;
79-
80- if (luma < upperScale)
81- higherCascadeLevelWeight = max (0.0f , 1.0f - lowerCascadeLevelWeight);
82- else
83- higherCascadeLevelWeight = upperScale / luma;
84-
85- uint32_t higherCascadeIndex = lowerCascadeIndex + 1u;
86-
87- const uint32_t sampleCount = sampleIndex + 1u;
88- const float reciprocalSampleCount = 1.0f / float (sampleCount);
89- accumulation.data[lowerCascadeIndex] += (sample * lowerCascadeLevelWeight - (sampleCount - (cascadeSampleCounter[lowerCascadeIndex])) * accumulation.data[lowerCascadeIndex]) * reciprocalSampleCount;
90- accumulation.data[higherCascadeIndex] += (sample * higherCascadeLevelWeight - (sampleCount - (cascadeSampleCounter[higherCascadeIndex])) * accumulation.data[higherCascadeIndex]) * reciprocalSampleCount;
91- cascadeSampleCounter[lowerCascadeIndex] = sampleCount;
92- cascadeSampleCounter[higherCascadeIndex] = sampleCount;
71+ const cascade_layer_scalar_type log2Start = splattingParameters.log2Start;
72+ const cascade_layer_scalar_type log2Base = splattingParameters.log2Base;
73+ const cascade_layer_scalar_type luma = getLuma (_sample);
74+ const cascade_layer_scalar_type log2Luma = log2<cascade_layer_scalar_type>(luma);
75+ const cascade_layer_scalar_type cascade = log2Luma * 1.f / log2Base - log2Start / log2Base;
76+ const cascade_layer_scalar_type clampedCascade = clamp (cascade, 0 , CascadeCount - 1 );
77+ // c<=0 -> 0, c>=Count-1 -> Count-1
78+ uint32_t lowerCascadeIndex = floor<cascade_layer_scalar_type>(cascade);
79+ // 0 whenever clamped or `cascade` is integer (when `clampedCascade` is integer)
80+ cascade_layer_scalar_type higherCascadeWeight = clampedCascade - floor<cascade_layer_scalar_type>(clampedCascade);
81+ // never 0 thanks to magic of `1-fract(x)`
82+ cascade_layer_scalar_type lowerCascadeWeight = cascade_layer_scalar_type (1 ) - higherCascadeWeight;
83+
84+ // handle super bright sample case
85+ if (cascade > CascadeCount - 1 )
86+ lowerCascadeWeight = exp2 (log2Start + log2Base * (CascadeCount - 1 ) - log2Luma);
87+
88+ accumulation.addSampleIntoCascadeEntry (_sample, lowerCascadeIndex, lowerCascadeWeight, higherCascadeWeight, sampleCount);
9389 }
90+
91+
9492};
9593
9694}
0 commit comments