Renderer: Rename Character -> Font/Symbol
This commit is contained in:
@@ -79,7 +79,7 @@ Application::~Application()
|
||||
m_scene->destroy();
|
||||
|
||||
FontManager::destroy();
|
||||
RendererCharacter::destroy();
|
||||
RendererFont::destroy();
|
||||
Renderer2D::destroy();
|
||||
RendererCubemap::destroy();
|
||||
RenderCommand::destroy();
|
||||
@@ -169,16 +169,16 @@ int Application::run()
|
||||
RenderCommand::clear();
|
||||
|
||||
std::pair<glm::mat4, glm::mat4> projectionView = m_scene->cameraProjectionView();
|
||||
RendererCubemap::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||
Renderer2D::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||
RendererCharacter::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||
RendererCubemap::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||
Renderer2D::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||
RendererFont::the().beginScene(projectionView.first, projectionView.second); // camera, lights, environment
|
||||
|
||||
m_scene->render();
|
||||
// RendererCharacter::the().drawCharacter(character, f->texture());
|
||||
|
||||
RendererCubemap::the().endScene();
|
||||
Renderer2D::the().endScene();
|
||||
RendererCharacter::the().endScene();
|
||||
RendererFont::the().endScene();
|
||||
|
||||
m_window->render();
|
||||
}
|
||||
|
||||
+11
-11
@@ -73,14 +73,14 @@ void Font::parseFont(const std::string& font)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Character
|
||||
// Symbol
|
||||
// ---------------------------------
|
||||
|
||||
if (action.compare("char") == 0) {
|
||||
unsigned char id = convert<unsigned char>(findValue("id", columns));
|
||||
uint32_t width = convert<uint32_t>(findValue("width", columns));
|
||||
uint32_t height = convert<uint32_t>(findValue("height", columns));
|
||||
Character character = {
|
||||
auto id = convert<char>(findValue("id", columns));
|
||||
auto width = convert<uint32_t>(findValue("width", columns));
|
||||
auto height = convert<uint32_t>(findValue("height", columns));
|
||||
Symbol symbol = {
|
||||
.id = id,
|
||||
.position = {
|
||||
convert<uint32_t>(findValue("x", columns)) + m_padding[Padding::Left],
|
||||
@@ -97,7 +97,7 @@ void Font::parseFont(const std::string& font)
|
||||
.advance = convert<uint32_t>(findValue("xadvance", columns)) - m_padding[Padding::Left] - m_padding[Padding::Right]
|
||||
};
|
||||
|
||||
m_characterList.emplace(id, std::make_shared<Character>(character));
|
||||
m_symbolList.emplace(id, std::make_shared<Symbol>(symbol));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -109,10 +109,10 @@ void Font::parseFont(const std::string& font)
|
||||
unsigned char second = convert<unsigned char>(findValue("second", columns));
|
||||
char amount = convert<char>(findValue("amount", columns));
|
||||
|
||||
// Add the kerning of the previous character to this character
|
||||
if (m_characterList.find(second) != m_characterList.end()) {
|
||||
auto character = m_characterList.at(second);
|
||||
character->kernings.emplace(first, amount);
|
||||
// Add the kerning of the previous symbol to this symbol
|
||||
if (m_symbolList.find(second) != m_symbolList.end()) {
|
||||
auto symbol = m_symbolList.at(second);
|
||||
symbol->kernings.emplace(first, amount);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -132,7 +132,7 @@ std::vector<std::string> Font::findColumns(const std::string& line) const
|
||||
size_t index = 0;
|
||||
size_t find = 0;
|
||||
size_t findFirstNotOf = 0;
|
||||
// Loop over line characters
|
||||
// Loop over line symbols
|
||||
while (find != std::string::npos) {
|
||||
find = line.find(" ", index);
|
||||
findFirstNotOf = line.find_first_not_of(" ", index);
|
||||
|
||||
@@ -24,13 +24,13 @@ namespace Inferno {
|
||||
|
||||
class Texture;
|
||||
|
||||
struct Character {
|
||||
char id; // Character
|
||||
struct Symbol {
|
||||
char id; // Symbol
|
||||
glm::uvec2 position; // Position
|
||||
glm::uvec2 size; // Width/height
|
||||
glm::ivec2 offset; // Offset from baseline to left / top of glyph
|
||||
uint32_t advance; // Amount to advance to next glyph
|
||||
std::unordered_map<unsigned char, char> kernings; // Kernings for characters that come before this one
|
||||
std::unordered_map<unsigned char, char> kernings; // Kernings for symbols that come before this one
|
||||
};
|
||||
|
||||
// -------------------------------------
|
||||
@@ -52,8 +52,8 @@ public:
|
||||
inline uint32_t lineSpacing() const { return m_lineSpacing; }
|
||||
inline std::shared_ptr<Texture> texture() const { return m_texture; }
|
||||
|
||||
inline std::shared_ptr<Character> get(unsigned char c) const { return m_characterList.at(c); }
|
||||
inline std::shared_ptr<Character> operator[](unsigned char c) const { return m_characterList.at(c); }
|
||||
inline std::shared_ptr<Symbol> get(unsigned char c) const { return m_symbolList.at(c); }
|
||||
inline std::shared_ptr<Symbol> operator[](unsigned char c) const { return m_symbolList.at(c); }
|
||||
|
||||
private:
|
||||
void parseFont(const std::string& font);
|
||||
@@ -66,7 +66,7 @@ private:
|
||||
uint32_t m_lineSpacing = { 0 };
|
||||
std::array<uint32_t, 4> m_padding = { 0 };
|
||||
std::shared_ptr<Texture> m_texture;
|
||||
std::unordered_map<unsigned char, std::shared_ptr<Character>> m_characterList;
|
||||
std::unordered_map<unsigned char, std::shared_ptr<Symbol>> m_symbolList;
|
||||
};
|
||||
|
||||
// -------------------------------------
|
||||
@@ -98,7 +98,7 @@ struct ruc::format::Formatter<glm::ivec2> : Formatter<std::vector<int32_t>> {
|
||||
// FontManager fm;
|
||||
// Font f = fm.load("path/to/font");
|
||||
// Font f2("path/to/font");
|
||||
// Character c = f['a'];
|
||||
// Symbol c = f['a'];
|
||||
|
||||
// Look into using signed distance fields for texture map generation ? anti-aliasing for text
|
||||
// https://youtu.be/d8cfgcJR9Tk
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "glad/glad.h"
|
||||
#include "ruc/format/log.h"
|
||||
|
||||
#include "inferno/component/transformcomponent.h"
|
||||
#include "inferno/render/buffer.h"
|
||||
#include "inferno/render/render-command.h"
|
||||
#include "inferno/render/renderer.h"
|
||||
@@ -388,7 +389,7 @@ void RendererCubemap::loadShader()
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
RendererCharacter::RendererCharacter(s)
|
||||
RendererFont::RendererFont(s)
|
||||
{
|
||||
Renderer::initialize();
|
||||
|
||||
@@ -396,7 +397,7 @@ RendererCharacter::RendererCharacter(s)
|
||||
// ---------------------------------
|
||||
|
||||
// Create array for storing quads vertices
|
||||
m_vertexBufferBase = new CharacterVertex[maxVertices];
|
||||
m_vertexBufferBase = new SymbolVertex[maxVertices];
|
||||
m_vertexBufferPtr = m_vertexBufferBase;
|
||||
|
||||
// GPU
|
||||
@@ -405,7 +406,7 @@ RendererCharacter::RendererCharacter(s)
|
||||
m_enableDepthBuffer = false;
|
||||
|
||||
// Create vertex buffer
|
||||
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(CharacterVertex) * maxVertices);
|
||||
auto vertexBuffer = std::make_shared<VertexBuffer>(sizeof(SymbolVertex) * maxVertices);
|
||||
vertexBuffer->setLayout({
|
||||
{ BufferElementType::Vec3, "a_position" },
|
||||
{ BufferElementType::Vec4, "a_color" },
|
||||
@@ -420,10 +421,10 @@ RendererCharacter::RendererCharacter(s)
|
||||
});
|
||||
m_vertexArray->addVertexBuffer(vertexBuffer);
|
||||
|
||||
ruc::info("RendererCharacter initialized");
|
||||
ruc::info("RendererFont initialized");
|
||||
}
|
||||
|
||||
void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>& characterQuad, std::shared_ptr<Texture> texture)
|
||||
void RendererFont::drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQuad, std::shared_ptr<Texture> texture)
|
||||
{
|
||||
// Create a new batch if the quad limit has been reached
|
||||
if (m_quadIndex >= maxQuads) {
|
||||
@@ -434,17 +435,17 @@ void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>
|
||||
|
||||
// Add the quads 4 vertices
|
||||
for (uint32_t i = 0; i < vertexPerQuad; i++) {
|
||||
m_vertexBufferPtr->quad.position = characterQuad[i].quad.position;
|
||||
m_vertexBufferPtr->quad.color = characterQuad[i].quad.color;
|
||||
m_vertexBufferPtr->quad.textureCoordinates = characterQuad[i].quad.textureCoordinates;
|
||||
m_vertexBufferPtr->quad.position = symbolQuad[i].quad.position;
|
||||
m_vertexBufferPtr->quad.color = symbolQuad[i].quad.color;
|
||||
m_vertexBufferPtr->quad.textureCoordinates = symbolQuad[i].quad.textureCoordinates;
|
||||
m_vertexBufferPtr->quad.textureIndex = (float)textureUnitIndex;
|
||||
|
||||
m_vertexBufferPtr->width = characterQuad[i].width;
|
||||
m_vertexBufferPtr->edge = characterQuad[i].edge;
|
||||
m_vertexBufferPtr->borderWidth = characterQuad[i].borderWidth;
|
||||
m_vertexBufferPtr->borderEdge = characterQuad[i].borderEdge;
|
||||
m_vertexBufferPtr->borderColor = characterQuad[i].borderColor;
|
||||
m_vertexBufferPtr->offset = characterQuad[i].offset;
|
||||
m_vertexBufferPtr->width = symbolQuad[i].width;
|
||||
m_vertexBufferPtr->edge = symbolQuad[i].edge;
|
||||
m_vertexBufferPtr->borderWidth = symbolQuad[i].borderWidth;
|
||||
m_vertexBufferPtr->borderEdge = symbolQuad[i].borderEdge;
|
||||
m_vertexBufferPtr->borderColor = symbolQuad[i].borderColor;
|
||||
m_vertexBufferPtr->offset = symbolQuad[i].offset;
|
||||
|
||||
m_vertexBufferPtr++;
|
||||
}
|
||||
@@ -452,7 +453,7 @@ void RendererCharacter::drawCharacter(std::array<CharacterVertex, vertexPerQuad>
|
||||
m_quadIndex++;
|
||||
}
|
||||
|
||||
void RendererCharacter::loadShader()
|
||||
void RendererFont::loadShader()
|
||||
{
|
||||
m_shader = ShaderManager::the().load("assets/glsl/batch-font");
|
||||
}
|
||||
|
||||
@@ -15,28 +15,27 @@
|
||||
#include "glm/ext/vector_float4.hpp" // glm::vec4
|
||||
#include "ruc/singleton.h"
|
||||
|
||||
#include "inferno/component/transformcomponent.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
class Shader;
|
||||
class Texture;
|
||||
class TransformComponent;
|
||||
class VertexArray;
|
||||
|
||||
struct QuadVertex {
|
||||
glm::vec3 position { 0.0f, 0.0f, 0.0f };
|
||||
glm::vec4 color { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
glm::vec2 textureCoordinates { 0.0f, 0.0f };
|
||||
float textureIndex = 0; // TODO: get int to pass to fragment correctly
|
||||
float textureIndex = 0;
|
||||
};
|
||||
|
||||
struct CubemapVertex {
|
||||
glm::vec3 position { 0.0f, 0.0f, 0.0f };
|
||||
glm::vec4 color { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
float textureIndex = 0; // TODO: get int to pass to fragment correctly
|
||||
float textureIndex = 0;
|
||||
};
|
||||
|
||||
struct CharacterVertex {
|
||||
struct SymbolVertex {
|
||||
QuadVertex quad;
|
||||
|
||||
// Font
|
||||
@@ -157,16 +156,16 @@ private:
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
class RendererCharacter final
|
||||
: public Renderer<CharacterVertex>
|
||||
, public ruc::Singleton<RendererCharacter> {
|
||||
class RendererFont final
|
||||
: public Renderer<SymbolVertex>
|
||||
, public ruc::Singleton<RendererFont> {
|
||||
public:
|
||||
RendererCharacter(s);
|
||||
virtual ~RendererCharacter() {};
|
||||
RendererFont(s);
|
||||
virtual ~RendererFont() {};
|
||||
|
||||
using Singleton<RendererCharacter>::destroy;
|
||||
using Singleton<RendererFont>::destroy;
|
||||
|
||||
void drawCharacter(std::array<CharacterVertex, vertexPerQuad>& characterQuad, std::shared_ptr<Texture> texture);
|
||||
void drawSymbol(std::array<SymbolVertex, vertexPerQuad>& symbolQuad, std::shared_ptr<Texture> texture);
|
||||
|
||||
private:
|
||||
void loadShader() override;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Riyyi
|
||||
* Copyright (C) 2022-2024 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "inferno/application.h"
|
||||
#include "inferno/component/textareacomponent.h"
|
||||
#include "inferno/component/transformcomponent.h"
|
||||
#include "inferno/render/font.h"
|
||||
#include "inferno/render/renderer.h"
|
||||
#include "inferno/render/texture.h"
|
||||
@@ -42,19 +43,19 @@ void TextAreaSystem::render()
|
||||
// Loop through textareas content
|
||||
// Linebreak if width reached
|
||||
// Break if lines AND width reached
|
||||
// Calculate character quad
|
||||
// Submit character quad for rendering
|
||||
// Calculate symbol quad
|
||||
// Submit symbol quad for rendering
|
||||
|
||||
std::shared_ptr<Font> font = FontManager::the().load(textarea.font);
|
||||
// glm::mat4 translate = transform.translate;
|
||||
|
||||
m_characters.clear();
|
||||
m_symbols.clear();
|
||||
createLines(font, textarea);
|
||||
createQuads(font, textarea);
|
||||
}
|
||||
}
|
||||
|
||||
using Characters = std::vector<std::shared_ptr<Character>>;
|
||||
using Symbols = std::vector<std::shared_ptr<Symbol>>;
|
||||
|
||||
void TextAreaSystem::createLines(std::shared_ptr<Font> font, const TextAreaComponent& textarea)
|
||||
{
|
||||
@@ -73,9 +74,9 @@ void TextAreaSystem::createLines(std::shared_ptr<Font> font, const TextAreaCompo
|
||||
size_t spaceIndex = 0;
|
||||
float lineWidth = 0.0f;
|
||||
float lineWidthSinceLastSpace = 0.0f;
|
||||
for (char character : textarea.content) {
|
||||
auto c = font->get(character);
|
||||
m_characters.push_back(c);
|
||||
for (char symbol : textarea.content) {
|
||||
auto c = font->get(symbol);
|
||||
m_symbols.push_back(c);
|
||||
|
||||
// Kerning
|
||||
char kerning = 0;
|
||||
@@ -86,18 +87,18 @@ void TextAreaSystem::createLines(std::shared_ptr<Font> font, const TextAreaCompo
|
||||
lineWidth += (c->advance + kerning) * fontScale;
|
||||
lineWidthSinceLastSpace += (c->advance + kerning) * fontScale;
|
||||
|
||||
if (character == ' ') {
|
||||
spaceIndex = m_characters.size() - 1;
|
||||
if (symbol == ' ') {
|
||||
spaceIndex = m_symbols.size() - 1;
|
||||
lineWidthSinceLastSpace = 0;
|
||||
}
|
||||
|
||||
if (lineWidth > textureWidth) {
|
||||
m_characters[spaceIndex] = nullptr;
|
||||
m_symbols[spaceIndex] = nullptr;
|
||||
lineWidth = 0;
|
||||
lineWidth = lineWidthSinceLastSpace;
|
||||
}
|
||||
|
||||
previous = character;
|
||||
previous = symbol;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,26 +109,26 @@ void TextAreaSystem::createQuads(std::shared_ptr<Font> font, const TextAreaCompo
|
||||
char previous = 0;
|
||||
float advanceX = 0.0f;
|
||||
float advanceY = 0.0f;
|
||||
for (const auto& character : m_characters) {
|
||||
for (const auto& symbol : m_symbols) {
|
||||
// Go to the next line on "\n"
|
||||
if (character == nullptr) {
|
||||
if (symbol == nullptr) {
|
||||
advanceX = 0;
|
||||
advanceY -= (font->lineSpacing() * textarea.lineSpacing) * fontScale;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::optional<CharacterQuad> quad = calculateCharacterQuad(character, previous, font, fontScale, advanceX, advanceY);
|
||||
std::optional<SymbolQuad> quad = calculateSymbolQuad(symbol, previous, font, fontScale, advanceX, advanceY);
|
||||
if (quad) {
|
||||
RendererCharacter::the().drawCharacter(quad.value(), font->texture());
|
||||
RendererFont::the().drawSymbol(quad.value(), font->texture());
|
||||
}
|
||||
|
||||
previous = character->id;
|
||||
previous = symbol->id;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<CharacterQuad> TextAreaSystem::calculateCharacterQuad(std::shared_ptr<Character> c, char previous, std::shared_ptr<Font> font, float fontScale, float& advanceX, float& advanceY)
|
||||
std::optional<SymbolQuad> TextAreaSystem::calculateSymbolQuad(std::shared_ptr<Symbol> c, char previous, std::shared_ptr<Font> font, float fontScale, float& advanceX, float& advanceY)
|
||||
{
|
||||
CharacterQuad characterQuad;
|
||||
SymbolQuad symbolQuad;
|
||||
|
||||
// Texture
|
||||
// -------------------------------------
|
||||
@@ -136,7 +137,7 @@ std::optional<CharacterQuad> TextAreaSystem::calculateCharacterQuad(std::shared_
|
||||
float textureHeight = static_cast<float>(font->texture()->height());
|
||||
VERIFY(textureWidth == textureHeight, "TextAreaSystem read invalid font texture");
|
||||
|
||||
// Skip empty characters (like space)
|
||||
// Skip empty symbols (like space)
|
||||
if (c->size.x == 0 || c->size.y == 0) {
|
||||
// Jump to the next glyph
|
||||
advanceX += c->advance * fontScale;
|
||||
@@ -167,10 +168,10 @@ std::optional<CharacterQuad> TextAreaSystem::calculateCharacterQuad(std::shared_
|
||||
(cursorMax.y / textureHeight * 2) + 1,
|
||||
};
|
||||
|
||||
characterQuad.at(0).quad.position = { cursorScreen.x, cursorScreenMax.y, 0.0f }; // bottom left
|
||||
characterQuad.at(1).quad.position = { cursorScreenMax.x, cursorScreenMax.y, 0.0f }; // bottom right
|
||||
characterQuad.at(2).quad.position = { cursorScreenMax.x, cursorScreen.y, 0.0f }; // top right
|
||||
characterQuad.at(3).quad.position = { cursorScreen.x, cursorScreen.y, 0.0f }; // top left
|
||||
symbolQuad.at(0).quad.position = { cursorScreen.x, cursorScreenMax.y, 0.0f }; // bottom left
|
||||
symbolQuad.at(1).quad.position = { cursorScreenMax.x, cursorScreenMax.y, 0.0f }; // bottom right
|
||||
symbolQuad.at(2).quad.position = { cursorScreenMax.x, cursorScreen.y, 0.0f }; // top right
|
||||
symbolQuad.at(3).quad.position = { cursorScreen.x, cursorScreen.y, 0.0f }; // top left
|
||||
|
||||
// Jump to the next glyph
|
||||
advanceX += (c->advance + kerning) * fontScale;
|
||||
@@ -187,12 +188,12 @@ std::optional<CharacterQuad> TextAreaSystem::calculateCharacterQuad(std::shared_
|
||||
(textureHeight - c->position.y) / textureHeight
|
||||
};
|
||||
|
||||
characterQuad.at(0).quad.textureCoordinates = { x.x, y.x };
|
||||
characterQuad.at(1).quad.textureCoordinates = { x.y, y.x };
|
||||
characterQuad.at(2).quad.textureCoordinates = { x.y, y.y };
|
||||
characterQuad.at(3).quad.textureCoordinates = { x.x, y.y };
|
||||
symbolQuad.at(0).quad.textureCoordinates = { x.x, y.x };
|
||||
symbolQuad.at(1).quad.textureCoordinates = { x.y, y.x };
|
||||
symbolQuad.at(2).quad.textureCoordinates = { x.y, y.y };
|
||||
symbolQuad.at(3).quad.textureCoordinates = { x.x, y.y };
|
||||
|
||||
return characterQuad;
|
||||
return symbolQuad;
|
||||
}
|
||||
|
||||
} // namespace Inferno
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Riyyi
|
||||
* Copyright (C) 2022-2024 Riyyi
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
@@ -14,17 +14,16 @@
|
||||
#include "glm/ext/vector_float3.hpp" // glm::vec3
|
||||
#include "ruc/singleton.h"
|
||||
|
||||
#include "inferno/component/textareacomponent.h"
|
||||
#include "inferno/render/font.h"
|
||||
#include "inferno/render/renderer.h"
|
||||
|
||||
namespace Inferno {
|
||||
|
||||
using Characters = std::vector<std::shared_ptr<Character>>;
|
||||
using CharacterQuad = std::array<CharacterVertex, Renderer<void>::vertexPerQuad>;
|
||||
using Symbols = std::vector<std::shared_ptr<Symbol>>;
|
||||
using SymbolQuad = std::array<SymbolVertex, Renderer<void>::vertexPerQuad>;
|
||||
|
||||
class Font;
|
||||
class Scene;
|
||||
class TextAreaComponent;
|
||||
|
||||
class TextAreaSystem final : public ruc::Singleton<TextAreaSystem> {
|
||||
public:
|
||||
@@ -39,9 +38,9 @@ private:
|
||||
void createLines(std::shared_ptr<Font> font, const TextAreaComponent& textarea);
|
||||
void createQuads(std::shared_ptr<Font> font, const TextAreaComponent& textarea);
|
||||
|
||||
std::optional<CharacterQuad> calculateCharacterQuad(std::shared_ptr<Character> c, char previous, std::shared_ptr<Font> font, float fontSize, float& advanceX, float& advanceY);
|
||||
std::optional<SymbolQuad> calculateSymbolQuad(std::shared_ptr<Symbol> c, char previous, std::shared_ptr<Font> font, float fontSize, float& advanceX, float& advanceY);
|
||||
|
||||
Characters m_characters;
|
||||
Symbols m_symbols;
|
||||
Scene* m_scene { nullptr };
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user