Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
sample.h
Go to the documentation of this file.
1#pragma once
2
10#include "Math/math.h"
11
12#include <Common/assertion.h>
13#include <Common/primitive_type.h>
14
15#include <cstddef>
16#include <array>
17#include <utility>
18#include <type_traits>
19#include <climits>
20
21namespace ph::math
22{
23
24template<typename To, typename From, std::size_t N>
25inline std::array<To, N> sample_cast(const std::array<From, N>& sample)
26{
27 std::array<To, N> casted;
28 for(std::size_t i = 0; i < N; ++i)
29 {
30 casted[i] = static_cast<To>(sample[i]);
31 }
32 return casted;
33}
34
40template<typename T>
41inline bool pick(const T pickProbability, const T sample)
42{
43 PH_ASSERT_IN_RANGE_INCLUSIVE(sample, T(0), T(1));
44 PH_ASSERT_IN_RANGE_INCLUSIVE(pickProbability, T(0), T(1));
45
46 return sample < pickProbability;
47}
48
49template<typename T>
50inline bool reused_pick(const T pickProbability, T& sample)
51{
52 // Note that <sample> is already on the correct scale if picking probability
53 // is 0 or 1, hence the ternary conditionals; division by 0 is also handled.
54
55 if(pick(pickProbability, sample))
56 {
57 sample = pickProbability != T(0) ?
58 math::clamp(sample / pickProbability, T(0), T(1)) : sample;
59
60 return true;
61 }
62 else
63 {
64 // The denominator should never be 0
65 PH_ASSERT_NE(pickProbability != T(1) ? (T(1) - pickProbability) : T(1), T(0));
66
67 sample = pickProbability != T(1) ?
68 math::clamp((sample - pickProbability) / (T(1) - pickProbability), T(0), T(1)) : sample;
69
70 return false;
71 }
72}
73
79template<typename T, typename BitsType>
80inline T bits_to_sample(const BitsType& bits)
81{
82 static_assert(CHAR_BIT == 8);
83
84 T normalizer = static_cast<T>(0);
85 if constexpr(std::is_same_v<BitsType, uint8>)
86 {
87 normalizer = static_cast<T>(0x1p-8);
88 }
89 else if constexpr(std::is_same_v<BitsType, uint16>)
90 {
91 normalizer = static_cast<T>(0x1p-16);
92 }
93 else if constexpr(std::is_same_v<BitsType, uint32>)
94 {
95 normalizer = static_cast<T>(0x1p-32);
96 }
97 else if constexpr(std::is_same_v<BitsType, uint64>)
98 {
99 normalizer = static_cast<T>(0x1p-64);
100 }
101 else
102 {
103 PH_STATIC_ASSERT_DEPENDENT_FALSE(T,
104 "No existing implementation can do `BitsType` -> sample type `T`.");
105 }
106
107 const T sample = bits * normalizer;
108 PH_ASSERT_IN_RANGE_INCLUSIVE(sample, static_cast<T>(0.0), static_cast<T>(1.0));
109 return sample;
110}
111
112}// end namespace ph::math
Miscellaneous math utilities.
Math functions and utilities.
Definition TransformInfo.h:10
T bits_to_sample(const BitsType &bits)
Converts input bits to a sample. For standard unsigned integral types, this is effectively normalizin...
Definition sample.h:80
bool pick(const T pickProbability, const T sample)
Randomly pick a branch with some probability.
Definition sample.h:41
std::array< To, N > sample_cast(const std::array< From, N > &sample)
Definition sample.h:25
bool reused_pick(const T pickProbability, T &sample)
Definition sample.h:50
T clamp(const T value, const T lowerBound, const T upperBound)
Clamps a value to [lowerBound, upperBound]. None of value, lowerBound and upperBound can be NaN,...
Definition math.h:77