Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
PixelBuffer2D.h
Go to the documentation of this file.
1#pragma once
2
3#include "Math/TVector2.h"
4
5#include <Common/assertion.h>
6#include <Common/primitive_type.h>
7
8#include <cstddef>
9#include <array>
10#include <limits>
11#include <stdexcept>
12#include <format>
13#include <algorithm>
14
15namespace ph
16{
17
18namespace pixel_buffer
19{
20
21inline constexpr uint8 MAX_PIXEL_ELEMENTS = 4;
22
25template<typename T>
26class TPixel final
27{
28public:
29 TPixel();
30
34 template<std::size_t N>
35 TPixel(const std::array<T, N>& values);
36
40 template<std::size_t N>
41 TPixel(const std::array<T, N>& valueBuffer, std::size_t numUsedValues);
42
43 template<typename U>
44 explicit TPixel(const TPixel<U>& other);
45
46 template<std::size_t N>
47 std::array<T, N> getValues() const;
48
52 std::array<T, MAX_PIXEL_ELEMENTS> getAllValues() const;
53
54 std::size_t numValues() const;
55 T operator [] (std::size_t index) const;
56
57private:
58 using ValueArrayType = std::array<T, MAX_PIXEL_ELEMENTS>;
59
60 ValueArrayType m_valueBuffer;
61 std::size_t m_numValues;
62};
63
64// In-header Implementations:
65
66template<typename T>
68 m_valueBuffer(),// init all values to 0
69 m_numValues (0)
70{}
71
72template<typename T>
73template<std::size_t N>
74inline TPixel<T>::TPixel(const std::array<T, N>& values) :
75 TPixel(values, N)
76{}
77
78template<typename T>
79template<std::size_t N>
80inline TPixel<T>::TPixel(const std::array<T, N>& valueBuffer, const std::size_t numUsedValues) :
81 TPixel()
82{
83 constexpr auto MIN_BUFFER_SIZE = std::min(N, std::tuple_size_v<ValueArrayType>);
84
85 if(numUsedValues > MIN_BUFFER_SIZE)
86 {
87 throw std::out_of_range(std::format(
88 "Buffer of size {} cannot hold {} input values.", MIN_BUFFER_SIZE, numUsedValues));
89 }
90
91 for(std::size_t i = 0; i < numUsedValues; ++i)
92 {
93 m_valueBuffer[i] = valueBuffer[i];
94 }
95
96 m_numValues = numUsedValues;
97}
98
99template<typename T>
100template<typename U>
101inline TPixel<T>::TPixel(const TPixel<U>& other) :
102 TPixel()
103{
104 for(std::size_t i = 0; i < other.numValues(); ++i)
105 {
106 m_valueBuffer[i] = static_cast<T>(other[i]);
107 }
108
109 m_numValues = other.numValues();
110}
111
112template<typename T>
113template<std::size_t N>
114inline std::array<T, N> TPixel<T>::getValues() const
115{
116 if(N > m_numValues)
117 {
118 throw std::out_of_range(std::format(
119 "Attepmting to get {} input values from an internal buffer of size {}.", N, m_numValues));
120 }
121
122 std::array<T, N> values;
123 for(std::size_t i = 0; i < N; ++i)
124 {
125 values[i] = m_valueBuffer[i];
126 }
127 return values;
128}
129
130template<typename T>
131inline std::array<T, MAX_PIXEL_ELEMENTS> TPixel<T>::getAllValues() const
132{
133 return m_valueBuffer;
134}
135
136template<typename T>
137inline std::size_t TPixel<T>::numValues() const
138{
139 return m_numValues;
140}
141
142template<typename T>
143inline T TPixel<T>::operator [] (const std::size_t index) const
144{
145 PH_ASSERT_LT(index, m_numValues);
146
147 return m_valueBuffer[index];
148}
149
150}// end namespace pixel_buffer
151
153{
154public:
157 std::size_t numPixelElements);
158
161 std::size_t numPixelElements,
162 std::size_t numMipLevels);
163
164 inline virtual ~PixelBuffer2D() = default;
165
166 virtual pixel_buffer::TPixel<float64> fetchPixel(math::TVector2<uint32> xy, std::size_t mipLevel) const = 0;
167
168 virtual std::size_t estimateMemoryUsageBytes() const;
169
171 std::size_t numPixelElements() const;
172 bool hasMipmap() const;
173 std::size_t numMipLevels() const;
174
175private:
177 uint8 m_numPixelElements;
178 uint8 m_numMipLevels;
179};
180
181// In-header Implementations:
182
184 const math::TVector2<uint32> size,
185 const std::size_t numPixelElements) :
186
188 size,
189 numPixelElements,
190 1)
191{}
192
194 const math::TVector2<uint32> size,
195 const std::size_t numPixelElements,
196 const std::size_t numMipLevels) :
197
198 m_size (size),
199 m_numPixelElements(static_cast<uint8>(numPixelElements)),
200 m_numMipLevels (static_cast<uint8>(numMipLevels))
201{
202 // No 0-sized buffer and unspecified pixel type
203 PH_ASSERT_GT(size.product(), 0);
204 PH_ASSERT_GT(numPixelElements, 0);
205 PH_ASSERT_GE(m_numMipLevels, 1);
206
207 // Check for possible value overflow
209 PH_ASSERT_LE(numMipLevels, std::numeric_limits<decltype(m_numMipLevels)>::max());
210}
211
213{
214 return m_size;
215}
216
217inline bool PixelBuffer2D::hasMipmap() const
218{
219 return m_numMipLevels > 1;
220}
221
222inline std::size_t PixelBuffer2D::numPixelElements() const
223{
224 return m_numPixelElements;
225}
226
227inline std::size_t PixelBuffer2D::numMipLevels() const
228{
229 return m_numMipLevels;
230}
231
233{
234 return sizeof(PixelBuffer2D);
235}
236
237}// end namespace ph
Definition PixelBuffer2D.h:153
virtual std::size_t estimateMemoryUsageBytes() const
Definition PixelBuffer2D.h:232
std::size_t numMipLevels() const
Definition PixelBuffer2D.h:227
math::TVector2< uint32 > getSize() const
Definition PixelBuffer2D.h:212
virtual ~PixelBuffer2D()=default
PixelBuffer2D(math::TVector2< uint32 > size, std::size_t numPixelElements)
Definition PixelBuffer2D.h:183
std::size_t numPixelElements() const
Definition PixelBuffer2D.h:222
virtual pixel_buffer::TPixel< float64 > fetchPixel(math::TVector2< uint32 > xy, std::size_t mipLevel) const =0
bool hasMipmap() const
Definition PixelBuffer2D.h:217
Represents a 2-D vector.
Definition TVector2.h:19
T product() const
Definition TArithmeticArrayBase.ipp:358
Represent a pixel from pixel buffer.
Definition PixelBuffer2D.h:27
TPixel()
Definition PixelBuffer2D.h:67
T operator[](std::size_t index) const
Definition PixelBuffer2D.h:143
std::size_t numValues() const
Definition PixelBuffer2D.h:137
std::array< T, MAX_PIXEL_ELEMENTS > getAllValues() const
Definition PixelBuffer2D.h:131
std::array< T, N > getValues() const
Definition PixelBuffer2D.h:114
constexpr uint8 MAX_PIXEL_ELEMENTS
Definition PixelBuffer2D.h:21
The root for all renderer implementations.
Definition EEngineProject.h:6