working text pipeline

This commit is contained in:
Kbz-8
2023-04-11 13:21:11 +02:00
parent 77d71adc1f
commit 026f83ca81
9 changed files with 217 additions and 96 deletions

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/07 16:40:09 by maldavid #+# #+# */
/* Updated: 2023/04/08 18:41:44 by maldavid ### ########.fr */
/* Updated: 2023/04/11 12:30:28 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -25,25 +25,6 @@ namespace mlx
Image::createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
Image::createSampler();
_color = 0xFFFFFFFF;
float red = (_color & 0x00FF0000) / 255;
float green = (_color & 0x0000FF00) / 255;
float blue = (_color & 0x000000FF) / 255;
std::vector<Vertex> vertexData = {
{{0, 0}, {red, green, blue, 1.f}, {0.0f, 0.0f}},
{{20, 0}, {red, green, blue, 1.f}, {1.0f, 0.0f}},
{{20, 20}, {red, green, blue, 1.f}, {1.0f, 1.0f}},
{{0, 20}, {red, green, blue, 1.f}, {0.0f, 1.0f}}
};
std::vector<uint16_t> indexData = { 0, 1, 2, 2, 3, 0 };
_vbo.create(sizeof(Vertex) * vertexData.size());
_vbo.setData(sizeof(Vertex) * vertexData.size(), vertexData.data());
_ibo.create(sizeof(uint16_t) * indexData.size(), indexData.data());
if(pixels != nullptr)
{
Buffer staging_buffer;
@@ -54,33 +35,17 @@ namespace mlx
}
}
void TextureAtlas::render(Renderer& renderer, int x, int y, std::array<glm::vec2, 4> pos, std::array<glm::vec2, 4> uv)
void TextureAtlas::render(Renderer& renderer, int x, int y, uint32_t ibo_size)
{
auto cmd = renderer.getActiveCmdBuffer().get();
float red = (_color & 0x00FF0000) / 255;
float green = (_color & 0x0000FF00) / 255;
float blue = (_color & 0x000000FF) / 255;
std::vector<Vertex> vertexData = {
{pos[0], {red, green, blue, 1.f}, uv[0]},
{pos[1], {red, green, blue, 1.f}, uv[1]},
{pos[2], {red, green, blue, 1.f}, uv[2]},
{pos[3], {red, green, blue, 1.f}, uv[3]}
};
_vbo.setData(sizeof(Vertex) * vertexData.size(), vertexData.data());
_vbo.bind(renderer);
_ibo.bind(renderer);
glm::vec2 translate(x, y);
vkCmdPushConstants(cmd, renderer.getPipeline().getPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(translate), &translate);
vkCmdDrawIndexed(cmd, static_cast<uint32_t>(_ibo.getSize() / sizeof(uint16_t)), 1, 0, 0, 0);
vkCmdDrawIndexed(cmd, ibo_size / sizeof(uint16_t), 1, 0, 0, 0);
}
void TextureAtlas::destroy() noexcept
{
Image::destroy();
_vbo.destroy();
_ibo.destroy();
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/07 16:36:33 by maldavid #+# #+# */
/* Updated: 2023/04/08 00:27:46 by maldavid ### ########.fr */
/* Updated: 2023/04/11 12:04:16 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -25,11 +25,9 @@ namespace mlx
TextureAtlas() = default;
void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format);
void render(class Renderer& renderer, int x, int y, std::array<glm::vec2, 4> pos, std::array<glm::vec2, 4> uv);
void render(class Renderer& renderer, int x, int y, uint32_t ibo_size);
void destroy() noexcept override;
inline void setColor(int color) noexcept { _color = color; }
inline void setDescriptor(DescriptorSet set) noexcept { _set = std::move(set); }
inline VkDescriptorSet getSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; }
inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, getImageView(), getSampler()); }
@@ -37,10 +35,7 @@ namespace mlx
~TextureAtlas() = default;
private:
VBO _vbo;
C_IBO _ibo;
DescriptorSet _set;
int _color;
};
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/25 11:59:07 by maldavid #+# #+# */
/* Updated: 2023/04/08 18:41:15 by maldavid ### ########.fr */
/* Updated: 2023/04/11 13:20:26 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -93,7 +93,7 @@ namespace mlx
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
info.magFilter = VK_FILTER_LINEAR;
info.minFilter = VK_FILTER_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/18 17:14:45 by maldavid #+# #+# */
/* Updated: 2023/04/03 14:23:46 by maldavid ### ########.fr */
/* Updated: 2023/04/11 12:33:33 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -41,6 +41,8 @@ namespace mlx
glm::vec4 color;
glm::vec2 uv;
Vertex(glm::vec2 _pos, glm::vec4 _color, glm::vec2 _uv) : pos(std::move(_pos)), color(std::move(_color)), uv(std::move(_uv)) {}
static VkVertexInputBindingDescription getBindingDescription()
{
VkVertexInputBindingDescription bindingDescription{};

66
src/renderer/text_library.cpp git.filemode.normal_file
View File

@@ -0,0 +1,66 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_library.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/10 11:59:57 by maldavid #+# #+# */
/* Updated: 2023/04/11 12:28:42 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <renderer/text_library.h>
#include <core/errors.h>
#include <renderer/renderer.h>
namespace mlx
{
void TextData::init(std::vector<Vertex> vbo_data, std::vector<uint16_t> ibo_data)
{
_vbo.create(sizeof(Vertex) * vbo_data.size(), vbo_data.data());
_ibo.create(sizeof(uint16_t) * ibo_data.size(), ibo_data.data());
}
void TextData::bind(Renderer& renderer) noexcept
{
_vbo.bind(renderer);
_ibo.bind(renderer);
}
void TextData::destroy() noexcept
{
_vbo.destroy();
_ibo.destroy();
}
std::shared_ptr<TextData> TextLibrary::getTextData(TextID id)
{
if(!_cache.count(id))
core::error::report(e_kind::fatal_error, "Text Library : wrong text ID '%d'", id);
return _cache[id];
}
TextID TextLibrary::addTextToLibrary(std::shared_ptr<TextData> text)
{
_cache[_current_id] = text;
_current_id++;
return _current_id - 1;
}
void TextLibrary::removeTextFromLibrary(TextID id)
{
if(_cache.count(id))
{
_cache[id]->destroy();
_cache.erase(id);
}
}
void TextLibrary::clearLibrary()
{
for(auto [id, text] : _cache)
text->destroy();
_cache.clear();
}
}

66
src/renderer/text_library.h git.filemode.normal_file
View File

@@ -0,0 +1,66 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* text_library.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/10 11:52:30 by maldavid #+# #+# */
/* Updated: 2023/04/11 12:28:08 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_TEXT_LIBRARY__
#define __MLX_TEXT_LIBRARY__
#include <renderer/buffers/vk_vbo.h>
#include <renderer/buffers/vk_ibo.h>
#include <string>
#include <unordered_map>
#include <memory>
#include <vector>
#include <cstdint>
namespace mlx
{
using TextID = uint32_t;
constexpr TextID nulltext = 0;
class TextData
{
public:
TextData() = default;
void init(std::vector<Vertex> vbo_data, std::vector<uint16_t> ibo_data);
void bind(class Renderer& renderer) noexcept;
inline uint32_t getIBOsize() noexcept { return _ibo.getSize(); }
void destroy() noexcept;
~TextData() = default;
private:
C_VBO _vbo;
C_IBO _ibo;
};
class TextLibrary
{
public:
TextLibrary() = default;
std::shared_ptr<TextData> getTextData(TextID id);
TextID addTextToLibrary(std::shared_ptr<TextData> text);
void removeTextFromLibrary(TextID id);
void clearLibrary();
~TextLibrary() = default;
private:
std::unordered_map<TextID, std::shared_ptr<TextData>> _cache;
TextID _current_id = 1;
};
}
#endif

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/06 16:41:13 by maldavid #+# #+# */
/* Updated: 2023/04/08 20:44:51 by maldavid ### ########.fr */
/* Updated: 2023/04/11 12:49:59 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -25,17 +25,53 @@ namespace mlx
{
uint8_t tmp_bitmap[512 * 512];
TextDrawData::TextDrawData(std::string text, int _color, int _x, int _y, TextLibrary& library, std::array<stbtt_bakedchar, 96>& cdata) : x(_x), y(_y), color(_color)
{
std::vector<Vertex> vertexData;
std::vector<uint16_t> indexData;
float stb_x = 0.0f;
float stb_y = 0.0f;
for(char c : text)
{
if(c < 32 || c > 127)
continue;
stbtt_aligned_quad q;
stbtt_GetBakedQuad(cdata.data(), 512, 512, c - 32, &stb_x, &stb_y, &q, 1);
std::size_t index = vertexData.size();
vertexData.emplace_back(glm::vec2{q.x0, q.y0}, glm::vec4{color & 0x00FF0000, color & 0x0000FF00, color & 0x000000FF, 0xFF}, glm::vec2{q.s0, q.t0});
vertexData.emplace_back(glm::vec2{q.x1, q.y0}, glm::vec4{color & 0x00FF0000, color & 0x0000FF00, color & 0x000000FF, 0xFF}, glm::vec2{q.s1, q.t0});
vertexData.emplace_back(glm::vec2{q.x1, q.y1}, glm::vec4{color & 0x00FF0000, color & 0x0000FF00, color & 0x000000FF, 0xFF}, glm::vec2{q.s1, q.t1});
vertexData.emplace_back(glm::vec2{q.x0, q.y1}, glm::vec4{color & 0x00FF0000, color & 0x0000FF00, color & 0x000000FF, 0xFF}, glm::vec2{q.s0, q.t1});
indexData.emplace_back(index + 0);
indexData.emplace_back(index + 1);
indexData.emplace_back(index + 2);
indexData.emplace_back(index + 2);
indexData.emplace_back(index + 3);
indexData.emplace_back(index + 0);
}
std::shared_ptr<TextData> text_data = std::make_shared<TextData>();
text_data->init(std::move(vertexData), std::move(indexData));
id = library.addTextToLibrary(text_data);
}
void TextPutPipeline::init(Renderer* renderer) noexcept
{
_renderer = renderer;
stbtt_BakeFontBitmap(opensans_regular_ttf, 0, 20.0f, tmp_bitmap, 512, 512, 32, 96, _cdata);
stbtt_BakeFontBitmap(opensans_regular_ttf, 0, 18.0f, tmp_bitmap, 512, 512, 32, 96, _cdata.data());
_atlas.create(tmp_bitmap, 512, 512, VK_FORMAT_R8_UNORM);
_atlas.setDescriptor(renderer->getFragDescriptorSet().duplicate());
}
void TextPutPipeline::put(int x, int y, int color, std::string str)
{
_drawlist.emplace(std::move(str), color, x, y);
_drawlist.emplace(std::move(str), color, x, y, _library, _cdata);
}
void TextPutPipeline::render()
@@ -43,39 +79,15 @@ namespace mlx
_atlas.updateSet(0);
for(auto& draw : _drawlist)
{
_atlas.setColor(draw.color);
int i = 0;
for(char c : draw.text)
{
if(c < 32 || c > 127)
continue;
stbtt_aligned_quad q;
float null_x = 0.0f;
float null_y = 0.0f;
stbtt_GetBakedQuad(_cdata, 512, 512, c - 32, &null_x, &null_y, &q, 1);
std::array<glm::vec2, 4> pos = {
glm::vec2{q.x0, q.y0},
glm::vec2{q.x1, q.y0},
glm::vec2{q.x1, q.y1},
glm::vec2{q.x0, q.y1}
};
std::array<glm::vec2, 4> uv = {
glm::vec2{q.s0, q.t0},
glm::vec2{q.s1, q.t0},
glm::vec2{q.s1, q.t1},
glm::vec2{q.s0, q.t1}
};
_atlas.render(*_renderer, draw.x, draw.y, std::move(pos), std::move(uv));
}
std::shared_ptr<TextData> draw_data = _library.getTextData(draw.id);
draw_data->bind(*_renderer);
_atlas.render(*_renderer, draw.x, draw.y, draw_data->getIBOsize());
}
}
void TextPutPipeline::destroy() noexcept
{
_library.clearLibrary();
_atlas.destroy();
}
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/06 16:24:11 by maldavid #+# #+# */
/* Updated: 2023/04/08 20:44:33 by maldavid ### ########.fr */
/* Updated: 2023/04/11 12:24:59 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
@@ -19,6 +19,33 @@
#include <stb_truetype.h>
#include <cstdint>
#include <unordered_set>
#include <renderer/text_library.h>
namespace mlx
{
struct TextDrawData
{
TextID id;
int x;
int y;
int color;
TextDrawData(std::string text, int _color, int _x, int _y, TextLibrary& library, std::array<stbtt_bakedchar, 96>& cdata);
bool operator==(const TextDrawData& rhs) const { return id == rhs.id && x == rhs.x && y == rhs.y && color == rhs.color; }
};
}
namespace std
{
template <>
struct hash<mlx::TextDrawData>
{
size_t operator()(const mlx::TextDrawData& d) const noexcept
{
return std::hash<mlx::TextID>()(d.id) + std::hash<int>()(d.x) + std::hash<int>()(d.y) + std::hash<int>()(d.color);
}
};
}
namespace mlx
{
@@ -37,22 +64,10 @@ namespace mlx
~TextPutPipeline() = default;
private:
struct DrawData
{
std::string text;
int x;
int y;
int color;
DrawData(std::string _text, int _color, int _x, int _y) :
text(std::move(_text)), color(_color), x(_x), y(_y)
{}
bool operator==(const DrawData& rhs) const { return text == rhs.text && x == rhs.x && y == rhs.y && color == rhs.color; }
};
stbtt_bakedchar _cdata[96];
std::array<stbtt_bakedchar, 96> _cdata;
TextureAtlas _atlas;
std::unordered_set<DrawData> _drawlist;
TextLibrary _library;
std::unordered_set<TextDrawData> _drawlist;
Renderer* _renderer = nullptr;
};
}

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 17:55:21 by maldavid #+# #+# */
/* Updated: 2023/04/08 19:04:29 by maldavid ### ########.fr */
/* Updated: 2023/04/11 12:50:58 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */