diff --git a/SHADE_Engine/src/Assets/Asset Types/SHFontAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHFontAsset.h index 3f79547e..c2fcb20c 100644 --- a/SHADE_Engine/src/Assets/Asset Types/SHFontAsset.h +++ b/SHADE_Engine/src/Assets/Asset Types/SHFontAsset.h @@ -35,6 +35,7 @@ namespace SHADE //! The actual data of the atlas to go into the binary std::unique_ptr bitmapData; - + //! size of the bitmap + uint32_t bitmapSize; }; } diff --git a/SHADE_Engine/src/Assets/Libraries/Compilers/SHFontCompiler.cpp b/SHADE_Engine/src/Assets/Libraries/Compilers/SHFontCompiler.cpp index dc9a8c97..804ec994 100644 --- a/SHADE_Engine/src/Assets/Libraries/Compilers/SHFontCompiler.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Compilers/SHFontCompiler.cpp @@ -81,8 +81,12 @@ namespace SHADE fontAsset->glyphTransformations.push_back(newData); } + uint32_t bytesRequired = fontBitmap.width() * fontBitmap.height() * 3 * sizeof(float); + // copy data from bitmap to asset. Each channel is a 32 bit float and there are 3 channels. - fontAsset->bitmapData = std::make_unique(fontBitmap.width() * fontBitmap.height() * 3 * sizeof (float)); + fontAsset->bitmapData = std::make_unique(bytesRequired); + + fontAsset->bitmapSize = bytesRequired; } /***************************************************************************/ @@ -107,14 +111,19 @@ namespace SHADE // XQ I need your help for path manipulation to actually load the msdfgen::FontHandle here. Am I doing this correctly? fontHandle = msdfgen::loadFont(SHFreetypeInstance::GetFreetypeHandle(), path.string().c_str()); - // Compile a font asset - auto* fontAsset = CompileFontToMemory(fontHandle); + if (fontHandle) + { + // Compile a font asset + auto* fontAsset = CompileFontToMemory(fontHandle); - // No path to binary format - if (!fontAsset) - return {}; + // No path to binary format + if (!fontAsset) + return {}; - CompileFontToBinary(path, *fontAsset); + return CompileFontToBinary(path, *fontAsset); + } + + SHLOG_ERROR("Unable to open font file: {}", path.string()); return {}; } @@ -124,7 +133,7 @@ namespace SHADE \brief This function takes in a font handle and generates a font asset from it. - It first geneates an atlas and all relevant data before creating the + It first generates an atlas and all relevant data before creating the asset. \param fontHandle @@ -187,6 +196,24 @@ namespace SHADE return newAsset; } + /***************************************************************************/ + /*! + + \brief + After generating the asset we call this function to serialize the font + data into binary data. + + \param path + path to font file (?). + + \param asset + Asset to write. + + \return + Path the asset. + + */ + /***************************************************************************/ std::string SHFontCompiler::CompileFontToBinary(AssetPath path, SHFontAsset const& asset) noexcept { std::string newPath{ path.string() }; @@ -195,19 +222,28 @@ namespace SHADE std::ofstream file{ newPath, std::ios::binary | std::ios::out | std::ios::trunc }; - //file.write( - // reinterpret_cast(&data.shaderType), sizeof(uint8_t) - //); + uint32_t numGlyphs = asset.glyphTransformations.size(); - //size_t const byteCount = sizeof(uint32_t) * data.spirvBinary.size(); + // Write number of glyphs first + file.write(reinterpret_cast(&numGlyphs), sizeof (uint32_t)); - //file.write( - // reinterpret_cast(&byteCount), sizeof(size_t) - //); + for (uint32_t i = 0; i < numGlyphs; ++i) + { + auto const& [glyph, data] = asset.glyphTransformations[i]; + + // write the glyph first + file.write (reinterpret_cast(&glyph), sizeof (msdfgen::unicode_t)); + + // then write the data next to it + file.write (reinterpret_cast(&data), sizeof (SHMatrix)); + } + + // Write bytes required for bitmap + file.write(reinterpret_cast(asset.bitmapSize), sizeof (uint32_t)); + + // now we write the actual bitmap + file.write (reinterpret_cast(asset.bitmapData.get()), asset.bitmapSize); - //file.write( - // reinterpret_cast(data.spirvBinary.data()), byteCount - //); file.close(); diff --git a/SHADE_Engine/src/Assets/Libraries/Loaders/SHFontLoader.cpp b/SHADE_Engine/src/Assets/Libraries/Loaders/SHFontLoader.cpp index 93de789b..36482d09 100644 --- a/SHADE_Engine/src/Assets/Libraries/Loaders/SHFontLoader.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Loaders/SHFontLoader.cpp @@ -2,11 +2,50 @@ #include "SHFontLoader.h" #include "Assets/Asset Types/SHFontAsset.h" #include "Graphics/MiddleEnd/TextRendering/SHFreetypeInstance.h" +#include "msdf-atlas-gen/msdf-atlas-gen.h" + +#include +#include +#include +#include namespace SHADE { SHADE::SHAssetData* SHFontLoader::Load(AssetPath path) { + auto newFontAsset = new SHFontAsset(); + + std::ifstream file{ path.string(), std::ios::in | std::ios::binary }; + if (!file.is_open()) + { + SHLOG_ERROR("Unable to open compiled font file: {}", path.string()); + return nullptr; + } + + uint32_t numGlyphs = 0; + + // read how many glyphs we have + file.read (reinterpret_cast(&numGlyphs), sizeof (uint32_t)); + + newFontAsset->glyphTransformations.resize(numGlyphs); + for (uint32_t i = 0; i < numGlyphs; ++i) + { + // read the glyph + file.read(reinterpret_cast(&std::get<0>(newFontAsset->glyphTransformations[i])), sizeof(msdfgen::unicode_t)); + + // Read the data for the glyph + file.read(reinterpret_cast(&std::get<1>(newFontAsset->glyphTransformations[i])), sizeof(SHMatrix)); + } + + // Read bytes required for the bitmap + file.read(reinterpret_cast(&newFontAsset->bitmapSize), sizeof(uint32_t)); + + // Read the bitmap + newFontAsset->bitmapData = std::make_unique(newFontAsset->bitmapSize); + file.read (reinterpret_cast(newFontAsset->bitmapData.get()), newFontAsset->bitmapSize); + + file.close(); + return nullptr; } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRendererComponent.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRendererComponent.cpp new file mode 100644 index 00000000..e392e79c --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRendererComponent.cpp @@ -0,0 +1,69 @@ +#include "SHpch.h" +#include "SHTextRendererComponent.h" + +namespace SHADE +{ + + void SHTextRendererComponent::MakeDirty(void) noexcept + { + requiresRecompute = true; + } + + void SHTextRendererComponent::Clean(void) noexcept + { + requiresRecompute = false; + } + + /***************************************************************************/ + /*! + + \brief + On create the text has nothing. + + */ + /***************************************************************************/ + void SHTextRendererComponent::OnCreate(void) + { + text = ""; + requiresRecompute = true; + + // Default white color. + color = SHColour::WHITE; + } + + /***************************************************************************/ + /*! + + \brief + Sets the text to be rendered. + + \param newText + + + \return + + */ + /***************************************************************************/ + void SHTextRendererComponent::SetText(std::string_view newText) noexcept + { + text = newText; + MakeDirty(); + } + + /***************************************************************************/ + /*! + + \brief + Getter for the text required to render. + + \return + + + */ + /***************************************************************************/ + std::string const& SHTextRendererComponent::GetText(void) const noexcept + { + return text; + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRendererComponent.h b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRendererComponent.h new file mode 100644 index 00000000..0b36ac9b --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRendererComponent.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include "ECS_Base/Components/SHComponent.h" +#include "Math/SHColour.h" + +namespace SHADE +{ + class SHTextRendererComponent final : public SHComponent + { + private: + //! Text required to be rendered + std::string text; + + //! Color of the text + SHColour color; + + //! Requires to recompute the positions of each glyph/character + bool requiresRecompute; + + void MakeDirty (void) noexcept; + void Clean (void) noexcept; + + public: + void OnCreate(void) override final; + + /*-----------------------------------------------------------------------*/ + /* SETTERS AND GETTERS */ + /*-----------------------------------------------------------------------*/ + void SetText (std::string_view newText) noexcept; + std::string const& GetText (void) const noexcept; + + + }; +} + diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.cpp new file mode 100644 index 00000000..81f51ada --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.cpp @@ -0,0 +1,7 @@ +#include "SHpch.h" +#include "SHTextRenderingSubSystem.h" + +namespace SHADE +{ + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.h new file mode 100644 index 00000000..90879f9d --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Resource/SHHandle.h" + +namespace SHADE +{ + class SHVkLogicalDevice; + class SHVkDescriptorPool; + class SHVkDescriptorSetGroup; + class SHVkDescriptorSetLayout; + class SHVkBuffer; + class SHLightComponent; + class SHVkCommandBuffer; + + + class SHTextRenderingSubSystem + { + private: + + public: + void Init(Handle device, Handle descPool) noexcept; + void Run(uint32_t frameIndex) noexcept; + void Exit(void) noexcept; + + + }; +}