Skip to content

Commit

Permalink
Begin to implement new TextureFormat design
Browse files Browse the repository at this point in the history
  • Loading branch information
adamkewley committed Aug 27, 2024
1 parent 9977120 commit 275683c
Show file tree
Hide file tree
Showing 16 changed files with 82 additions and 45 deletions.
1 change: 1 addition & 0 deletions src/oscar/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ add_library(oscar STATIC
Graphics/Snorm8.h
Graphics/SourceBlendingFactor.h
Graphics/SubMeshDescriptor.h
Graphics/TextureChannelEncoding.h
Graphics/TextureChannelFormat.h
Graphics/TextureDimensionality.h
Graphics/TextureFilterMode.h
Expand Down
3 changes: 1 addition & 2 deletions src/oscar/Formats/SVG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ Texture2D osc::load_texture2D_from_svg(std::istream& in, float scale)
// return as a GPU-ready texture
Texture2D rv{
{bitmap.width(), bitmap.height()},
TextureFormat::RGBA32,
ColorSpace::sRGB,
TextureFormat::R8G8B8A8_SRGB,
TextureWrapMode::Clamp,
TextureFilterMode::Nearest,
};
Expand Down
1 change: 1 addition & 0 deletions src/oscar/Graphics.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <oscar/Graphics/Snorm8.h>
#include <oscar/Graphics/SourceBlendingFactor.h>
#include <oscar/Graphics/SubMeshDescriptor.h>
#include <oscar/Graphics/TextureChannelEncoding.h>
#include <oscar/Graphics/TextureChannelFormat.h>
#include <oscar/Graphics/TextureDimensionality.h>
#include <oscar/Graphics/TextureFilterMode.h>
Expand Down
6 changes: 3 additions & 3 deletions src/oscar/Graphics/Detail/TextureFormatList.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
namespace osc::detail
{
using TextureFormatList = OptionList<TextureFormat,
TextureFormat::R8,
TextureFormat::RG16,
TextureFormat::RGB24,
TextureFormat::R8_UNORM,
TextureFormat::R8G8_UNORM,
TextureFormat::R8G8B8_UNORM,
TextureFormat::RGBA32,
TextureFormat::RGFloat,
TextureFormat::RGBFloat,
Expand Down
6 changes: 3 additions & 3 deletions src/oscar/Graphics/Detail/TextureFormatTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ namespace osc::detail
struct TextureFormatTraits;

template<>
struct TextureFormatTraits<TextureFormat::R8> {
struct TextureFormatTraits<TextureFormat::R8_UNORM> {
static inline constexpr CPUDataType equivalent_cpu_datatype = CPUDataType::UnsignedByte;
static inline constexpr CPUImageFormat equivalent_cpu_image_format = CPUImageFormat::R8;
static inline constexpr size_t num_channels = 1;
static inline constexpr TextureChannelFormat channel_format = TextureChannelFormat::Uint8;
};

template<>
struct TextureFormatTraits<TextureFormat::RG16> {
struct TextureFormatTraits<TextureFormat::R8G8_UNORM> {
static inline constexpr CPUDataType equivalent_cpu_datatype = CPUDataType::UnsignedByte;
static inline constexpr CPUImageFormat equivalent_cpu_image_format = CPUImageFormat::RG;
static inline constexpr size_t num_channels = 2;
static inline constexpr TextureChannelFormat channel_format = TextureChannelFormat::Uint8;
};

template<>
struct TextureFormatTraits<TextureFormat::RGB24> {
struct TextureFormatTraits<TextureFormat::R8G8B8_UNORM> {
static inline constexpr CPUDataType equivalent_cpu_datatype = CPUDataType::UnsignedByte;
static inline constexpr CPUImageFormat equivalent_cpu_image_format = CPUImageFormat::RGB;
static inline constexpr size_t num_channels = 3;
Expand Down
8 changes: 4 additions & 4 deletions src/oscar/Graphics/GraphicsImplementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1922,10 +1922,10 @@ std::optional<TextureFormat> osc::to_texture_format(size_t num_channels, Texture

static_assert(num_options<TextureFormat>() == 7);
switch (num_channels) {
case 1: return format_is_byte_oriented ? TextureFormat::R8 : std::optional<TextureFormat>{};
case 2: return format_is_byte_oriented ? TextureFormat::RG16 : TextureFormat::RGFloat;
case 3: return format_is_byte_oriented ? TextureFormat::RGB24 : TextureFormat::RGBFloat;
case 4: return format_is_byte_oriented ? TextureFormat::RGBA32 : TextureFormat::RGBAFloat;
case 1: return format_is_byte_oriented ? TextureFormat::R8_UNORM : std::optional<TextureFormat>{};
case 2: return format_is_byte_oriented ? TextureFormat::R8G8_UNORM : TextureFormat::RGFloat;
case 3: return format_is_byte_oriented ? TextureFormat::R8G8B8_UNORM : TextureFormat::RGBFloat;
case 4: return format_is_byte_oriented ? TextureFormat::RGBA32 : TextureFormat::RGBAFloat;
default: return std::nullopt;
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/oscar/Graphics/OpenGL/TextureFormatOpenGLTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace osc::detail
struct TextureFormatOpenGLTraits;

template<>
struct TextureFormatOpenGLTraits<TextureFormat::R8> {
struct TextureFormatOpenGLTraits<TextureFormat::R8_UNORM> {
static inline constexpr GLint unpack_alignment = 1;
static inline constexpr GLenum internal_format_srgb = GL_R8;
static inline constexpr GLenum internal_format_linear = GL_R8;
Expand All @@ -18,7 +18,7 @@ namespace osc::detail
};

template<>
struct TextureFormatOpenGLTraits<TextureFormat::RG16> {
struct TextureFormatOpenGLTraits<TextureFormat::R8G8_UNORM> {
static inline constexpr GLint unpack_alignment = 1;
static inline constexpr GLenum internal_format_srgb = GL_RG;
static inline constexpr GLenum internal_format_linear = GL_RG;
Expand All @@ -27,7 +27,7 @@ namespace osc::detail
};

template<>
struct TextureFormatOpenGLTraits<TextureFormat::RGB24> {
struct TextureFormatOpenGLTraits<TextureFormat::R8G8B8_UNORM> {
static inline constexpr GLint unpack_alignment = 1;
static inline constexpr GLenum internal_format_srgb = GL_SRGB8;
static inline constexpr GLenum internal_format_linear = GL_RGB8;
Expand Down
4 changes: 1 addition & 3 deletions src/oscar/Graphics/Texture2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@ namespace osc
public:
Texture2D(
Vec2i dimensions,
TextureFormat = TextureFormat::RGBA32,
ColorSpace = ColorSpace::sRGB,
TextureFormat = TextureFormat::Default,
TextureWrapMode = TextureWrapMode::Repeat,
TextureFilterMode = TextureFilterMode::Linear
);

Vec2i dimensions() const;
TextureFormat texture_format() const;
ColorSpace color_space() const;

TextureWrapMode wrap_mode() const; // same as wrap_mode_u
void set_wrap_mode(TextureWrapMode); // sets all axes
Expand Down
11 changes: 11 additions & 0 deletions src/oscar/Graphics/TextureChannelEncoding.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

namespace osc
{
// describes the encoding method used to read/write values to a single channel (R/G/B/A) of a texture
enum class TextureChannelEncoding {
Linear,
sRGB,
NUM_OPTIONS
};
}
1 change: 1 addition & 0 deletions src/oscar/Graphics/TextureChannelFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace osc
{
// describes the native format of a single channel (R/G/B/A) of a texture
enum class TextureChannelFormat {
Uint8,
Float32,
Expand Down
37 changes: 32 additions & 5 deletions src/oscar/Graphics/TextureFormat.h
Original file line number Diff line number Diff line change
@@ -1,27 +1,54 @@
#pragma once

#include <oscar/Graphics/TextureChannelEncoding.h>
#include <oscar/Graphics/TextureChannelFormat.h>

#include <cstddef>
#include <optional>

namespace osc
{
// the underlying format used by a texture
//
// note: the naming convention and docuemntation for each format is designed
// to be the same as Vulkan's:
//
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFormat.html
enum class TextureFormat {
R8,
RG16,
RGB24,
RGBA32,
// a one-component, 8-bit unsigned normalized format that has a single 8-bit R component
R8_UNORM,

// a two-component, 16-bit unsigned normalized format that has an 8-bit R component in byte
// 0, and an 8-bit G component in byte 1.
R8G8_UNORM,

// a three-component, 24-bit unsigned normalized format that has an 8-bit R component in
// byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
R8G8B8_UNORM,

// a four-component, 32-bit unsigned normalized format that has an 8-bit R component in byte 0,
// an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in
// byte 3.
R8G8B8A8_UNORM,

// a four-component, 32-bit unsigned normalized format that has an 8-bit R component stored with
// sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in
// byte 1, an 8-bit B component stored with sRGB nonlinear encoding in byte 2, and an 8-bit A
// component in byte 3.
R8G8B8A8_SRGB,

RGFloat,
RGBFloat,
RGBAFloat,

NUM_OPTIONS,

Default = R8G8B8A8_SRGB,
};

size_t num_channels_in(TextureFormat);
TextureChannelFormat channel_format_of(TextureFormat);
TextureChannelFormat channel_format_of(TextureFormat, size_t channel);
TextureChannelEncoding channel_encoding_of(TextureFormat, size_t channel);
size_t num_bytes_per_pixel_in(TextureFormat);
std::optional<TextureFormat> to_texture_format(size_t num_channels, TextureChannelFormat);
}
3 changes: 1 addition & 2 deletions src/oscar/Graphics/Textures/ChequeredTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ namespace

Texture2D rv{
texture_dims,
TextureFormat::RGBA32,
ColorSpace::sRGB,
TextureFormat::R8G8B8A8_SRGB,
TextureWrapMode::Repeat,
TextureFilterMode::Nearest,
};
Expand Down
2 changes: 1 addition & 1 deletion src/oscar/UI/Tabs/ScreenshotTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ class osc::ScreenshotTab::Impl final : public StandardTabImpl {
c.render_to(render_texture);
}

Texture2D rv{render_texture.dimensions(), TextureFormat::RGB24, ColorSpace::sRGB};
Texture2D rv{render_texture.dimensions(), TextureFormat::R8G8B8_UNORM, ColorSpace::sRGB};
graphics::copy_texture(render_texture, rv);
return rv;
}
Expand Down
8 changes: 4 additions & 4 deletions tests/testoscar/Graphics/TestCubemap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ TEST(Cubemap, can_move_construct)
TEST(Cubemap, can_copy_assign)
{
const Cubemap first{1, TextureFormat::RGBA32};
Cubemap second{2, TextureFormat::RGB24};
Cubemap second{2, TextureFormat::R8G8B8_UNORM};
second = first;

ASSERT_EQ(second.width(), first.width());
Expand All @@ -57,7 +57,7 @@ TEST(Cubemap, is_nothrow_assignable)
TEST(Cubemap, can_move_assign)
{
const int32_t first_width = 1;
const TextureFormat first_format = TextureFormat::RGB24;
const TextureFormat first_format = TextureFormat::R8G8B8_UNORM;
Cubemap first{first_width, first_format};

const int32_t second_width = 2;
Expand Down Expand Up @@ -127,7 +127,7 @@ TEST(Cubemap, width_returns_width_provided_via_constructor)

TEST(Cubemap, format_returns_TextureFormat_provided_via_constructor)
{
const TextureFormat format = TextureFormat::RGB24;
const TextureFormat format = TextureFormat::R8G8B8_UNORM;
const Cubemap cubemap{1, format};

ASSERT_EQ(cubemap.texture_format(), format);
Expand Down Expand Up @@ -163,7 +163,7 @@ TEST(Cubemap, set_pixel_data_throws_exception_if_given_invalid_number_of_bytes_f

TEST(Cubemap, set_pixel_data_throws_if_given_invalid_number_of_bytes_for_RGB24)
{
const TextureFormat format = TextureFormat::RGB24;
const TextureFormat format = TextureFormat::R8G8B8_UNORM;
const size_t invalid_num_bytes_per_pixel = 4;
const size_t width = 5;
const size_t invalid_num_bytes_per_face = width*width*invalid_num_bytes_per_pixel;
Expand Down
6 changes: 3 additions & 3 deletions tests/testoscar/Graphics/TestTexture2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ TEST(Texture2D, SetPixelDataWorksFineFor8BitSingleChannelData)
const Vec2i dimensions = {1, 1};
const std::vector<uint8_t> singleChannelPixels(static_cast<size_t>(dimensions.x * dimensions.y));

Texture2D t{dimensions, TextureFormat::R8};
Texture2D t{dimensions, TextureFormat::R8_UNORM};
t.set_pixel_data(singleChannelPixels); // shouldn't throw
}

Expand All @@ -127,7 +127,7 @@ TEST(Texture2D, SetPixelDataWith8BitSingleChannelDataFollowedByGetPixelsBlanksOu
const Vec2i dimensions = {1, 1};
const std::vector<uint8_t> singleChannelPixels(static_cast<size_t>(dimensions.x * dimensions.y), color);

Texture2D t{dimensions, TextureFormat::R8};
Texture2D t{dimensions, TextureFormat::R8_UNORM};
t.set_pixel_data(singleChannelPixels);

for (const Color& c : t.pixels()) {
Expand All @@ -141,7 +141,7 @@ TEST(Texture2D, SetPixelDataWith8BitSingleChannelDataFollowedByGetPixels32Blanks
const Vec2i dimensions = {1, 1};
const std::vector<uint8_t> singleChannelPixels(static_cast<size_t>(dimensions.x * dimensions.y), color);

Texture2D t{dimensions, TextureFormat::R8};
Texture2D t{dimensions, TextureFormat::R8_UNORM};
t.set_pixel_data(singleChannelPixels);

for (const Color32& c : t.pixels32()) {
Expand Down
24 changes: 12 additions & 12 deletions tests/testoscar/Graphics/TestTextureFormat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ TEST(TextureFormat, NumChannelsReturnsExpectedValues)
{
static_assert(num_options<TextureFormat>() == 7);

ASSERT_EQ(num_channels_in(TextureFormat::R8), 1);
ASSERT_EQ(num_channels_in(TextureFormat::RG16), 2);
ASSERT_EQ(num_channels_in(TextureFormat::RGB24), 3);
ASSERT_EQ(num_channels_in(TextureFormat::R8_UNORM), 1);
ASSERT_EQ(num_channels_in(TextureFormat::R8G8_UNORM), 2);
ASSERT_EQ(num_channels_in(TextureFormat::R8G8B8_UNORM), 3);
ASSERT_EQ(num_channels_in(TextureFormat::RGBA32), 4);
ASSERT_EQ(num_channels_in(TextureFormat::RGFloat), 2);
ASSERT_EQ(num_channels_in(TextureFormat::RGBFloat), 3);
Expand All @@ -29,9 +29,9 @@ TEST(TextureFormat, ChannelFormatReturnsExpectedValues)
{
static_assert(num_options<TextureFormat>() == 7);

ASSERT_EQ(channel_format_of(TextureFormat::R8), TextureChannelFormat::Uint8);
ASSERT_EQ(channel_format_of(TextureFormat::RG16), TextureChannelFormat::Uint8);
ASSERT_EQ(channel_format_of(TextureFormat::RGB24), TextureChannelFormat::Uint8);
ASSERT_EQ(channel_format_of(TextureFormat::R8_UNORM), TextureChannelFormat::Uint8);
ASSERT_EQ(channel_format_of(TextureFormat::R8G8_UNORM), TextureChannelFormat::Uint8);
ASSERT_EQ(channel_format_of(TextureFormat::R8G8B8_UNORM), TextureChannelFormat::Uint8);
ASSERT_EQ(channel_format_of(TextureFormat::RGBA32), TextureChannelFormat::Uint8);
ASSERT_EQ(channel_format_of(TextureFormat::RGFloat), TextureChannelFormat::Float32);
ASSERT_EQ(channel_format_of(TextureFormat::RGBFloat), TextureChannelFormat::Float32);
Expand All @@ -42,9 +42,9 @@ TEST(TextureFormat, NumBytesPerPixelReturnsExpectedValues)
{
static_assert(num_options<TextureFormat>() == 7);

ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::R8), 1);
ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::RG16), 2);
ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::RGB24), 3);
ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::R8_UNORM), 1);
ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::R8G8_UNORM), 2);
ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::R8G8B8_UNORM), 3);
ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::RGBA32), 4);
ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::RGFloat), 8);
ASSERT_EQ(num_bytes_per_pixel_in(TextureFormat::RGBFloat), 12);
Expand All @@ -55,9 +55,9 @@ TEST(TextureFormat, ToTextureFormatReturnsExpectedValues)
{
static_assert(num_options<TextureFormat>() == 7);

ASSERT_EQ(to_texture_format(1, TextureChannelFormat::Uint8), TextureFormat::R8);
ASSERT_EQ(to_texture_format(2, TextureChannelFormat::Uint8), TextureFormat::RG16);
ASSERT_EQ(to_texture_format(3, TextureChannelFormat::Uint8), TextureFormat::RGB24);
ASSERT_EQ(to_texture_format(1, TextureChannelFormat::Uint8), TextureFormat::R8_UNORM);
ASSERT_EQ(to_texture_format(2, TextureChannelFormat::Uint8), TextureFormat::R8G8_UNORM);
ASSERT_EQ(to_texture_format(3, TextureChannelFormat::Uint8), TextureFormat::R8G8B8_UNORM);
ASSERT_EQ(to_texture_format(4, TextureChannelFormat::Uint8), TextureFormat::RGBA32);
ASSERT_EQ(to_texture_format(5, TextureChannelFormat::Uint8), std::nullopt);

Expand Down

0 comments on commit 275683c

Please sign in to comment.