@@ -248,7 +248,7 @@ class TextureBaseTyped : public TextureBase {
248
248
subImage (std::make_index_sequence<v_dim>(), image, offset, mipmap_level);
249
249
}
250
250
251
- // / @brief Regenerates all mipmaps from the top level.
251
+ // / @brief Generates all mipmaps from the top level using OpenGL's built-in glGenerateMipmap .
252
252
void generateMipmap ()
253
253
{
254
254
this ->bind ();
@@ -505,7 +505,7 @@ class TextureBaseRegular : public TextureBaseTyped<v_dim, v_target> {
505
505
{}
506
506
507
507
// / @brief Initializes a new texture with the given size.
508
- // / @remark mipmap_levels defaults to generating a full mipmap down to 1x1.
508
+ // / @remark mipmap_levels defaults to generating storage for a full mipmap down to 1x1.
509
509
explicit TextureBaseRegular (svec<v_dim> size,
510
510
std::optional<GLsizei> mipmap_levels = std::nullopt,
511
511
PixelInternalFormat internal_format = PixelInternalFormat::RGBA8)
@@ -515,7 +515,7 @@ class TextureBaseRegular : public TextureBaseTyped<v_dim, v_target> {
515
515
}
516
516
517
517
// / @brief Initializes a new texture with the given image data.
518
- // / @remark mipmap_levels defaults to generating a full mipmap down to 1x1.
518
+ // / @remark mipmap_levels defaults to generating storage for a full mipmap down to 1x1.
519
519
// / @remark internal_format defaults to being chosen, based on the format of the provided image.
520
520
template <PixelFormat v_pixel_format, PixelType v_pixel_type, std::size_t v_row_alignment>
521
521
explicit TextureBaseRegular (const Image<v_dim, v_pixel_format, v_pixel_type, v_row_alignment>& image,
@@ -532,7 +532,7 @@ class TextureBaseRegular : public TextureBaseTyped<v_dim, v_target> {
532
532
TextureBaseRegular& operator =(const TextureBaseRegular&) = delete ;
533
533
534
534
// / @brief Generates storage for the specified size.
535
- // / @remark mipmap_levels defaults to generating a full mipmap down to 1x1.
535
+ // / @remark mipmap_levels defaults to generating storage for a full mipmap down to 1x1.
536
536
void generate (svec<v_dim> size,
537
537
std::optional<GLsizei> mipmap_levels = std::nullopt,
538
538
PixelInternalFormat internal_format = PixelInternalFormat::RGBA8)
@@ -542,7 +542,7 @@ class TextureBaseRegular : public TextureBaseTyped<v_dim, v_target> {
542
542
}
543
543
544
544
// / @brief Generates texture storage and fills it with the provided image.
545
- // / @remark mipmap_levels defaults to generating a full mipmap down to 1x1.
545
+ // / @remark mipmap_levels defaults to generating storage for a full mipmap down to 1x1.
546
546
// / @remark internal_format defaults to being chosen, based on the format of the provided image.
547
547
template <PixelFormat v_pixel_format, PixelType v_pixel_type, std::size_t v_row_alignment>
548
548
void generate (const Image<v_dim, v_pixel_format, v_pixel_type, v_row_alignment>& image,
@@ -554,38 +554,17 @@ class TextureBaseRegular : public TextureBaseTyped<v_dim, v_target> {
554
554
storage (
555
555
std::make_index_sequence<v_dim>(), static_cast <svec<v_dim>>(image.size ()), mipmap_levels, internal_format);
556
556
this ->subImage (std::make_index_sequence<v_dim>(), image);
557
- glGenerateMipmap (toGLConstant (v_target));
558
557
}
559
558
560
559
protected:
561
560
TextureBaseRegular (TextureBaseRegular&&) = default ;
562
561
TextureBaseRegular& operator =(TextureBaseRegular&&) = default ;
563
562
564
563
private:
565
- // / @brief Returns the biggest component of a given vector.
566
- template <std::size_t ... v_indices>
567
- static GLsizei maxSize (svec<v_dim> size, std::index_sequence<v_indices...>)
568
- {
569
- GLsizei result = 0 ;
570
- ((result = std::max (result, size[v_indices])), ...);
571
- return result;
572
- }
573
-
574
- // / @brief Calculates the integer log2 plus one of the given value, which is the required mipmap count for a given
575
- // / size.
576
- static GLsizei mipmapCount (GLsizei value)
577
- {
578
- // TODO: C++20 use std::bit_width
579
- GLsizei result = 1 ;
580
- while (value >>= 1 )
581
- result++;
582
- return result;
583
- }
584
-
585
- // / @brief Returns the required count to generate a full mipmap down to 1x1 for the given size.
586
- GLsizei maxMipmapLevelsFor (svec<v_dim> size)
564
+ // / @brief Calculates the required mipmap count for a given size.
565
+ static constexpr GLsizei mipmapCount (GLsizei value)
587
566
{
588
- return mipmapCount ( maxSize (size, std::make_index_sequence<v_dim>())) ;
567
+ return dutils::ilog2 ( static_cast < std::make_unsigned_t <GLsizei>>(value)) + 1 ;
589
568
}
590
569
591
570
// / @brief Calls glTexStorage with the provided parameters and index sequence of the textures dimension.
@@ -595,10 +574,18 @@ class TextureBaseRegular : public TextureBaseTyped<v_dim, v_target> {
595
574
std::optional<GLsizei> mipmap_levels = std::nullopt,
596
575
PixelInternalFormat internal_format = PixelInternalFormat::RGBA8)
597
576
{
598
- glTexStorage<v_dim>(toGLConstant (v_target),
599
- mipmap_levels.value_or (maxMipmapLevelsFor (size)),
600
- toGLConstant (internal_format),
601
- size[v_indices]...);
577
+ if (!mipmap_levels) {
578
+ if constexpr (v_target == TextureTarget::Texture1DArray)
579
+ mipmap_levels = mipmapCount (size.x ().maxValue ());
580
+ else if constexpr (v_target == TextureTarget::Texture2DArray ||
581
+ v_target == TextureTarget::Texture2DMultisampleArray ||
582
+ v_target == TextureTarget::TextureCubeMapArray)
583
+ mipmap_levels = mipmapCount (size.xy ().maxValue ());
584
+ else
585
+ mipmap_levels = mipmapCount (size.maxValue ());
586
+ }
587
+
588
+ glTexStorage<v_dim>(toGLConstant (v_target), *mipmap_levels, toGLConstant (internal_format), size[v_indices]...);
602
589
this ->setSize (size);
603
590
}
604
591
};
0 commit comments