Add Text rendering
- Add FreeType as dependency - Add MsdfGen as dependency - Add MsdfAtlasGen as dependency
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
#include "copium/core/Application.h"
|
||||
|
||||
#include "copium/asset/AssetManager.h"
|
||||
#include "copium/core/Vulkan.h"
|
||||
#include "copium/event/EventDispatcher.h"
|
||||
#include "copium/event/MouseMoveEvent.h"
|
||||
#include "copium/event/MouseScrollEvent.h"
|
||||
#include "copium/event/MousePressEvent.h"
|
||||
#include "copium/event/KeyPressEvent.h"
|
||||
#include "copium/event/MouseMoveEvent.h"
|
||||
#include "copium/event/MousePressEvent.h"
|
||||
#include "copium/event/MouseScrollEvent.h"
|
||||
#include "copium/event/WindowFocusEvent.h"
|
||||
#include "copium/event/WindowResizeEvent.h"
|
||||
#include "copium/mesh/Vertex.h"
|
||||
#include "copium/mesh/VertexPassthrough.h"
|
||||
#include "copium/asset/AssetManager.h"
|
||||
#include "copium/sampler/Font.h"
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
@@ -60,6 +61,7 @@ namespace Copium
|
||||
vkDeviceWaitIdle(Vulkan::GetDevice());
|
||||
AssetManager::UnloadAsset(texture2D);
|
||||
AssetManager::UnloadAsset(texture2D2);
|
||||
AssetManager::UnloadAsset(font);
|
||||
AssetManager::UnloadAsset(graphicsPipeline);
|
||||
AssetManager::UnloadAsset(graphicsPipelinePassthrough);
|
||||
AssetManager::UnloadAsset(framebuffer);
|
||||
@@ -68,6 +70,8 @@ namespace Copium
|
||||
|
||||
bool Application::Update()
|
||||
{
|
||||
static Copium::Timer timer;
|
||||
|
||||
if (!Vulkan::GetSwapChain().BeginPresent())
|
||||
return true;
|
||||
|
||||
@@ -75,6 +79,14 @@ namespace Copium
|
||||
Vulkan::GetSwapChain().SubmitToGraphicsQueue(*commandBuffer);
|
||||
|
||||
Vulkan::GetSwapChain().EndPresent();
|
||||
if (timer.Elapsed() >= 1.0)
|
||||
{
|
||||
fps = frameCounter;
|
||||
frameCounter = 0;
|
||||
timer.Start(); // Not quite accurate since the elapsed time might me 1.1, then we lose 0.1 precision
|
||||
}
|
||||
frameCounter++;
|
||||
|
||||
return !glfwWindowShouldClose(Vulkan::GetWindow().GetWindow());
|
||||
}
|
||||
|
||||
@@ -93,7 +105,10 @@ namespace Copium
|
||||
case EventType::MouseMove:
|
||||
{
|
||||
const MouseMoveEvent& mouseMoveEvent = static_cast<const MouseMoveEvent&>(event);
|
||||
mousePos = {mouseMoveEvent.GetPos().x / Vulkan::GetSwapChain().GetExtent().width, mouseMoveEvent.GetPos().y / Vulkan::GetSwapChain().GetExtent().height};
|
||||
|
||||
float aspect = Vulkan::GetSwapChain().GetExtent().width / (float)Vulkan::GetSwapChain().GetExtent().height;
|
||||
mousePos = {(mouseMoveEvent.GetPos().x / Vulkan::GetSwapChain().GetExtent().width - 0.5) * 2.0 * aspect,
|
||||
-(mouseMoveEvent.GetPos().y / Vulkan::GetSwapChain().GetExtent().height - 0.5) * 2.0};
|
||||
|
||||
return EventResult::Continue;
|
||||
}
|
||||
@@ -144,6 +159,7 @@ namespace Copium
|
||||
{
|
||||
texture2D = AssetManager::LoadAsset<Texture2D>("fox.meta");
|
||||
texture2D2 = AssetManager::LoadAsset<Texture2D>("fox2.meta");
|
||||
font = AssetManager::LoadAsset<Font>("font.meta");
|
||||
}
|
||||
|
||||
void Application::InitializeDescriptorSets()
|
||||
@@ -202,9 +218,12 @@ namespace Copium
|
||||
renderer->Quad(glm::vec2{-1 + x * 0.2 + 0.05, -1 + y * 0.2 + 0.05}, glm::vec2{0.1, 0.1}, glm::vec3{x * 0.1, y * 0.1, 1.0});
|
||||
}
|
||||
}
|
||||
renderer->Quad(glm::vec2{-0.9, -0.4}, glm::vec2{0.8, 0.8}, AssetManager::GetAsset<Texture2D>(texture2D));
|
||||
renderer->Quad(glm::vec2{ 0.1, -0.4}, glm::vec2{0.8, 0.8}, AssetManager::GetAsset<Texture2D>(texture2D2));
|
||||
renderer->Quad(mousePos, glm::vec2{0.8, 0.8}, AssetManager::GetAsset<Texture2D>(texture2D2));
|
||||
float aspect = fb.GetWidth() / (float)fb.GetHeight();
|
||||
renderer->Quad(glm::vec2{-0.8, -0.4}, glm::vec2{0.8, 0.8}, AssetManager::GetAsset<Texture2D>(texture2D));
|
||||
renderer->Quad(glm::vec2{ 0.1, -0.4}, glm::vec2{0.8, 0.8}, AssetManager::GetAsset<Font>(font));
|
||||
renderer->Quad(mousePos - glm::vec2(0.1), glm::vec2{0.2}, AssetManager::GetAsset<Texture2D>(texture2D2));
|
||||
std::string s = std::to_string(fps) + " fps";
|
||||
renderer->Text(s, glm::vec2{-aspect + 0.01, 0.94}, AssetManager::GetAsset<Font>(font), 0.06, glm::vec3{0.3, 0.2, 0.8});
|
||||
renderer->End();
|
||||
|
||||
fb.Unbind(*commandBuffer);
|
||||
@@ -230,6 +249,7 @@ namespace Copium
|
||||
float time = startTimer.Elapsed();
|
||||
Framebuffer& fb = AssetManager::GetAsset<Framebuffer>(framebuffer);
|
||||
float aspect = fb.GetWidth() / (float)fb.GetHeight();
|
||||
time = 0;
|
||||
|
||||
{
|
||||
glm::mat4 projection = glm::perspective(glm::radians(45.0f), aspect, 0.1f, 10.0f);
|
||||
@@ -245,8 +265,9 @@ namespace Copium
|
||||
|
||||
{
|
||||
UniformBuffer& uniformBuffer = descriptorSetRenderer->GetUniformBuffer("ubo");
|
||||
uniformBuffer.Set("projection", glm::ortho(-aspect, aspect, -1.0f, 1.0f));
|
||||
uniformBuffer.Set("view", glm::translate(glm::mat4(1), glm::vec3(0.1 * glm::sin(4 * time), 0.1 * glm::cos(4 * time), 0.0)));
|
||||
uniformBuffer.Set("projection", glm::ortho(-aspect, aspect, 1.0f, -1.0f));
|
||||
// uniformBuffer.Set("view", glm::translate(glm::mat4(1), glm::vec3(0.1 * glm::sin(4 * time), 0.1 * glm::cos(4 * time), 0.0)));
|
||||
uniformBuffer.Set("view", glm::mat4(1));
|
||||
uniformBuffer.Update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Copium
|
||||
AssetHandle framebuffer;
|
||||
AssetHandle texture2D;
|
||||
AssetHandle texture2D2;
|
||||
AssetHandle font;
|
||||
AssetHandle graphicsPipeline;
|
||||
AssetHandle graphicsPipelinePassthrough;
|
||||
std::unique_ptr<DescriptorPool> descriptorPool;
|
||||
@@ -28,7 +29,10 @@ namespace Copium
|
||||
std::unique_ptr<Mesh> mesh;
|
||||
std::unique_ptr<Mesh> meshPassthrough;
|
||||
std::unique_ptr<CommandBuffer> commandBuffer;
|
||||
|
||||
glm::vec2 mousePos;
|
||||
int fps;
|
||||
int frameCounter;
|
||||
|
||||
public:
|
||||
Application();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "copium/asset/AssetManager.h"
|
||||
#include "copium/sampler/Texture2D.h"
|
||||
#include "copium/sampler/ColorAttachment.h"
|
||||
#include "copium/sampler/Font.h"
|
||||
#include "copium/pipeline/Pipeline.h"
|
||||
#include "copium/buffer/Framebuffer.h"
|
||||
|
||||
@@ -24,6 +25,7 @@ namespace Copium
|
||||
AssetManager::RegisterAssetType<ColorAttachment>("RenderTexture");
|
||||
AssetManager::RegisterAssetType<Pipeline>("Pipeline");
|
||||
AssetManager::RegisterAssetType<Framebuffer>("Framebuffer");
|
||||
AssetManager::RegisterAssetType<Font>("Font");
|
||||
|
||||
// TODO: Make the working directory always be relative to the assets folder
|
||||
// By looking at where the executable is, since that should always be in the bin folder (it currently isn't though)
|
||||
|
||||
@@ -13,19 +13,10 @@ int main(int argc, char** argv)
|
||||
Copium::Vulkan::Initialize();
|
||||
{
|
||||
Copium::Application application;
|
||||
Copium::Timer timer;
|
||||
int frames = 0;
|
||||
while (application.Update())
|
||||
{
|
||||
glfwPollEvents();
|
||||
Copium::EventDispatcher::Dispatch();
|
||||
if (timer.Elapsed() >= 1.0)
|
||||
{
|
||||
CP_DEBUG("%d fps", frames);
|
||||
frames = 0;
|
||||
timer.Start();
|
||||
}
|
||||
frames++;
|
||||
}
|
||||
}
|
||||
Copium::Vulkan::Destroy();
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Copium
|
||||
{
|
||||
creator.SetVertexDescriptor(RendererVertex::GetDescriptor());
|
||||
creator.SetDepthTest(false);
|
||||
creator.SetBlending(true);
|
||||
}
|
||||
else if (type == "Passthrough")
|
||||
{
|
||||
@@ -196,7 +197,7 @@ namespace Copium
|
||||
depthStencilCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
depthStencilCreateInfo.depthTestEnable = creator.depthTest ? VK_TRUE : VK_FALSE;
|
||||
depthStencilCreateInfo.depthWriteEnable = creator.depthTest ? VK_TRUE : VK_FALSE;
|
||||
depthStencilCreateInfo.depthCompareOp = VK_COMPARE_OP_LESS;
|
||||
depthStencilCreateInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||
depthStencilCreateInfo.depthBoundsTestEnable = VK_FALSE;
|
||||
depthStencilCreateInfo.minDepthBounds = 0.0f;
|
||||
depthStencilCreateInfo.maxDepthBounds = 1.0f;
|
||||
@@ -210,9 +211,9 @@ namespace Copium
|
||||
VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT |
|
||||
VK_COLOR_COMPONENT_A_BIT;
|
||||
colorBlendAttachment.blendEnable = VK_FALSE;
|
||||
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
colorBlendAttachment.blendEnable = creator.blending ? VK_TRUE : VK_FALSE;
|
||||
colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
|
||||
@@ -38,6 +38,11 @@ namespace Copium
|
||||
this->depthTest = depthTest;
|
||||
}
|
||||
|
||||
void PipelineCreator::SetBlending(bool blending)
|
||||
{
|
||||
this->blending = blending;
|
||||
}
|
||||
|
||||
void PipelineCreator::AddShaderDescription()
|
||||
{
|
||||
for (auto& binding : shaderReflector.bindings)
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Copium
|
||||
VkFrontFace frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
bool depthTest = true;
|
||||
bool blending = false;
|
||||
|
||||
public:
|
||||
PipelineCreator(VkRenderPass renderPass, const std::string& vertexShader, const std::string& fragmentShader);
|
||||
@@ -42,6 +43,7 @@ namespace Copium
|
||||
void SetCullMode(VkCullModeFlags flags);
|
||||
void SetCullFrontFace(VkFrontFace cullFrontFace);
|
||||
void SetDepthTest(bool depthTest);
|
||||
void SetBlending(bool blending);
|
||||
private:
|
||||
void AddShaderDescription();
|
||||
static VkDescriptorType GetDescriptorType(BindingType type);
|
||||
|
||||
@@ -31,10 +31,10 @@ namespace Copium
|
||||
void Renderer::Quad(const glm::vec2& pos, const glm::vec2& size, const glm::vec3& color)
|
||||
{
|
||||
AllocateQuad();
|
||||
AddVertex(glm::vec2{pos.x, pos.y + size.y}, color, -1, glm::vec2{0, 0});
|
||||
AddVertex(pos + size, color, -1, glm::vec2{0, 0});
|
||||
AddVertex(glm::vec2{pos.x + size.x, pos.y}, color, -1, glm::vec2{0, 0});
|
||||
AddVertex(pos, color, -1, glm::vec2{0, 0});
|
||||
AddVertex(pos, color, -1, glm::vec2{0, 0}, RendererVertex::TYPE_QUAD);
|
||||
AddVertex(glm::vec2{pos.x + size.x, pos.y}, color, -1, glm::vec2{0, 0}, RendererVertex::TYPE_QUAD);
|
||||
AddVertex(pos + size, color, -1, glm::vec2{0, 0}, RendererVertex::TYPE_QUAD);
|
||||
AddVertex(glm::vec2{pos.x, pos.y + size.y}, color, -1, glm::vec2{0, 0}, RendererVertex::TYPE_QUAD);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,19 +42,55 @@ namespace Copium
|
||||
{
|
||||
AllocateQuad();
|
||||
int texIndex = AllocateSampler(sampler);
|
||||
AddVertex(glm::vec2{pos.x, pos.y + size.y}, glm::vec3{1, 1, 1}, texIndex, glm::vec2{texCoord1.x, texCoord2.y});
|
||||
AddVertex(pos + size, glm::vec3{1,1,1}, texIndex, texCoord2);
|
||||
AddVertex(glm::vec2{pos.x + size.x, pos.y}, glm::vec3{1, 1, 1}, texIndex, glm::vec2{texCoord2.x, texCoord1.y});
|
||||
AddVertex(pos, glm::vec3{1,1,1}, texIndex, texCoord1);
|
||||
AddVertex(pos, glm::vec3{1,1,1}, texIndex, texCoord1, RendererVertex::TYPE_QUAD);
|
||||
AddVertex(glm::vec2{pos.x + size.x, pos.y}, glm::vec3{1, 1, 1}, texIndex, glm::vec2{texCoord2.x, texCoord1.y}, RendererVertex::TYPE_QUAD);
|
||||
AddVertex(pos + size, glm::vec3{1,1,1}, texIndex, texCoord2, RendererVertex::TYPE_QUAD);
|
||||
AddVertex(glm::vec2{pos.x, pos.y + size.y}, glm::vec3{1, 1, 1}, texIndex, glm::vec2{texCoord1.x, texCoord2.y}, RendererVertex::TYPE_QUAD);
|
||||
}
|
||||
|
||||
void Renderer::AddVertex(const glm::vec2& position, const glm::vec3& color, int texindex, const glm::vec2& texCoord)
|
||||
glm::vec2 Renderer::Text(const std::string& str, const glm::vec2& position, const Font& font, float size, const glm::vec3& color)
|
||||
{
|
||||
glm::vec2 offset = position;
|
||||
for (char c : str)
|
||||
{
|
||||
if(c == ' ')
|
||||
{
|
||||
const Glyph& glyph = font.GetGlyph(c);
|
||||
offset.x += glyph.advance * size;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\t')
|
||||
{
|
||||
const Glyph& glyph = font.GetGlyph(' ');
|
||||
offset.x += glyph.advance * size * 4;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
offset.y -= font.GetLineHeight() * size;
|
||||
offset.x = position.x;
|
||||
continue;
|
||||
}
|
||||
const Glyph& glyph = font.GetGlyph(c);
|
||||
AllocateQuad();
|
||||
int texIndex = AllocateSampler(font);
|
||||
AddVertex(offset + glm::vec2{glyph.pos1.x * size, glyph.pos1.y * size}, color, texIndex, glyph.texCoord1, RendererVertex::TYPE_TEXT);
|
||||
AddVertex(offset + glm::vec2{glyph.pos2.x * size, glyph.pos1.y * size}, color, texIndex, glm::vec2{glyph.texCoord2.x, glyph.texCoord1.y}, RendererVertex::TYPE_TEXT);
|
||||
AddVertex(offset + glm::vec2{glyph.pos2.x * size, glyph.pos2.y * size}, color, texIndex, glyph.texCoord2, RendererVertex::TYPE_TEXT);
|
||||
AddVertex(offset + glm::vec2{glyph.pos1.x * size, glyph.pos2.y * size}, color, texIndex, glm::vec2{glyph.texCoord1.x, glyph.texCoord2.y}, RendererVertex::TYPE_TEXT);
|
||||
offset.x += glyph.advance * size;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
void Renderer::AddVertex(const glm::vec2& position, const glm::vec3& color, int texindex, const glm::vec2& texCoord, int type)
|
||||
{
|
||||
RendererVertex* vertex = (RendererVertex*)mappedVertexBuffer;
|
||||
vertex->position = position;
|
||||
vertex->color = color;
|
||||
vertex->texCoord = texCoord;
|
||||
vertex->texIndex = texindex;
|
||||
vertex->type = type;
|
||||
mappedVertexBuffer = (RendererVertex*)mappedVertexBuffer + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "copium/pipeline/Pipeline.h"
|
||||
#include "copium/renderer/Batch.h"
|
||||
#include "copium/sampler/Texture2D.h"
|
||||
#include "copium/sampler/Font.h"
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
@@ -37,6 +38,8 @@ namespace Copium
|
||||
|
||||
void Quad(const glm::vec2& from, const glm::vec2& to, const glm::vec3& color = glm::vec3{1, 1, 1});
|
||||
void Quad(const glm::vec2& from, const glm::vec2& to, const Sampler& sampler, const glm::vec2& texCoord1 = glm::vec2{0, 0}, const glm::vec2& texCoord2 = glm::vec2{1, 1});
|
||||
// Returns the position where the text rendering ended
|
||||
glm::vec2 Text(const std::string& str, const glm::vec2& position, const Font& font, float size, const glm::vec3& color = glm::vec3(1, 1, 1));
|
||||
|
||||
void Begin(CommandBuffer& commandBuffer);
|
||||
void End();
|
||||
@@ -52,6 +55,6 @@ namespace Copium
|
||||
void Flush();
|
||||
void NextBatch();
|
||||
|
||||
void AddVertex(const glm::vec2& position, const glm::vec3& color, int texindex, const glm::vec2& texCoord);
|
||||
void AddVertex(const glm::vec2& position, const glm::vec3& color, int texindex, const glm::vec2& texCoord, int type);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Copium
|
||||
descriptor.AddAttribute(0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(RendererVertex, color), sizeof(RendererVertex));
|
||||
descriptor.AddAttribute(0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(RendererVertex, texCoord), sizeof(RendererVertex));
|
||||
descriptor.AddAttribute(0, 3, VK_FORMAT_R8_SINT, offsetof(RendererVertex, texIndex), sizeof(RendererVertex));
|
||||
descriptor.AddAttribute(0, 4, VK_FORMAT_R8_SINT, offsetof(RendererVertex, type), sizeof(RendererVertex));
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,13 @@ namespace Copium
|
||||
{
|
||||
struct RendererVertex
|
||||
{
|
||||
static const int TYPE_QUAD = 0;
|
||||
static const int TYPE_TEXT = 1;
|
||||
glm::vec2 position;
|
||||
glm::vec3 color;
|
||||
glm::vec2 texCoord;
|
||||
int8_t texIndex;
|
||||
int8_t type = TYPE_QUAD; // TODO: Should maybe have different Renderers for quad vs text instead of a flag
|
||||
|
||||
static VertexDescriptor GetDescriptor();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "copium/sampler/Font.h"
|
||||
|
||||
#include "copium/buffer/Buffer.h"
|
||||
#include "copium/core/Vulkan.h"
|
||||
#include "copium/sampler/Image.h"
|
||||
|
||||
#define MSDF_ATLAS_PUBLIC
|
||||
#define MSDFGEN_PUBLIC
|
||||
#include <msdf-atlas-gen/msdf-atlas-gen.h>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
Font::Font(const MetaFile& metaFile)
|
||||
{
|
||||
msdfgen::FreetypeHandle* ft = msdfgen::initializeFreetype();
|
||||
CP_ASSERT(ft, "Failed to initialize FreeType"); // TODO: Move to Vulkan singleton class?
|
||||
std::string fontPath = metaFile.GetMetaClass("Font").GetValue("filepath");
|
||||
msdfgen::FontHandle* font = msdfgen::loadFont(ft, fontPath.c_str());
|
||||
CP_ASSERT(font, "Failed to initialize font: %s", fontPath.c_str());
|
||||
|
||||
std::vector<msdf_atlas::GlyphGeometry> glyphs;
|
||||
msdf_atlas::FontGeometry fontGeometry(&glyphs);
|
||||
fontGeometry.loadCharset(font, 1.0, msdf_atlas::Charset::ASCII);
|
||||
const double maxCornerAngle = 3.0;
|
||||
for (msdf_atlas::GlyphGeometry& glyph : glyphs)
|
||||
{
|
||||
glyph.edgeColoring(&msdfgen::edgeColoringInkTrap, maxCornerAngle, 0);
|
||||
}
|
||||
msdf_atlas::TightAtlasPacker packer;
|
||||
packer.setDimensionsConstraint(msdf_atlas::TightAtlasPacker::DimensionsConstraint::SQUARE);
|
||||
packer.setMinimumScale(64.0);
|
||||
packer.setPixelRange(2.0);
|
||||
packer.setMiterLimit(1.0);
|
||||
packer.setPadding(2);
|
||||
packer.pack(glyphs.data(), glyphs.size());
|
||||
|
||||
int width = 0, height = 0;
|
||||
packer.getDimensions(width, height);
|
||||
|
||||
msdf_atlas::ImmediateAtlasGenerator<float, 3, msdf_atlas::msdfGenerator, msdf_atlas::BitmapAtlasStorage<msdf_atlas::byte, 3>> generator(width, height);
|
||||
msdf_atlas::GeneratorAttributes attributes;
|
||||
generator.setAttributes(attributes);
|
||||
generator.setThreadCount(4);
|
||||
generator.generate(glyphs.data(), glyphs.size());
|
||||
|
||||
msdf_atlas::BitmapAtlasStorage<msdf_atlas::byte, 3> pixels = generator.atlasStorage();
|
||||
std::vector<uint8_t> data;
|
||||
data.resize(width * height * 4);
|
||||
msdfgen::Bitmap<msdf_atlas::byte, 3> bitmap = (msdfgen::Bitmap<msdf_atlas::byte, 3>)pixels;
|
||||
for (int i = 0; i < width * height; i++)
|
||||
{
|
||||
data[i * 4] = bitmap[i * 3];
|
||||
data[i * 4 + 1] = bitmap[i * 3 + 1];
|
||||
data[i * 4 + 2] = bitmap[i * 3 + 2];
|
||||
data[i * 4 + 3] = 255;
|
||||
}
|
||||
InitializeTextureImageFromData(data.data(), width, height);
|
||||
|
||||
for (msdf_atlas::GlyphGeometry& glyphGeom : glyphs)
|
||||
{
|
||||
Glyph glyph;
|
||||
glyph.advance = glyphGeom.getAdvance();
|
||||
double l, b, r, t;
|
||||
glyphGeom.getQuadPlaneBounds(l, b, r, t);
|
||||
glyph.pos1 = glm::vec2{l, b};
|
||||
glyph.pos2 = glm::vec2{r, t};
|
||||
glyphGeom.getQuadAtlasBounds(l, b, r, t);
|
||||
glyph.texCoord1 = glm::vec2{l / width, b / height};
|
||||
glyph.texCoord2 = glm::vec2{r / width, t / height};
|
||||
this->glyphs.emplace((char)glyphGeom.getCodepoint(), glyph);
|
||||
}
|
||||
lineHeight = fontGeometry.getMetrics().lineHeight;
|
||||
|
||||
msdfgen::destroyFont(font);
|
||||
msdfgen::deinitializeFreetype(ft);
|
||||
}
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
vkDestroyImage(Vulkan::GetDevice(), image, nullptr);
|
||||
vkFreeMemory(Vulkan::GetDevice(), imageMemory, nullptr);
|
||||
vkDestroyImageView(Vulkan::GetDevice(), imageView, nullptr);
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo Font::GetDescriptorImageInfo(int index) const
|
||||
{
|
||||
VkDescriptorImageInfo imageInfo{};
|
||||
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
imageInfo.sampler = sampler;
|
||||
imageInfo.imageView = imageView;
|
||||
|
||||
return imageInfo;
|
||||
}
|
||||
|
||||
const Glyph& Font::GetGlyph(char c) const
|
||||
{
|
||||
CP_ASSERT(glyphs.find(c) != glyphs.end(), "Glyph not found: %c", c);
|
||||
return glyphs.find(c)->second;
|
||||
}
|
||||
|
||||
float Font::GetLineHeight() const
|
||||
{
|
||||
return lineHeight;
|
||||
}
|
||||
|
||||
void Font::InitializeTextureImageFromData(const uint8_t* rgbaData, int width, int height)
|
||||
{
|
||||
VkDeviceSize bufferSize = width * height * 4;
|
||||
Buffer stagingBuffer{VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1};
|
||||
void* data = stagingBuffer.Map();
|
||||
memcpy(data, rgbaData, bufferSize);
|
||||
stagingBuffer.Unmap();
|
||||
|
||||
Image::InitializeImage(width, height, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &image, &imageMemory);
|
||||
Image::TransitionImageLayout(image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
Image::CopyBufferToImage(stagingBuffer, image, width, height);
|
||||
Image::TransitionImageLayout(image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
imageView = Image::InitializeImageView(image, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/sampler/Sampler.h"
|
||||
#include "copium/sampler/Glyph.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class Font : public Sampler
|
||||
{
|
||||
CP_DELETE_COPY_AND_MOVE_CTOR(Font);
|
||||
struct GlyphData
|
||||
{
|
||||
|
||||
};
|
||||
private:
|
||||
VkImage image;
|
||||
VkDeviceMemory imageMemory;
|
||||
VkImageView imageView;
|
||||
|
||||
std::map<char, Glyph> glyphs;
|
||||
float lineHeight;
|
||||
public:
|
||||
Font(const MetaFile& metaFile);
|
||||
~Font() override;
|
||||
|
||||
VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override;
|
||||
|
||||
const Glyph& GetGlyph(char c) const;
|
||||
float GetLineHeight() const;
|
||||
private:
|
||||
void InitializeTextureImageFromFile(const std::string& filename);
|
||||
void InitializeTextureImageFromData(const uint8_t* rgbaData, int width, int height);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
struct Glyph
|
||||
{
|
||||
float advance;
|
||||
glm::vec2 pos1;
|
||||
glm::vec2 pos2;
|
||||
glm::vec2 texCoord1;
|
||||
glm::vec2 texCoord2;
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "copium/sampler/Texture2D.h"
|
||||
|
||||
#include "copium/core/Vulkan.h"
|
||||
#include "copium/sampler/Image.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb/stb_image.h>
|
||||
@@ -19,7 +20,7 @@ namespace Copium
|
||||
Texture2D::Texture2D(const std::vector<uint8_t>& rgbaData, int width, int height)
|
||||
{
|
||||
CP_ASSERT(rgbaData.size() == width * height * 4, "rgbaData has invalid size, should be equal to width * height * 4 (%d) actually is %d", width * height * 4, rgbaData.size());
|
||||
InitializeTextureImageFromData((void*)rgbaData.data(), width, height);
|
||||
InitializeTextureImageFromData(rgbaData.data(), width, height);
|
||||
}
|
||||
|
||||
Texture2D::~Texture2D()
|
||||
@@ -41,6 +42,7 @@ namespace Copium
|
||||
|
||||
void Texture2D::InitializeTextureImageFromFile(const std::string& filename)
|
||||
{
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
int texChannels;
|
||||
@@ -48,12 +50,12 @@ namespace Copium
|
||||
|
||||
CP_ASSERT(pixels, "Failed to load texture image");
|
||||
|
||||
InitializeTextureImageFromData((void*)pixels, texWidth, texHeight);
|
||||
InitializeTextureImageFromData(pixels, texWidth, texHeight);
|
||||
|
||||
stbi_image_free(pixels);
|
||||
}
|
||||
|
||||
void Texture2D::InitializeTextureImageFromData(void* rgbaData, int width, int height)
|
||||
void Texture2D::InitializeTextureImageFromData(const uint8_t* rgbaData, int width, int height)
|
||||
{
|
||||
VkDeviceSize bufferSize = width * height * 4;
|
||||
Buffer stagingBuffer{VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, bufferSize, 1};
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/buffer/CommandBufferScoped.h"
|
||||
#include "copium/sampler/Image.h"
|
||||
#include "copium/sampler/Sampler.h"
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class Texture2D final : public Sampler
|
||||
@@ -24,6 +20,6 @@ namespace Copium
|
||||
VkDescriptorImageInfo GetDescriptorImageInfo(int index) const override;
|
||||
private:
|
||||
void InitializeTextureImageFromFile(const std::string& filename);
|
||||
void InitializeTextureImageFromData(void* rgbaData, int width, int height);
|
||||
void InitializeTextureImageFromData(const uint8_t* rgbaData, int width, int height);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user