Skip to content

Commit

Permalink
Completed: Image, FontAtlas, & FontBatchRenderer
Browse files Browse the repository at this point in the history
  • Loading branch information
WillisMedwell committed Mar 11, 2024
1 parent 69746a3 commit c9b1ba2
Show file tree
Hide file tree
Showing 13 changed files with 297 additions and 397 deletions.
36 changes: 20 additions & 16 deletions code/Demos/src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,11 +411,15 @@ struct IsoData {
Renderer::ResourceManager resource_manager;
Renderer::InstanceRenderer instance_renderer;

std::optional<Renderer::FontBatchRenderer> font_batch_renderer;

Cameras::StationaryPerspective camera { glm::vec3(0, 1, -1), glm::normalize(glm::vec3(0, -0.25f, 0.5f)) };
};
struct IsoLogic {
void init(AppRenderer& renderer, Core::AudioManager& audio, IsoData& data) {

std::cout << std::thread::hardware_concurrency() << '\n';

Media::Sound sound {};

auto wav_file_data = Utily::FileReader::load_entire_file("assets/background_sound.wav");
Expand All @@ -430,22 +434,22 @@ struct IsoLogic {
data.spinning.angle = 0;
data.spinning.rotations_per_second = 1;

auto model_data = std::move(
Utily::FileReader::load_entire_file("assets/teapot.obj")
.on_error(print_then_quit)
.value());
auto model = std::move(
Model::decode_as_static_model(model_data, ".obj")
.on_error(print_then_quit)
.value());

auto image_png = std::move(
Utily::FileReader::load_entire_file("assets/texture.png")
.on_error(print_then_quit)
.value());
auto image = Media::Image {};
image.init(image_png, true, false)
.on_error(print_then_quit);
auto model_data = Utily::FileReader::load_entire_file("assets/teapot.obj")
.on_error_panic()
.value_move();
auto model = Model::decode_as_static_model(model_data, ".obj")
.on_error_panic()
.value_move();
auto image = Media::Image::create("assets/texture.png")
.on_error_panic()
.value_move();

data.font_batch_renderer.emplace(Renderer::FontBatchRenderer::create(data.resource_manager, "assets/RobotoMono.ttf")
.on_error_panic()
.value_move());

auto font_atlas = Media::FontAtlas::create("assets/RobotoMono.ttf", 500).on_error_panic().value_move();
font_atlas.atlas_image().save_to_disk("RobotoMonoAtlas.png");

data.instance_renderer.init(data.resource_manager, model, image);

Expand Down
2 changes: 1 addition & 1 deletion code/Engine/include/Core/Texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Core {
Texture(Texture&&);

[[nodiscard]] auto init() noexcept -> Utily::Result<void, Utily::Error>;
auto upload_image(Media::Image& image, Filter filter = Filter::smooth, bool offload_image_on_success = false) noexcept -> Utily::Result<void, Utily::Error>;
auto upload_image(const Media::Image& image, Filter filter = Filter::smooth) noexcept -> Utily::Result<void, Utily::Error>;

// Once texture unit is aquired, it cannot be taken away unless unbinded() or just bind(false).
[[nodiscard]] auto bind(bool locked = false) noexcept -> Utily::Result<uint32_t, Utily::Error>;
Expand Down
41 changes: 19 additions & 22 deletions code/Engine/include/Media/Font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
#include <ranges>
#include <utility>

#if 0
namespace Media {

namespace FontAtlasConstants {
namespace FontAtlasConstants {
consteval static auto gen_drawable_chars() {
constexpr char first_printable = char(32);
constexpr char last_printable = char(127);
Expand All @@ -33,11 +34,6 @@ namespace Media {
}
constexpr static auto IS_CHAR_DRAWABLE = gen_is_char_drawable_table();
}
}

#if 0

namespace Media {

class Font;

Expand Down Expand Up @@ -101,31 +97,32 @@ namespace Media {
{
public:
/// @brief Load .ttf font from disk. Generate a font-atlas image. Can fail.
static auto create(std::filesystem::path path) noexcept -> Utily::Result<FontAtlas, Utily::Error>;
[[nodiscard]] static auto create(std::filesystem::path path, uint32_t char_height_px) noexcept -> Utily::Result<FontAtlas, Utily::Error>;

FontAtlas(FontAtlas&& other)
: _m(std::move(other.m)) { }
: _m(std::move(other._m)) { }

struct UvCoord {
float min_x;
float max_x;
float min_y;
float max_y;
};
[[nodiscard]] auto uv_for(char a) const noexcept -> FontAtlas::UvCoord;

auto uv_for(char c) const noexcept -> glm::vec2;
[[nodiscard]] auto atlas_image() const noexcept -> const Media::Image& { return _m.atlas_image; }
[[nodiscard]] auto atlas_layout() const noexcept { return _m.atlas_layout; }
[[nodiscard]] auto glyph_dimensions() const noexcept { return _m.glyph_dimensions; }

private:
struct M {
const Media::Image atlas_image;
const glm::vec2 atlas_layout;
const glm::vec2 glyph_dimensions;
Media::Image atlas_image;
glm::vec2 atlas_layout;
glm::vec2 glyph_dimensions;
} _m;

explicit FontAtlas(M m)
explicit FontAtlas(M&& m)
: _m(std::move(m)) { }

constexpr static auto PRINTABLE_CHARS = []() {
constexpr char first_printable = char(32);
constexpr char last_printable = char(127);
constexpr size_t n = last_printable - first_printable;
std::array<char, n> chars {};
std::ranges::copy(std::views::iota(first_printable, last_printable), chars.begin());
return chars;
}();
};
}

Expand Down
11 changes: 7 additions & 4 deletions code/Engine/include/Media/Image.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,18 @@ namespace Media {
[[nodiscard]] static auto create(std::filesystem::path path)
-> Utily::Result<Image, Utily::Error>;
/// @brief Take decoded-raw image data and copy it. Can fail.
[[nodiscard]] static auto create(std::span<uint8_t> raw_bytes, glm::uvec2 dimensions, InternalFormat format)
[[nodiscard]] static auto create(std::span<const uint8_t> raw_bytes, glm::uvec2 dimensions, InternalFormat format)
-> Utily::Result<Image, Utily::Error>;

Image(Image&& other);

[[nodiscard]] inline auto raw_bytes() const noexcept { return std::span { _m.data.get(), _m.data_size_bytes }; }
[[nodsicard]] inline auto dimensions() const noexcept { return _m.dimensions; }
[[nodiscard]] auto format() const { return _m.format; }
[[nodiscard]] auto opengl_format() const -> uint32_t;

Image(Image&& other);
Image(const Image&) = delete;

auto save_to_disk(std::filesystem::path path) const noexcept -> Utily::Result<void, Utily::Error>;
private:
struct M {
std::unique_ptr<uint8_t[]> data = {};
Expand All @@ -95,7 +98,7 @@ namespace Media {
InternalFormat format = InternalFormat::undefined;
} _m;

explicit Image(M m)
explicit Image(M&& m)
: _m(std::move(m)) { }
};
}
36 changes: 22 additions & 14 deletions code/Engine/include/Renderer/FontBatchRenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ namespace Renderer {
glm::vec2 screen_dimensions;
glm::vec4 font_colour;
};
void init(ResourceManager& resource_manager, Media::FontAtlas& font_atlas);


static auto create(ResourceManager& resource_manager, std::filesystem::path ttf_path) noexcept -> Utily::Result<FontBatchRenderer, Utily::Error>;

void begin_batch(BatchConfig&& batch_config);
void push_to_batch(std::string_view text, glm::vec2 bottom_left, float height_px);
void end_batch();

FontBatchRenderer(FontBatchRenderer&& other)
: _m(std::move(other._m)) { }

private:
void load_text_into_vb(const std::string_view& text, glm::vec2 bottom_left, float height_px);

Expand All @@ -26,17 +30,21 @@ namespace Renderer {
glm::vec2 uv_coord;
using VBL = Core::VertexBufferLayout<glm::vec2, glm::vec2>;
};

std::optional<BatchConfig> _current_batch_config = std::nullopt;
std::vector<Vertex> _current_batch_vertices = {};

glm::vec2 _glyph_dimensions = { 0, 0 };
glm::vec2 _atlas_dimensions = { 0, 0 };

Renderer::ResourceHandle<Core::Shader> _s;
Renderer::ResourceHandle<Core::Texture> _t;
Renderer::ResourceHandle<Core::VertexBuffer> _vb;
Renderer::ResourceHandle<Core::IndexBuffer> _ib;
Renderer::ResourceHandle<Core::VertexArray> _va;

struct M {
std::vector<Vertex> current_batch_vertices;
std::optional<BatchConfig> current_batch_config;

Media::FontAtlas font_atlas;

Renderer::ResourceHandle<Core::Shader> s;
Renderer::ResourceHandle<Core::Texture> t;
Renderer::ResourceHandle<Core::VertexBuffer> vb;
Renderer::ResourceHandle<Core::IndexBuffer> ib;
Renderer::ResourceHandle<Core::VertexArray> va;
} _m;

explicit FontBatchRenderer(M&& m)
: _m(std::move(m)) { }
};
}
42 changes: 0 additions & 42 deletions code/Engine/include/Renderer/FontRenderer.hpp

This file was deleted.

1 change: 0 additions & 1 deletion code/Engine/include/Renderer/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,5 @@ namespace Renderer {

#include "Renderer/ResourceHandle.hpp"
#include "Renderer/ResourceManager.hpp"
#include "Renderer/FontRenderer.hpp"
#include "Renderer/FontBatchRenderer.hpp"
#include "Renderer/InstanceRenderer.hpp"
2 changes: 1 addition & 1 deletion code/Engine/src/App/AppRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ auto AppRenderer::add_texture(Media::Image& image) noexcept -> Utily::Result<Tex
return result.error();
}

if (auto result = texture.upload_image(image, Core::Texture::Filter::smooth, false); result.has_error()) {
if (auto result = texture.upload_image(image, Core::Texture::Filter::smooth); result.has_error()) {
return result.error();
}
return TextureId { static_cast<std::ptrdiff_t>(id) };
Expand Down
24 changes: 7 additions & 17 deletions code/Engine/src/Core/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Core {
, _id(std::exchange(other._id, std::nullopt))
, _texture_unit_index(std::exchange(other._texture_unit_index, std::nullopt)) { }

auto getUsableTextureUnit() noexcept
auto get_usable_texture_unit() noexcept
-> Utily::Result<std::tuple<std::ptrdiff_t, TextureUnit*>, Utily::Error> {
if (!texture_units().size()) {
// TODO collect analytics about how many texture slots.
Expand Down Expand Up @@ -63,9 +63,8 @@ namespace Core {
}

auto Texture::upload_image(
Media::Image& image,
Filter filter,
bool offload_image_on_success) noexcept
const Media::Image& image,
Filter filter) noexcept
-> Utily::Result<void, Utily::Error> {
Core::DebugOpRecorder::instance().push("Core::Texture", "upload_image()");
Profiler::Timer timer("Core::Texture::upload_image()", { "rendering" });
Expand All @@ -90,9 +89,9 @@ namespace Core {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

int32_t bytes_per_pixel = 4;
uint32_t gl_format = GL_RGBA8;
uint32_t gl_format = GL_RGBA;

if (image.format() == Media::ColourFormat::greyscale) {
if (image.format() == Media::Image::InternalFormat::greyscale) {
bytes_per_pixel = 1;
gl_format = GL_RED;
} else {
Expand All @@ -102,17 +101,8 @@ namespace Core {
const void* img_data = reinterpret_cast<const void*>(image.raw_bytes().data());
glPixelStorei(GL_UNPACK_ALIGNMENT, bytes_per_pixel);

glTexImage2D(GL_TEXTURE_2D, 0, (GLint)image.format(), image.dimensions().x, image.dimensions().y, 0, gl_format, GL_UNSIGNED_BYTE, img_data);
glTexImage2D(GL_TEXTURE_2D, 0, (GLint)image.opengl_format(), image.dimensions().x, image.dimensions().y, 0, gl_format, GL_UNSIGNED_BYTE, img_data);

if (offload_image_on_success) {
glFinish();
image.stop();
}
if constexpr (!Config::SKIP_IMAGE_TEXTURE_FENCING) {
auto fence = Core::Fence {};
fence.init();
image.add_fence(std::move(fence));
}
return {};
}

Expand All @@ -133,7 +123,7 @@ namespace Core {
_texture_unit_index = std::nullopt;
}

auto result = getUsableTextureUnit();
auto result = get_usable_texture_unit();
if (result.has_error()) {
return result.error();
}
Expand Down
Loading

0 comments on commit c9b1ba2

Please sign in to comment.