• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Razakhel / RaZ / 16746843640

05 Aug 2025 09:54AM UTC coverage: 74.293% (-0.3%) from 74.615%
16746843640

push

github

Razakhel
[Render/Renderer] Added sampler functions

- Renamed activateTexture() to setActiveTexture(), and TextureParam* enums to TextureParameter*

- Added several noexcept specifications

- Removed single dots at the end of message strings

66 of 170 new or added lines in 28 files covered. (38.82%)

8326 of 11207 relevant lines covered (74.29%)

1745.43 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.22
/src/RaZ/Render/Texture.cpp
1
#include "RaZ/Data/Color.hpp"
2
#include "RaZ/Data/Image.hpp"
3
#if defined(USE_OPENGL_ES)
4
#include "RaZ/Render/Framebuffer.hpp"
5
#endif
6
#include "RaZ/Render/Renderer.hpp"
7
#include "RaZ/Render/Texture.hpp"
8
#include "RaZ/Utils/Logger.hpp"
9

10
#include "tracy/Tracy.hpp"
11

12
namespace Raz {
13

14
namespace {
15

16
inline TextureFormat recoverFormat(TextureColorspace colorspace) {
341✔
17
  switch (colorspace) {
341✔
18
    case TextureColorspace::INVALID:
×
19
    default:
20
      break;
×
21

22
    case TextureColorspace::GRAY:
72✔
23
      return TextureFormat::RED;
72✔
24

25
    case TextureColorspace::RG:
9✔
26
      return TextureFormat::RG;
9✔
27

28
    case TextureColorspace::RGB:
211✔
29
    case TextureColorspace::SRGB:
30
      return TextureFormat::RGB;
211✔
31

32
    case TextureColorspace::RGBA:
34✔
33
    case TextureColorspace::SRGBA:
34
      return TextureFormat::RGBA;
34✔
35

36
    case TextureColorspace::DEPTH:
15✔
37
      return TextureFormat::DEPTH;
15✔
38
  }
39

NEW
40
  throw std::invalid_argument("[Texture] Invalid texture colorspace");
×
41
}
42

43
inline TextureInternalFormat recoverInternalFormat(TextureColorspace colorspace, TextureDataType dataType) {
280✔
44
  switch (colorspace) {
280✔
45
    case TextureColorspace::INVALID:
×
46
    default:
47
      break;
×
48

49
    case TextureColorspace::GRAY:
55✔
50
      return (dataType == TextureDataType::BYTE    ? TextureInternalFormat::R8
57✔
51
           : (dataType == TextureDataType::FLOAT16 ? TextureInternalFormat::R16F
2✔
52
                                                   : TextureInternalFormat::R32F));
55✔
53

54
    case TextureColorspace::RG:
9✔
55
      return (dataType == TextureDataType::BYTE    ? TextureInternalFormat::RG8
11✔
56
           : (dataType == TextureDataType::FLOAT16 ? TextureInternalFormat::RG16F
2✔
57
                                                   : TextureInternalFormat::RG32F));
9✔
58

59
    case TextureColorspace::RGB:
150✔
60
      return (dataType == TextureDataType::BYTE    ? TextureInternalFormat::RGB8
240✔
61
           : (dataType == TextureDataType::FLOAT16 ? TextureInternalFormat::RGB16F
90✔
62
                                                   : TextureInternalFormat::RGB32F));
150✔
63

64
    case TextureColorspace::RGBA:
11✔
65
      return (dataType == TextureDataType::BYTE    ? TextureInternalFormat::RGBA8
13✔
66
           : (dataType == TextureDataType::FLOAT16 ? TextureInternalFormat::RGBA16F
2✔
67
                                                   : TextureInternalFormat::RGBA32F));
11✔
68

69
    // Floating-point sRGB(A) textures aren't treated as sRGB, which is necessarily an integer format; they're therefore interpreted as floating-point RGB(A)
70

71
    case TextureColorspace::SRGB:
25✔
72
      return (dataType == TextureDataType::BYTE    ? TextureInternalFormat::SRGB8
27✔
73
           : (dataType == TextureDataType::FLOAT16 ? TextureInternalFormat::RGB16F
2✔
74
                                                   : TextureInternalFormat::RGB32F));
25✔
75

76
    case TextureColorspace::SRGBA:
15✔
77
      return (dataType == TextureDataType::BYTE    ? TextureInternalFormat::SRGBA8
21✔
78
           : (dataType == TextureDataType::FLOAT16 ? TextureInternalFormat::RGBA16F
6✔
79
                                                   : TextureInternalFormat::RGBA32F));
15✔
80

81
    case TextureColorspace::DEPTH:
15✔
82
      return TextureInternalFormat::DEPTH32F;
15✔
83
  }
84

85
  throw std::invalid_argument("[Texture] Invalid texture colorspace to recover the internal format from");
×
86
}
87

88
constexpr TextureParameterValue recoverParam(TextureFilter filter) {
902✔
89
  switch (filter) {
902✔
90
    case TextureFilter::NEAREST: return TextureParameterValue::NEAREST;
44✔
91
    case TextureFilter::LINEAR:  return TextureParameterValue::LINEAR;
858✔
NEW
92
    default:                     break;
×
93
  }
94

NEW
95
  throw std::invalid_argument("[Texture] Invalid texture filter");
×
96
}
97

98
constexpr TextureParameterValue recoverParam(TextureFilter filter, TextureFilter mipmapFilter) {
64✔
99
  switch (filter) {
64✔
100
    case TextureFilter::NEAREST:
10✔
101
      return (mipmapFilter == TextureFilter::NEAREST ? TextureParameterValue::NEAREST_MIPMAP_NEAREST : TextureParameterValue::NEAREST_MIPMAP_LINEAR);
10✔
102

103
    case TextureFilter::LINEAR:
54✔
104
      return (mipmapFilter == TextureFilter::NEAREST ? TextureParameterValue::LINEAR_MIPMAP_NEAREST : TextureParameterValue::LINEAR_MIPMAP_LINEAR);
54✔
105

NEW
106
    default:
×
NEW
107
      break;
×
108
  }
109

NEW
110
  throw std::invalid_argument("[Texture] Invalid texture filter");
×
111
}
112

113
constexpr TextureParameterValue recoverParam(TextureWrapping wrapping) {
457✔
114
  switch (wrapping) {
457✔
115
    case TextureWrapping::REPEAT: return TextureParameterValue::REPEAT;
69✔
116
    case TextureWrapping::CLAMP:  return TextureParameterValue::CLAMP_TO_EDGE;
388✔
NEW
117
    default:                      break;
×
118
  }
119

NEW
120
  throw std::invalid_argument("[Texture] Invalid texture wrapping");
×
121
}
122

123
constexpr TextureColorspace recoverColorspace(ImageColorspace imgColorspace, bool shouldUseSrgb) {
71✔
124
  auto texColorspace = static_cast<TextureColorspace>(imgColorspace);
71✔
125

126
  if (shouldUseSrgb) {
71✔
127
    if (texColorspace == TextureColorspace::RGB)
33✔
128
      texColorspace = TextureColorspace::SRGB;
20✔
129
    else if (texColorspace == TextureColorspace::RGBA)
13✔
130
      texColorspace = TextureColorspace::SRGBA;
10✔
131
  }
132

133
  return texColorspace;
71✔
134
}
135

136
} // namespace
137

138
void Texture::bind() const {
1,580✔
139
  Renderer::bindTexture(m_type, m_index);
1,580✔
140
}
1,580✔
141

142
void Texture::unbind() const {
1,451✔
143
  Renderer::unbindTexture(m_type);
1,451✔
144
}
1,451✔
145

146
void Texture::setFilter(TextureFilter minify, TextureFilter magnify) const {
419✔
147
  ZoneScopedN("Texture::setFilter");
148

149
  bind();
419✔
150
  Renderer::setTextureParameter(m_type, TextureParameter::MINIFY_FILTER, recoverParam(minify));
419✔
151
  Renderer::setTextureParameter(m_type, TextureParameter::MAGNIFY_FILTER, recoverParam(magnify));
419✔
152
  unbind();
419✔
153
}
419✔
154

155
void Texture::setFilter(TextureFilter minify, TextureFilter mipmapMinify, TextureFilter magnify) const {
64✔
156
  ZoneScopedN("Texture::setFilter");
157

158
  bind();
64✔
159
  Renderer::setTextureParameter(m_type, TextureParameter::MINIFY_FILTER, recoverParam(minify, mipmapMinify));
64✔
160
  Renderer::setTextureParameter(m_type, TextureParameter::MAGNIFY_FILTER, recoverParam(magnify));
64✔
161
  unbind();
64✔
162
}
64✔
163

164
void Texture::setWrapping(TextureWrapping wrapping) const {
457✔
165
  ZoneScopedN("Texture::setWrapping");
166

167
  const TextureParameterValue value = recoverParam(wrapping);
457✔
168

169
  bind();
457✔
170
  Renderer::setTextureParameter(m_type, TextureParameter::WRAP_S, value);
457✔
171
  Renderer::setTextureParameter(m_type, TextureParameter::WRAP_T, value);
457✔
172
  Renderer::setTextureParameter(m_type, TextureParameter::WRAP_R, value);
457✔
173
  unbind();
457✔
174
}
457✔
175

176
void Texture::setColorspace(TextureColorspace colorspace) {
66✔
177
  setColorspace(colorspace, (colorspace == TextureColorspace::DEPTH ? TextureDataType::FLOAT32 : TextureDataType::BYTE));
66✔
178
}
66✔
179

180
void Texture::setColorspace(TextureColorspace colorspace, TextureDataType dataType) {
138✔
181
  assert("Error: A depth texture must have a 32-bit floating-point data type."
138✔
182
      && (colorspace != TextureColorspace::DEPTH || dataType == TextureDataType::FLOAT32));
183
  assert("Error: A depth texture cannot be three-dimensional." && (colorspace != TextureColorspace::DEPTH || m_type != TextureType::TEXTURE_3D));
138✔
184

185
  ZoneScopedN("Texture::setColorspace");
186

187
  m_colorspace = colorspace;
138✔
188
  m_dataType   = dataType;
138✔
189

190
  load();
138✔
191

192
  if (m_colorspace == TextureColorspace::DEPTH)
138✔
193
    setFilter(TextureFilter::NEAREST);
12✔
194
}
138✔
195

196
Texture::~Texture() {
389✔
197
  ZoneScopedN("Texture::~Texture");
198

199
  if (!m_index.isValid())
389✔
200
    return;
3✔
201

202
  Logger::debug("[Texture] Destroying (ID: " + std::to_string(m_index) + ")...");
386✔
203
  Renderer::deleteTexture(m_index);
386✔
204
  Logger::debug("[Texture] Destroyed");
386✔
205
}
389✔
206

207
Texture::Texture(TextureType type) : m_type{ type } {
386✔
208
  ZoneScopedN("Texture::Texture");
209

210
  Logger::debug("[Texture] Creating...");
386✔
211
  Renderer::generateTexture(m_index);
386✔
212
  Logger::debug("[Texture] Created (ID: " + std::to_string(m_index) + ')');
386✔
213

214
  setFilter(TextureFilter::LINEAR);
386✔
215
  setWrapping(TextureWrapping::CLAMP);
386✔
216
}
386✔
217

218
void Texture::setLoadedParameters(bool createMipmaps) const {
67✔
219
  ZoneScopedN("Texture::setLoadedParameters");
220

221
  if (m_colorspace == TextureColorspace::GRAY || m_colorspace == TextureColorspace::RG) {
67✔
222
    Renderer::setTextureParameter(m_type, TextureParameter::SWIZZLE_R, static_cast<int>(TextureFormat::RED));
16✔
223
    Renderer::setTextureParameter(m_type, TextureParameter::SWIZZLE_G, static_cast<int>(TextureFormat::RED));
16✔
224
    Renderer::setTextureParameter(m_type, TextureParameter::SWIZZLE_B, static_cast<int>(TextureFormat::RED));
16✔
225
    Renderer::setTextureParameter(m_type, TextureParameter::SWIZZLE_A, (m_colorspace == TextureColorspace::RG ? static_cast<int>(TextureFormat::GREEN) : 1));
16✔
226
  }
227

228
  if (createMipmaps
67✔
229
#if defined(USE_WEBGL)
230
    // WebGL doesn't seem to support mipmap generation for sRGB textures
231
    && m_colorspace != TextureColorspace::SRGB && m_colorspace != TextureColorspace::SRGBA
232
#endif
233
  ) {
234
    generateMipmaps();
53✔
235
    setFilter(TextureFilter::LINEAR, TextureFilter::LINEAR, TextureFilter::LINEAR);
53✔
236
  } else {
237
    setFilter(TextureFilter::LINEAR);
14✔
238
  }
239

240
  setWrapping(TextureWrapping::REPEAT);
67✔
241
}
67✔
242

243
void Texture::generateMipmaps() const {
53✔
244
  ZoneScopedN("Texture::generateMipmaps");
245

246
  bind();
53✔
247
  Renderer::generateMipmap(m_type);
53✔
248
  unbind();
53✔
249
}
53✔
250

251
#if !defined(USE_OPENGL_ES)
252
Texture1D::Texture1D()
18✔
253
  : Texture(TextureType::TEXTURE_1D) {}
18✔
254

255
Texture1D::Texture1D(unsigned int width, TextureColorspace colorspace, TextureDataType dataType)
3✔
256
  : Texture1D(colorspace, dataType) { resize(width); }
3✔
257

258
Texture1D::Texture1D(const Color& color, unsigned int width) : Texture1D() {
5✔
259
  m_width = width;
5✔
260

261
  fill(color);
5✔
262
}
5✔
263

264
void Texture1D::resize(unsigned int width) {
4✔
265
  m_width = width;
4✔
266

267
  load();
4✔
268
}
4✔
269

270
void Texture1D::fill(const Color& color) {
6✔
271
  ZoneScopedN("Texture1D::fill");
272

273
  m_colorspace = TextureColorspace::RGB;
6✔
274
  m_dataType   = TextureDataType::BYTE;
6✔
275

276
  const std::vector<Vec3b> values(m_width * 3, Vec3b(color));
6✔
277

278
  bind();
6✔
279
  Renderer::sendImageData1D(TextureType::TEXTURE_1D,
6✔
280
                            0,
281
                            TextureInternalFormat::RGB,
282
                            m_width,
283
                            TextureFormat::RGB,
284
                            PixelDataType::UBYTE,
285
                            values.data());
6✔
286
  unbind();
6✔
287
}
6✔
288

289
void Texture1D::load() const {
17✔
290
  ZoneScopedN("Texture1D::load");
291

292
  if (m_colorspace == TextureColorspace::INVALID)
17✔
293
    return; // No colorspace has been set yet, the texture can't be loaded
2✔
294

295
  bind();
15✔
296
  Renderer::sendImageData1D(TextureType::TEXTURE_1D,
30✔
297
                            0,
298
                            recoverInternalFormat(m_colorspace, m_dataType),
15✔
299
                            m_width,
15✔
300
                            recoverFormat(m_colorspace),
15✔
301
                            (m_dataType == TextureDataType::BYTE ? PixelDataType::UBYTE : PixelDataType::FLOAT),
15✔
302
                            nullptr);
303
  unbind();
15✔
304
}
305
#endif
306

307
Texture2D::Texture2D()
328✔
308
  : Texture(TextureType::TEXTURE_2D) {}
328✔
309

310
Texture2D::Texture2D(unsigned int width, unsigned int height, TextureColorspace colorspace, TextureDataType dataType)
11✔
311
  : Texture2D(colorspace, dataType) { resize(width, height); }
11✔
312

313
Texture2D::Texture2D(const Color& color, unsigned int width, unsigned int height) : Texture2D() {
149✔
314
  m_width  = width;
149✔
315
  m_height = height;
149✔
316

317
  fill(color);
149✔
318
}
149✔
319

320
void Texture2D::resize(unsigned int width, unsigned int height) {
65✔
321
  m_width  = width;
65✔
322
  m_height = height;
65✔
323

324
  load();
65✔
325
}
65✔
326

327
void Texture2D::load(const Image& image, bool createMipmaps, bool shouldUseSrgb) {
69✔
328
  ZoneScopedN("Texture2D::load(Image)");
329

330
  if (image.isEmpty()) {
69✔
331
    // Image not found, defaulting texture to pure white
332
    fill(ColorPreset::White);
9✔
333
    return;
9✔
334
  }
335

336
  m_width      = image.getWidth();
60✔
337
  m_height     = image.getHeight();
60✔
338
  m_colorspace = recoverColorspace(image.getColorspace(), shouldUseSrgb);
60✔
339
  m_dataType   = (image.getDataType() == ImageDataType::FLOAT ? TextureDataType::FLOAT16 : TextureDataType::BYTE);
60✔
340

341
#if defined(USE_OPENGL_ES)
342
  if ((m_width & (m_width - 1)) != 0 || (m_height & (m_height - 1)) != 0) {
343
    Logger::warn("[Texture] The given image's dimensions (" + std::to_string(m_width) + 'x' + std::to_string(m_height)
344
               + ") are not powers of two; this can give unexpected results.");
345
  }
346
#endif
347

348
  int unpackAlignment = 4;
60✔
349

350
  if (image.getChannelCount() == 1) {
60✔
351
    Renderer::getParameter(StateParameter::UNPACK_ALIGNMENT, &unpackAlignment);
15✔
352
    Renderer::setPixelStorage(PixelStorage::UNPACK_ALIGNMENT, 1);
15✔
353
  }
354

355
  bind();
60✔
356

357
  Renderer::sendImageData2D(TextureType::TEXTURE_2D,
120✔
358
                            0,
359
                            recoverInternalFormat(m_colorspace, m_dataType),
360
                            m_width,
361
                            m_height,
362
                            recoverFormat(m_colorspace),
363
                            (m_dataType == TextureDataType::BYTE ? PixelDataType::UBYTE : PixelDataType::FLOAT),
60✔
364
                            image.getDataPtr());
365

366
  if (image.getChannelCount() == 1)
60✔
367
    Renderer::setPixelStorage(PixelStorage::UNPACK_ALIGNMENT, unpackAlignment);
15✔
368

369
  setLoadedParameters(createMipmaps);
60✔
370
}
371

372
void Texture2D::fill(const Color& color) {
159✔
373
  ZoneScopedN("Texture2D::fill");
374

375
  m_colorspace = TextureColorspace::RGB;
159✔
376
  m_dataType   = TextureDataType::BYTE;
159✔
377

378
  const std::vector<Vec3b> values(m_width * m_height * 3, Vec3b(color));
159✔
379

380
  bind();
159✔
381
  Renderer::sendImageData2D(TextureType::TEXTURE_2D,
159✔
382
                            0,
383
                            TextureInternalFormat::RGB,
384
                            m_width,
385
                            m_height,
386
                            TextureFormat::RGB,
387
                            PixelDataType::UBYTE,
388
                            values.data());
159✔
389
  unbind();
159✔
390
}
159✔
391

392
Image Texture2D::recoverImage() const {
50✔
393
  ZoneScopedN("Texture2D::recoverImage");
394

395
  Image img(m_width, m_height, static_cast<ImageColorspace>(m_colorspace), (m_dataType == TextureDataType::BYTE ? ImageDataType::BYTE : ImageDataType::FLOAT));
50✔
396

397
  const PixelDataType pixelDataType = (m_dataType == TextureDataType::BYTE ? PixelDataType::UBYTE : PixelDataType::FLOAT);
50✔
398

399
#if !defined(USE_OPENGL_ES)
400
  bind();
50✔
401
  Renderer::recoverTextureData(TextureType::TEXTURE_2D, 0, recoverFormat(m_colorspace), pixelDataType, img.getDataPtr());
50✔
402
  unbind();
50✔
403
#else
404
  // Recovering an image directly from a texture (glGetTexImage()) is not possible with OpenGL ES; a framebuffer must be used to read the texture from instead
405
  // See: https://stackoverflow.com/a/53993894/3292304
406

407
  const Framebuffer dummyFramebuffer;
408
  Renderer::bindFramebuffer(dummyFramebuffer.getIndex(), FramebufferType::READ_FRAMEBUFFER);
409

410
  Renderer::setFramebufferTexture2D(FramebufferAttachment::COLOR0, m_index, 0, TextureType::TEXTURE_2D, FramebufferType::READ_FRAMEBUFFER);
411
  Renderer::recoverFrame(m_width, m_height, recoverFormat(m_colorspace), pixelDataType, img.getDataPtr());
412

413
  Renderer::unbindFramebuffer(FramebufferType::READ_FRAMEBUFFER);
414
#endif
415

416
  return img;
50✔
417
}
×
418

419
void Texture2D::load() const {
174✔
420
  ZoneScopedN("Texture2D::load");
421

422
  if (m_colorspace == TextureColorspace::INVALID)
174✔
423
    return; // No colorspace has been set yet, the texture can't be loaded
2✔
424

425
  bind();
172✔
426
  Renderer::sendImageData2D(TextureType::TEXTURE_2D,
344✔
427
                            0,
428
                            recoverInternalFormat(m_colorspace, m_dataType),
172✔
429
                            m_width,
172✔
430
                            m_height,
172✔
431
                            recoverFormat(m_colorspace),
172✔
432
                            (m_dataType == TextureDataType::BYTE ? PixelDataType::UBYTE : PixelDataType::FLOAT),
172✔
433
                            nullptr);
434
  unbind();
172✔
435
}
436

437
Texture3D::Texture3D()
40✔
438
  : Texture(TextureType::TEXTURE_3D) {}
40✔
439

440
Texture3D::Texture3D(unsigned int width, unsigned int height, unsigned int depth, TextureColorspace colorspace, TextureDataType dataType)
3✔
441
  : Texture3D(colorspace, dataType) { resize(width, height, depth); }
3✔
442

443
Texture3D::Texture3D(const Color& color, unsigned int width, unsigned int height, unsigned int depth) : Texture3D() {
10✔
444
  m_width  = width;
10✔
445
  m_height = height;
10✔
446
  m_depth  = depth;
10✔
447

448
  fill(color);
10✔
449
}
10✔
450

451
void Texture3D::resize(unsigned int width, unsigned int height, unsigned int depth) {
8✔
452
  m_width  = width;
8✔
453
  m_height = height;
8✔
454
  m_depth  = depth;
8✔
455

456
  load();
8✔
457
}
8✔
458

459
void Texture3D::load(const std::vector<Image>& imageSlices, bool createMipmaps, bool shouldUseSrgb) {
17✔
460
  ZoneScopedN("Texture3D::load(std::vector<Image>)");
461

462
  if (imageSlices.empty() || imageSlices.front().isEmpty()) {
17✔
463
    // Images not found, defaulting texture to pure white
464
    fill(ColorPreset::White);
6✔
465
    return;
6✔
466
  }
467

468
  const ImageColorspace firstImgColorspace = imageSlices.front().getColorspace();
11✔
469
  const ImageDataType firstImgDataType     = imageSlices.front().getDataType();
11✔
470

471
  m_width      = imageSlices.front().getWidth();
11✔
472
  m_height     = imageSlices.front().getHeight();
11✔
473
  m_depth      = static_cast<unsigned int>(imageSlices.size());
11✔
474
  m_colorspace = recoverColorspace(firstImgColorspace, shouldUseSrgb);
11✔
475
  m_dataType   = (firstImgDataType == ImageDataType::FLOAT ? TextureDataType::FLOAT16 : TextureDataType::BYTE);
11✔
476

477
#if defined(USE_OPENGL_ES)
478
  if ((m_width & (m_width - 1)) != 0 || (m_height & (m_height - 1)) != 0 || (m_depth & (m_depth - 1)) != 0) {
479
    Logger::warn("[Texture] The given image's dimensions (" + std::to_string(m_width) + 'x' + std::to_string(m_height) + 'x' + std::to_string(m_depth)
480
               + ") are not powers of two; this can give unexpected results.");
481
  }
482
#endif
483

484
  load();
11✔
485

486
  const TextureFormat textureFormat = recoverFormat(m_colorspace);
11✔
487
  const PixelDataType pixelDataType = (m_dataType == TextureDataType::BYTE ? PixelDataType::UBYTE : PixelDataType::FLOAT);
11✔
488

489
  bind();
11✔
490

491
  for (std::size_t imgIndex = 0; imgIndex < imageSlices.size(); ++imgIndex) {
23✔
492
    const Image& img = imageSlices[imgIndex];
16✔
493

494
    if (img.getWidth() != m_width || img.getHeight() != m_height || img.getColorspace() != firstImgColorspace || img.getDataType() != firstImgDataType)
16✔
495
      throw std::invalid_argument("[Texture3D] The given images have different attributes.");
4✔
496

497
    Renderer::sendImageSubData3D(TextureType::TEXTURE_3D,
12✔
498
                                 0,
499
                                 0,
500
                                 0,
501
                                 static_cast<unsigned int>(imgIndex),
502
                                 m_width,
503
                                 m_height,
504
                                 1,
505
                                 textureFormat,
506
                                 pixelDataType,
507
                                 img.getDataPtr());
508
  }
509

510
  setLoadedParameters(createMipmaps);
7✔
511
}
512

513
void Texture3D::fill(const Color& color) {
17✔
514
  ZoneScopedN("Texture3D::fill");
515

516
  m_colorspace = TextureColorspace::RGB;
17✔
517
  m_dataType   = TextureDataType::BYTE;
17✔
518

519
  const std::vector<Vec3b> values(m_width * m_height * m_depth * 3, Vec3b(color));
17✔
520

521
  bind();
17✔
522
  Renderer::sendImageData3D(TextureType::TEXTURE_3D,
17✔
523
                            0,
524
                            TextureInternalFormat::RGB,
525
                            m_width,
526
                            m_height,
527
                            m_depth,
528
                            TextureFormat::RGB,
529
                            PixelDataType::UBYTE,
530
                            values.data());
17✔
531
  unbind();
17✔
532
}
17✔
533

534
void Texture3D::load() const {
35✔
535
  ZoneScopedN("Texture3D::load");
536

537
  if (m_colorspace == TextureColorspace::INVALID)
35✔
538
    return; // No colorspace has been set yet, the texture can't be loaded
2✔
539

540
  bind();
33✔
541
  Renderer::sendImageData3D(TextureType::TEXTURE_3D,
66✔
542
                            0,
543
                            recoverInternalFormat(m_colorspace, m_dataType),
33✔
544
                            m_width,
33✔
545
                            m_height,
33✔
546
                            m_depth,
33✔
547
                            recoverFormat(m_colorspace),
33✔
548
                            (m_dataType == TextureDataType::BYTE ? PixelDataType::UBYTE : PixelDataType::FLOAT),
33✔
549
                            nullptr);
550
  unbind();
33✔
551
}
552

553
} // namespace Raz
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc