1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Image/BsPixelVolume.h"
7#include "Resources/BsGpuResourceData.h"
8#include "Reflection/BsIReflectable.h"
9
10namespace bs
11{
12 /** @addtogroup Resources
13 * @{
14 */
15
16 /** Pixel formats usable by images, textures and render surfaces. */
17 enum BS_SCRIPT_EXPORT(m:Rendering) PixelFormat
18 {
19 /** Unknown pixel format. */
20 PF_UNKNOWN BS_SCRIPT_EXPORT(ex:true) = 0,
21 /** 8-bit 1-channel pixel format, unsigned normalized. */
22 PF_R8 BS_SCRIPT_EXPORT(n:R8) = 1,
23 /** 8-bit 2-channel pixel format, unsigned normalized. */
24 PF_RG8 BS_SCRIPT_EXPORT(n:RG8) = 2,
25 /** 8-bit 3-channel pixel format, unsigned normalized. */
26 PF_RGB8 BS_SCRIPT_EXPORT(n:RGB8) = 3,
27 /** 8-bit 3-channel pixel format, unsigned normalized. */
28 PF_BGR8 BS_SCRIPT_EXPORT(n:BGR8) = 4,
29 /** 8-bit 4-channel pixel format, unsigned normalized. */
30 PF_BGRA8 BS_SCRIPT_EXPORT(n:BGRA8) = 7,
31 /** 8-bit 4-channel pixel format, unsigned normalized. */
32 PF_RGBA8 BS_SCRIPT_EXPORT(n:RGBA8) = 8,
33 /** DXT1/BC1 format containing opaque RGB or 1-bit alpha RGB. 4 bits per pixel. */
34 PF_BC1 BS_SCRIPT_EXPORT(n:BC1) = 13,
35 /** DXT3/BC2 format containing RGB with premultiplied alpha. 4 bits per pixel. */
36 PF_BC1a BS_SCRIPT_EXPORT(ex:true) = 14,
37 /** DXT3/BC2 format containing RGB with explicit alpha. 8 bits per pixel. */
38 PF_BC2 BS_SCRIPT_EXPORT(n:BC2) = 15,
39 /** DXT5/BC2 format containing RGB with explicit alpha. 8 bits per pixel. Better alpha gradients than BC2. */
40 PF_BC3 BS_SCRIPT_EXPORT(n:BC3) = 16,
41 /** One channel compressed format. 4 bits per pixel. */
42 PF_BC4 BS_SCRIPT_EXPORT(n:BC4) = 17,
43 /** Two channel compressed format. 8 bits per pixel. */
44 PF_BC5 BS_SCRIPT_EXPORT(n:BC5) = 18,
45 /** Format storing RGB in half (16-bit) floating point format usable for HDR. 8 bits per pixel. */
46 PF_BC6H BS_SCRIPT_EXPORT(n:BC6H) = 19,
47 /**
48 * Format storing RGB with optional alpha channel. Similar to BC1/BC2/BC3 formats but with higher quality and
49 * higher decompress overhead. 8 bits per pixel.
50 */
51 PF_BC7 BS_SCRIPT_EXPORT(n:BC7) = 20,
52 /** 16-bit 1-channel pixel format, signed float. */
53 PF_R16F BS_SCRIPT_EXPORT(n:R16F) = 21,
54 /** 16-bit 2-channel pixel format, signed float. */
55 PF_RG16F BS_SCRIPT_EXPORT(n:RG16F) = 22,
56 /** 16-bit 4-channel pixel format, signed float. */
57 PF_RGBA16F BS_SCRIPT_EXPORT(n:RGBA16F) = 24,
58 /** 32-bit 1-channel pixel format, signed float. */
59 PF_R32F BS_SCRIPT_EXPORT(n:R32F) = 25,
60 /** 32-bit 2-channel pixel format, signed float. */
61 PF_RG32F BS_SCRIPT_EXPORT(n:RG32F) = 26,
62 /** 32-bit 3-channel pixel format, signed float. */
63 PF_RGB32F BS_SCRIPT_EXPORT(n:RGB32F) = 27,
64 /** 32-bit 4-channel pixel format, signed float. */
65 PF_RGBA32F BS_SCRIPT_EXPORT(n:RGBA32F) = 28,
66 /** Depth stencil format, 32bit depth, 8bit stencil + 24 unused. Depth stored as signed float. */
67 PF_D32_S8X24 BS_SCRIPT_EXPORT(n:D32_S8X24) = 29,
68 /** Depth stencil fomrat, 24bit depth + 8bit stencil. Depth stored as unsigned normalized. */
69 PF_D24S8 BS_SCRIPT_EXPORT(n:D24S8) = 30,
70 /** Depth format, 32bits. Signed float. */
71 PF_D32 BS_SCRIPT_EXPORT(n:D32) = 31,
72 /** Depth format, 16bits. Unsigned normalized. */
73 PF_D16 BS_SCRIPT_EXPORT(n:D16) = 32,
74 /** Packed unsigned float format, 11 bits for red, 11 bits for green, 10 bits for blue. */
75 PF_RG11B10F BS_SCRIPT_EXPORT(ex:true) = 33,
76 /**
77 * Packed unsigned normalized format, 10 bits for red, 10 bits for green, 10 bits for blue, and two bits for alpha.
78 */
79 PF_RGB10A2 BS_SCRIPT_EXPORT(ex:true) = 34,
80 /** 8-bit 1-channel pixel format, signed integer. */
81 PF_R8I BS_SCRIPT_EXPORT(n:R8I) = 35,
82 /** 8-bit 2-channel pixel format, signed integer. */
83 PF_RG8I BS_SCRIPT_EXPORT(n:RG8I) = 36,
84 /** 8-bit 4-channel pixel format, signed integer. */
85 PF_RGBA8I BS_SCRIPT_EXPORT(n:RGBA8I) = 37,
86 /** 8-bit 1-channel pixel format, unsigned integer. */
87 PF_R8U BS_SCRIPT_EXPORT(n:R8U) = 38,
88 /** 8-bit 2-channel pixel format, unsigned integer. */
89 PF_RG8U BS_SCRIPT_EXPORT(n:RG8U) = 39,
90 /** 8-bit 4-channel pixel format, unsigned integer. */
91 PF_RGBA8U BS_SCRIPT_EXPORT(n:RGBA8U) = 40,
92 /** 8-bit 1-channel pixel format, signed normalized. */
93 PF_R8S BS_SCRIPT_EXPORT(n:R8S) = 41,
94 /** 8-bit 2-channel pixel format, signed normalized. */
95 PF_RG8S BS_SCRIPT_EXPORT(n:RG8S) = 42,
96 /** 8-bit 4-channel pixel format, signed normalized. */
97 PF_RGBA8S BS_SCRIPT_EXPORT(n:RGBA8S) = 43,
98 /** 16-bit 1-channel pixel format, signed integer. */
99 PF_R16I BS_SCRIPT_EXPORT(n:R16I) = 44,
100 /** 16-bit 2-channel pixel format, signed integer. */
101 PF_RG16I BS_SCRIPT_EXPORT(n:RG16I) = 45,
102 /** 16-bit 4-channel pixel format, signed integer. */
103 PF_RGBA16I BS_SCRIPT_EXPORT(n:RGBA16I) = 46,
104 /** 16-bit 1-channel pixel format, unsigned integer. */
105 PF_R16U BS_SCRIPT_EXPORT(n:R16U) = 47,
106 /** 16-bit 2-channel pixel format, unsigned integer. */
107 PF_RG16U BS_SCRIPT_EXPORT(n:RG16U) = 48,
108 /** 16-bit 4-channel pixel format, unsigned integer. */
109 PF_RGBA16U BS_SCRIPT_EXPORT(n:RGBA16U) = 49,
110 /** 32-bit 1-channel pixel format, signed integer. */
111 PF_R32I BS_SCRIPT_EXPORT(n:R32I) = 50,
112 /** 32-bit 2-channel pixel format, signed integer. */
113 PF_RG32I BS_SCRIPT_EXPORT(n:RG32I) = 51,
114 /** 32-bit 3-channel pixel format, signed integer. */
115 PF_RGB32I BS_SCRIPT_EXPORT(n:RGB32I) = 52,
116 /** 32-bit 4-channel pixel format, signed integer. */
117 PF_RGBA32I BS_SCRIPT_EXPORT(n:RGBA32I) = 53,
118 /** 32-bit 1-channel pixel format, unsigned integer. */
119 PF_R32U BS_SCRIPT_EXPORT(n:R32U) = 54,
120 /** 32-bit 2-channel pixel format, unsigned integer. */
121 PF_RG32U BS_SCRIPT_EXPORT(n:RG32U) = 55,
122 /** 32-bit 3-channel pixel format, unsigned integer. */
123 PF_RGB32U BS_SCRIPT_EXPORT(n:RGB32U) = 56,
124 /** 32-bit 4-channel pixel format, unsigned integer. */
125 PF_RGBA32U BS_SCRIPT_EXPORT(n:RGBA32U) = 57,
126 /** 16-bit 1-channel pixel format, signed normalized. */
127 PF_R16S BS_SCRIPT_EXPORT(n:R16S) = 58,
128 /** 16-bit 2-channel pixel format, signed normalized. */
129 PF_RG16S BS_SCRIPT_EXPORT(n:RG16S) = 59,
130 /** 16-bit 4-channel pixel format, signed normalized. */
131 PF_RGBA16S BS_SCRIPT_EXPORT(n:RGBA16S) = 60,
132 /** 16-bit 1-channel pixel format, unsigned normalized. */
133 PF_R16 BS_SCRIPT_EXPORT(n:R16) = 61,
134 /** 16-bit 2-channel pixel format, unsigned normalized. */
135 PF_RG16 BS_SCRIPT_EXPORT(n:RG16) = 62,
136 /** 16-bit 3-channel pixel format, unsigned normalized. */
137 PF_RGB16 BS_SCRIPT_EXPORT(n:RGB16) = 63,
138 /** 16-bit 4-channel pixel format, unsigned normalized. */
139 PF_RGBA16 BS_SCRIPT_EXPORT(n:RGBA16) = 64,
140 /** Number of pixel formats currently defined. */
141 PF_COUNT BS_SCRIPT_EXPORT(ex:true)
142 };
143
144 /** Flags defining some properties of pixel formats. */
145 enum PixelFormatFlags {
146 /** This format has an alpha channel. */
147 PFF_HASALPHA = 0x1,
148 /**
149 * This format is compressed. This invalidates the values in elemBytes, elemBits and the bit counts as these might
150 * not be fixed in a compressed format.
151 */
152 PFF_COMPRESSED = 0x2,
153 /** This is a floating point format. */
154 PFF_FLOAT = 0x4,
155 /** This is a depth format (for depth textures). */
156 PFF_DEPTH = 0x8,
157 /** This format stores data internally as integers. */
158 PFF_INTEGER = 0x10,
159 /** Format contains signed data. Absence of this flag implies unsigned data. */
160 PFF_SIGNED = 0x20,
161 /** Format contains normalized data. This will be [0, 1] for unsigned, and [-1,1] for signed formats. */
162 PFF_NORMALIZED = 0x40
163 };
164
165 /** Types used for individual components of a pixel. */
166 enum PixelComponentType
167 {
168 PCT_BYTE = 0, /**< 8-bit integer per component */
169 PCT_SHORT = 1, /**< 16-bit integer per component. */
170 PCT_INT = 2, /**< 32-bit integer per component. */
171 PCT_FLOAT16 = 3, /**< 16 bit float per component */
172 PCT_FLOAT32 = 4, /**< 32 bit float per component */
173 PCT_PACKED_R11G11B10 = 5, /**< 11 bits for first two components, 10 for third component. */
174 PCT_PACKED_R10G10B10A2 = 6, /**< 10 bits for first three components, 2 bits for last component */
175 PCT_COUNT /**< Number of pixel types */
176 };
177
178 /** Determines how are texture pixels filtered during sampling. */
179 enum TextureFilter
180 {
181 /** Pixel nearest to the sampled location is chosen. */
182 TF_NEAREST,
183 /** Four pixels nearest to the sampled location are interpolated to yield the sampled color. */
184 TF_BILINEAR
185 };
186
187 /** A list of cubemap faces. */
188 enum CubemapFace
189 {
190 CF_PositiveX,
191 CF_NegativeX,
192 CF_PositiveY,
193 CF_NegativeY,
194 CF_PositiveZ,
195 CF_NegativeZ
196 };
197
198 /**
199 * A buffer describing a volume (3D), image (2D) or line (1D) of pixels in memory. Pixels are stored as a succession
200 * of "depth" slices, each containing "height" rows of "width" pixels.
201 *
202 * @note
203 * If using the constructor instead of create() you must call GpuResourceData::allocateInternalBuffer or set the buffer
204 * in some other way before reading/writing from this object, as by the default there is no buffer allocated.
205 *
206 * @see GpuResourceData
207 */
208 class BS_CORE_EXPORT BS_SCRIPT_EXPORT() PixelData : public GpuResourceData
209 {
210 public:
211 PixelData() = default;
212
213 /**
214 * Constructs a new object with an internal buffer capable of holding "extents" volume of pixels, where each pixel
215 * is of the specified pixel format. Extent offsets are also stored, but are not used internally.
216 */
217 PixelData(const PixelVolume& extents, PixelFormat pixelFormat);
218
219 /**
220 * Constructs a new object with an internal buffer capable of holding volume of pixels described by provided width,
221 * height and depth, where each pixel is of the specified pixel format.
222 */
223 PixelData(UINT32 width, UINT32 height, UINT32 depth, PixelFormat pixelFormat);
224
225 PixelData(const PixelData& copy);
226 PixelData& operator=(const PixelData& rhs);
227
228 /**
229 * Returns the number of pixels that offsets one row from another. This can be "width", but doesn't have to be as
230 * some buffers require padding.
231 */
232 BS_SCRIPT_EXPORT(n:RawRowPitch,pr:getter)
233 UINT32 getRowPitch() const { return mRowPitch; }
234
235 /**
236 * Returns the number of pixels that offsets one depth slice from another. This can be "width * height", but
237 * doesn't have to be as some buffers require padding.
238 */
239 BS_SCRIPT_EXPORT(n:RawSlicePitch,pr:getter)
240 UINT32 getSlicePitch() const { return mSlicePitch; }
241
242 /**
243 * Sets the pitch (in pixels) that determines offset between rows of the pixel buffer. Call this before allocating
244 * the buffer.
245 */
246 void setRowPitch(UINT32 rowPitch) { mRowPitch = rowPitch; }
247
248 /**
249 * Sets the pitch (in pixels) that determines offset between depth slices of the pixel buffer. Call this before
250 * allocating the buffer.
251 */
252 void setSlicePitch(UINT32 slicePitch) { mSlicePitch = slicePitch; }
253
254 /**
255 * Returns the number of extra pixels in a row (non-zero only if rows are not consecutive (row pitch is larger
256 * than width)).
257 */
258 UINT32 getRowSkip() const { return mRowPitch - getWidth(); }
259
260 /**
261 * Returns the number of extra pixels in a depth slice (non-zero only if slices aren't consecutive (slice pitch is
262 * larger than width*height).
263 */
264 UINT32 getSliceSkip() const { return mSlicePitch - (getHeight() * mRowPitch); }
265
266 /** Returns the pixel format used by the internal buffer for storing the pixels. */
267 BS_SCRIPT_EXPORT(n:Format,pr:getter)
268 PixelFormat getFormat() const { return mFormat; }
269
270 /** Returns width of the buffer in pixels. */
271 UINT32 getWidth() const { return mExtents.getWidth(); }
272
273 /** Returns height of the buffer in pixels. */
274 UINT32 getHeight() const { return mExtents.getHeight(); }
275
276 /** Returns depth of the buffer in pixels. */
277 UINT32 getDepth() const { return mExtents.getDepth(); }
278
279 /**
280 * Returns left-most start of the pixel volume. This value is not used internally in any way. It is just passed
281 * through from the constructor.
282 */
283 UINT32 getLeft() const { return mExtents.left; }
284
285 /**
286 * Returns right-most end of the pixel volume. This value is not used internally in any way. It is just passed
287 * through from the constructor.
288 */
289 UINT32 getRight() const { return mExtents.right; }
290
291 /**
292 * Returns top-most start of the pixel volume. This value is not used internally in any way. It is just passed
293 * through from the constructor.
294 */
295 UINT32 getTop() const { return mExtents.top; }
296
297 /**
298 * Returns bottom-most end of the pixel volume. This value is not used internally in any way. It is just passed
299 * through from the constructor.
300 */
301 UINT32 getBottom() const { return mExtents.bottom; }
302
303 /**
304 * Returns front-most start of the pixel volume. This value is not used internally in any way. It is just passed
305 * through from the constructor.
306 */
307 UINT32 getFront() const { return mExtents.front; }
308
309 /**
310 * Returns back-most end of the pixel volume. This value is not used internally in any way. It is just passed
311 * through from the constructor.
312 */
313 UINT32 getBack() const { return mExtents.back; }
314
315 /** Returns extents of the pixel volume this object is capable of holding. */
316 BS_SCRIPT_EXPORT(n:Extents,pr:getter)
317 PixelVolume getExtents() const { return mExtents; }
318
319 /**
320 * Return whether this buffer is laid out consecutive in memory (meaning the pitches are equal to the dimensions).
321 */
322 BS_SCRIPT_EXPORT(n:RawIsConsecutive,pr:getter)
323 bool isConsecutive() const
324 {
325 return mRowPitch == getWidth() && mSlicePitch == getWidth()*getHeight();
326 }
327
328 /** Return the size (in bytes) this image would take if it was laid out consecutive in memory. */
329 UINT32 getConsecutiveSize() const;
330
331 /** Return the size (in bytes) of the buffer this image requires. */
332 BS_SCRIPT_EXPORT(n:RawSize,pr:getter)
333 UINT32 getSize() const;
334
335 /**
336 * Returns pixel data containing a sub-volume of this object. Returned data will not have its own buffer, but will
337 * instead point to this one. It is up to the caller to ensure this object outlives any sub-volume objects.
338 */
339 PixelData getSubVolume(const PixelVolume& volume) const;
340
341 /**
342 * Samples a color at the specified coordinates using a specific filter.
343 *
344 * @param[in] coords Coordinates to sample the color at. They start at top left corner (0, 0), and are in range
345 * [0, 1].
346 * @param[in] filter Filtering mode to use when sampling the color.
347 * @return Sampled color.
348 */
349 Color sampleColorAt(const Vector2& coords, TextureFilter filter = TF_BILINEAR) const;
350
351 /** Returns pixel color at the specified coordinates. */
352 Color getColorAt(UINT32 x, UINT32 y, UINT32 z = 0) const;
353
354 /** Sets the pixel color at the specified coordinates. */
355 void setColorAt(const Color& color, UINT32 x, UINT32 y, UINT32 z = 0);
356
357 /**
358 * Converts all the internal data into an array of colors. Array is mapped as such:
359 * arrayIdx = x + y * width + z * width * height.
360 */
361 Vector<Color> getColors() const;
362
363 /**
364 * Initializes the internal buffer with the provided set of colors. The array should be of width * height * depth
365 * size and mapped as such: arrayIdx = x + y * width + z * width * height.
366 */
367 void setColors(const Vector<Color>& colors);
368
369 /**
370 * Initializes the internal buffer with the provided set of colors. The array should be of
371 * width * height * depth size and mapped as such: arrayIdx = x + y * width + z * width * height.
372 */
373 void setColors(Color* colors, UINT32 numElements);
374
375 /** Initializes all the pixels with a single color. */
376 void setColors(const Color& color);
377
378 /**
379 * Interprets pixel data as depth information as retrieved from the GPU's depth buffer. Converts the device specific
380 * depth value to range [0, 1] and returns it.
381 */
382 float getDepthAt(UINT32 x, UINT32 y, UINT32 z = 0) const;
383
384 /**
385 * Converts all the internal data into an array of floats as if each individual pixel is retrieved with
386 * getDepthAt(). Array is mapped as such: arrayIdx = x + y * width + z * width * height.
387 */
388 Vector<float> getDepths() const;
389
390 /**
391 * Constructs a new object with an internal buffer capable of holding "extents" volume of pixels, where each pixel
392 * is of the specified pixel format. Extent offsets are also stored, but are not used internally.
393 */
394 static SPtr<PixelData> create(const PixelVolume& extents, PixelFormat pixelFormat);
395
396 /**
397 * Constructs a new object with an internal buffer capable of holding volume of pixels described by provided width,
398 * height and depth, where each pixel is of the specified pixel format.
399 */
400 static SPtr<PixelData> create(UINT32 width, UINT32 height, UINT32 depth, PixelFormat pixelFormat);
401
402 private:
403 /**
404 * Initializes the internal buffer with the provided set of colors. The array should be of width * height * depth
405 * size and mapped as such: arrayIdx = x + y * width + z * width * height.
406 *
407 * @note A generic method that is reused in other more specific setColors() calls.
408 */
409 template<class T>
410 void setColorsInternal(const T& colors, UINT32 numElements);
411
412 /** Returns the needed size of the internal buffer, in bytes. */
413 UINT32 getInternalBufferSize() const override;
414
415 private:
416 PixelVolume mExtents = PixelVolume(0, 0, 0, 0);
417 PixelFormat mFormat = PF_UNKNOWN;
418 UINT32 mRowPitch = 0;
419 UINT32 mSlicePitch = 0;
420
421 /************************************************************************/
422 /* SERIALIZATION */
423 /************************************************************************/
424 public:
425 friend class PixelDataRTTI;
426 static RTTITypeBase* getRTTIStatic();
427 RTTITypeBase* getRTTI() const override;
428 };
429
430 /** @} */
431}
432