mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-06-18 00:27:02 +08:00
feat: add text class
This commit is contained in:
@@ -94,6 +94,7 @@ add_executable(${PROJECT_NAME}
|
|||||||
src/tools/font.cpp
|
src/tools/font.cpp
|
||||||
src/tools/log.cpp
|
src/tools/log.cpp
|
||||||
src/tools/perlin_noise.cpp
|
src/tools/perlin_noise.cpp
|
||||||
|
src/ui/text.cpp
|
||||||
src/window.cpp
|
src/window.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <Cubed/config.hpp>
|
#include <Cubed/config.hpp>
|
||||||
#include <Cubed/shader.hpp>
|
#include <Cubed/shader.hpp>
|
||||||
|
#include <Cubed/ui/text.hpp>
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
@@ -45,6 +46,13 @@ private:
|
|||||||
std::unordered_map<std::size_t, Shader> m_shaders;
|
std::unordered_map<std::size_t, Shader> m_shaders;
|
||||||
std::vector<GLuint> m_vao;
|
std::vector<GLuint> m_vao;
|
||||||
std::vector<Vertex2D> m_ui;
|
std::vector<Vertex2D> m_ui;
|
||||||
|
|
||||||
|
Text m_version_text;
|
||||||
|
Text m_fps_text;
|
||||||
|
Text m_player_pos_text;
|
||||||
|
|
||||||
|
void init_text();
|
||||||
|
|
||||||
void render_outline();
|
void render_outline();
|
||||||
void render_sky();
|
void render_sky();
|
||||||
void render_text();
|
void render_text();
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include <Cubed/config.hpp>
|
||||||
|
|
||||||
struct Character {
|
struct Character {
|
||||||
glm::vec2 uv_min;
|
glm::vec2 uv_min;
|
||||||
glm::vec2 uv_max;
|
glm::vec2 uv_max;
|
||||||
@@ -23,8 +25,8 @@ public:
|
|||||||
Font();
|
Font();
|
||||||
~Font();
|
~Font();
|
||||||
|
|
||||||
static void render_text(const Shader& shader, const std::string& text, float x, float y, float scale, const glm::vec3& color);
|
static std::vector<Vertex2D> vertices(const std::string& text, float x = 0.0f, float y = 0.0f, float scale = 1.0f);
|
||||||
|
static GLuint text_texture();
|
||||||
private:
|
private:
|
||||||
FT_Library m_ft;
|
FT_Library m_ft;
|
||||||
FT_Face m_face;
|
FT_Face m_face;
|
||||||
@@ -32,7 +34,7 @@ private:
|
|||||||
float m_texture_width = 64;
|
float m_texture_width = 64;
|
||||||
float m_texture_height = 64;
|
float m_texture_height = 64;
|
||||||
|
|
||||||
GLuint m_text_texture;
|
static inline GLuint m_text_texture;
|
||||||
std::unordered_map<char8_t, Character> m_characters;
|
std::unordered_map<char8_t, Character> m_characters;
|
||||||
|
|
||||||
void load_character(char8_t c);
|
void load_character(char8_t c);
|
||||||
|
|||||||
65
include/Cubed/ui/color.hpp
Normal file
65
include/Cubed/ui/color.hpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Cubed/tools/cubed_assert.hpp>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
enum class Color {
|
||||||
|
BLACK,
|
||||||
|
WHITE,
|
||||||
|
RED,
|
||||||
|
GREEN,
|
||||||
|
BLUE,
|
||||||
|
YELLOW,
|
||||||
|
CYAN,
|
||||||
|
MAGENTA,
|
||||||
|
GRAY,
|
||||||
|
ORANGE,
|
||||||
|
PURPLE,
|
||||||
|
PINK,
|
||||||
|
BROWN
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr glm::vec4 color_value(Color color) {
|
||||||
|
using glm::vec4;
|
||||||
|
|
||||||
|
switch (color) {
|
||||||
|
case Color::BLACK:
|
||||||
|
return vec4{0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
case Color::WHITE:
|
||||||
|
return vec4{1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
case Color::RED:
|
||||||
|
return vec4{1.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
case Color::GREEN:
|
||||||
|
return vec4{0.0f, 1.0f, 0.0f, 1.0f};
|
||||||
|
case Color::BLUE:
|
||||||
|
return vec4{0.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
case Color::YELLOW:
|
||||||
|
return vec4{1.0f, 1.0f, 0.0f, 1.0f};
|
||||||
|
case Color::CYAN:
|
||||||
|
return vec4{0.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
case Color::MAGENTA:
|
||||||
|
return vec4{1.0f, 0.0f, 1.0f, 1.0f};
|
||||||
|
case Color::GRAY:
|
||||||
|
return vec4{0.5f, 0.5f, 0.5f, 1.0f};
|
||||||
|
case Color::ORANGE:
|
||||||
|
return vec4{1.0f, 0.647f, 0.0f, 1.0f};
|
||||||
|
case Color::PURPLE:
|
||||||
|
return vec4{0.502f, 0.0f, 0.502f, 1.0f};
|
||||||
|
case Color::PINK:
|
||||||
|
return vec4{1.0f, 0.753f, 0.769f, 1.0f};
|
||||||
|
case Color::BROWN:
|
||||||
|
return vec4{0.647f, 0.165f, 0.165f, 1.0f};
|
||||||
|
default:
|
||||||
|
CUBED_ASSERT_MSG(false, "Unknown Color");
|
||||||
|
return vec4{1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline glm::vec4 rgb255_to_float(int r, int g, int b, int a) {
|
||||||
|
float nr = static_cast<float>(r) / 255.0f;
|
||||||
|
float ng = static_cast<float>(g) / 255.0f;
|
||||||
|
float nb = static_cast<float>(b) / 255.0f;
|
||||||
|
float na = static_cast<float>(a) / 255.0f;
|
||||||
|
|
||||||
|
return glm::vec4{nr, ng, nb, na};
|
||||||
|
}
|
||||||
46
include/Cubed/ui/text.hpp
Normal file
46
include/Cubed/ui/text.hpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <Cubed/config.hpp>
|
||||||
|
#include <Cubed/ui/color.hpp>
|
||||||
|
|
||||||
|
class Shader;
|
||||||
|
|
||||||
|
class Text {
|
||||||
|
public:
|
||||||
|
Text();
|
||||||
|
Text(std::string_view str, glm::vec2 pos = glm::vec2{0.0f, 0.0f}, Color color = Color::BLACK);
|
||||||
|
~Text();
|
||||||
|
|
||||||
|
Text& color(Color color);
|
||||||
|
//Text& color(const glm::vec4& color, int pos);
|
||||||
|
Text& position(float x, float y);
|
||||||
|
Text& scale(float s);
|
||||||
|
static void set_loc(const Shader& shader);
|
||||||
|
Text& text(std::string_view str);
|
||||||
|
|
||||||
|
|
||||||
|
void render();
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_scale = 1.0f;
|
||||||
|
glm::vec2 m_pos{0.0f, 0.0f};
|
||||||
|
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_text;
|
||||||
|
glm::vec4 m_color{1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
|
glm::mat4 m_model_matrix;
|
||||||
|
|
||||||
|
std::vector<Vertex2D> m_vertices;
|
||||||
|
GLuint m_vbo = 0;
|
||||||
|
static inline GLuint m_color_loc = 0;
|
||||||
|
static inline GLuint m_mv_loc = 0;
|
||||||
|
|
||||||
|
void update_vertices();
|
||||||
|
void upload_to_gpu();
|
||||||
|
|
||||||
|
};
|
||||||
@@ -104,6 +104,8 @@ void Renderer::init() {
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, m_text_vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, m_text_vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float)* 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float)* 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
init_text();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Shader& Renderer::get_shader(const std::string& name) const {
|
const Shader& Renderer::get_shader(const std::string& name) const {
|
||||||
@@ -112,6 +114,23 @@ const Shader& Renderer::get_shader(const std::string& name) const {
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::init_text() {
|
||||||
|
const auto& shader = get_shader("text");
|
||||||
|
Text::set_loc(shader);
|
||||||
|
m_version_text
|
||||||
|
.position(0.0f, 100.0f)
|
||||||
|
.scale(0.8f)
|
||||||
|
.color(Color::WHITE)
|
||||||
|
.text("Version: v0.0.1-Debug");
|
||||||
|
m_fps_text
|
||||||
|
.position(0.0f, 50.0f)
|
||||||
|
.text("FPS: 0");
|
||||||
|
m_player_pos_text
|
||||||
|
.position(0.0f, 150.0f)
|
||||||
|
.scale(0.8f)
|
||||||
|
.text("x: 0.00 y: 0.00 z: 0.00");
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::render() {
|
void Renderer::render() {
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
@@ -192,15 +211,15 @@ void Renderer::render_text() {
|
|||||||
m_proj_loc = shader.loc("projection");
|
m_proj_loc = shader.loc("projection");
|
||||||
|
|
||||||
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_ui_proj));
|
glUniformMatrix4fv(m_proj_loc, 1, GL_FALSE, glm::value_ptr(m_ui_proj));
|
||||||
|
m_fps_text.text(std::string{"FPS: " + std::to_string(static_cast<int>(App::get_fps()))});
|
||||||
Font::render_text(shader, std::string{"FPS: " + std::to_string(static_cast<int>(App::get_fps()))}, 0.0f, 50.0f, 1.0f, glm::vec3(1.0f, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
Font::render_text(shader, "Version: v0.0.1-Debug", 0.0f, 100.0f, 0.8f, glm::vec3(1.0f, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
const auto& player = m_world.get_player("TestPlayer");
|
const auto& player = m_world.get_player("TestPlayer");
|
||||||
const auto& pos = player.get_player_pos();
|
const auto& pos = player.get_player_pos();
|
||||||
std::string player_pos = std::format("x: {:.2f} y: {:.2f} z: {:.2f}", pos.x, pos.y, pos.z);
|
std::string player_pos = std::format("x: {:.2f} y: {:.2f} z: {:.2f}", pos.x, pos.y, pos.z);
|
||||||
Font::render_text(shader, player_pos, 0.0f, 150.0f, 0.8f, glm::vec3(1.0f, 1.0f, 1.0f));
|
m_player_pos_text.text(player_pos);
|
||||||
|
|
||||||
|
m_fps_text.render();
|
||||||
|
m_player_pos_text.render();
|
||||||
|
m_version_text.render();
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ layout (location = 2) in float layer;
|
|||||||
out vec2 tc;
|
out vec2 tc;
|
||||||
flat out int tex_layer;
|
flat out int tex_layer;
|
||||||
uniform mat4 projection;
|
uniform mat4 projection;
|
||||||
|
uniform mat4 mv_matrix;
|
||||||
void main(void) {
|
void main(void) {
|
||||||
gl_Position = projection * vec4(pos, 0.0, 1.0);
|
gl_Position = projection * mv_matrix * vec4(pos, 0.0, 1.0);
|
||||||
tc = texCoord;
|
tc = texCoord;
|
||||||
tex_layer = int(layer);
|
tex_layer = int(layer);
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
#include <Cubed/config.hpp>
|
|
||||||
#include <Cubed/shader.hpp>
|
#include <Cubed/shader.hpp>
|
||||||
#include <Cubed/tools/font.hpp>
|
#include <Cubed/tools/font.hpp>
|
||||||
#include <Cubed/tools/log.hpp>
|
#include <Cubed/tools/log.hpp>
|
||||||
#include <Cubed/tools/shader_tools.hpp>
|
#include <Cubed/tools/shader_tools.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Font::Font() {
|
Font::Font() {
|
||||||
|
|
||||||
if (FT_Init_FreeType(&m_ft)) {
|
if (FT_Init_FreeType(&m_ft)) {
|
||||||
@@ -24,10 +22,8 @@ Font::~Font() {
|
|||||||
|
|
||||||
FT_Done_Face(m_face);
|
FT_Done_Face(m_face);
|
||||||
FT_Done_FreeType(m_ft);
|
FT_Done_FreeType(m_ft);
|
||||||
for (const auto& [key, character] : m_characters) {
|
|
||||||
glDeleteTextures(1, &m_text_texture);
|
glDeleteTextures(1, &m_text_texture);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Font::load_character(char8_t c) {
|
void Font::load_character(char8_t c) {
|
||||||
if (FT_Load_Char(m_face, c, FT_LOAD_RENDER)) {
|
if (FT_Load_Char(m_face, c, FT_LOAD_RENDER)) {
|
||||||
@@ -36,6 +32,7 @@ void Font::load_character(char8_t c) {
|
|||||||
}
|
}
|
||||||
const auto& width = m_face->glyph->bitmap.width;
|
const auto& width = m_face->glyph->bitmap.width;
|
||||||
const auto& height = m_face->glyph->bitmap.rows;
|
const auto& height = m_face->glyph->bitmap.rows;
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY, m_text_texture);
|
||||||
glTexSubImage3D(
|
glTexSubImage3D(
|
||||||
GL_TEXTURE_2D_ARRAY,
|
GL_TEXTURE_2D_ARRAY,
|
||||||
0,
|
0,
|
||||||
@@ -90,13 +87,9 @@ void Font::setup_font_character() {
|
|||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Vertex2D> Font::vertices(const std::string &text, float x, float y, float scale) {
|
||||||
|
|
||||||
void Font::render_text(const Shader& shader, const std::string& text, float x, float y, float scale, const glm::vec3& color) {
|
|
||||||
static Font font;
|
static Font font;
|
||||||
|
|
||||||
glUniform3f(shader.loc("textColor"), color.x, color.y, color.z);
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
std::vector<Vertex2D> vertices;
|
std::vector<Vertex2D> vertices;
|
||||||
|
|
||||||
for (char8_t c : text) {
|
for (char8_t c : text) {
|
||||||
@@ -122,22 +115,10 @@ void Font::render_text(const Shader& shader, const std::string& text, float x, f
|
|||||||
x += (ch.advance >> 6) * scale;
|
x += (ch.advance >> 6) * scale;
|
||||||
|
|
||||||
}
|
}
|
||||||
GLuint vbo;
|
|
||||||
glGenBuffers(1, &vbo);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex2D), vertices.data(), GL_STATIC_DRAW);
|
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, font.m_text_texture);
|
|
||||||
|
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*)0);
|
return vertices;
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*)offsetof(Vertex2D, s));
|
}
|
||||||
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*)offsetof(Vertex2D, layer));
|
|
||||||
|
GLuint Font::text_texture() {
|
||||||
glEnableVertexAttribArray(0);
|
return m_text_texture;
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
glEnableVertexAttribArray(2);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
|
||||||
glDeleteBuffers(1, &vbo);
|
|
||||||
}
|
}
|
||||||
90
src/ui/text.cpp
Normal file
90
src/ui/text.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#include <Cubed/ui/text.hpp>
|
||||||
|
|
||||||
|
#include <Cubed/shader.hpp>
|
||||||
|
#include <Cubed/tools/font.hpp>
|
||||||
|
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
Text::Text() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Text::Text(std::string_view str, glm::vec2 pos, Color color) {
|
||||||
|
m_text.assign(str);
|
||||||
|
m_pos = pos;
|
||||||
|
m_color = color_value(color);
|
||||||
|
update_vertices();
|
||||||
|
}
|
||||||
|
|
||||||
|
Text::~Text() {
|
||||||
|
if (m_vbo != 0) {
|
||||||
|
glDeleteBuffers(1, &m_vbo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& Text::color(Color color) {
|
||||||
|
m_color = color_value(color);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& Text::position(float x, float y) {
|
||||||
|
m_pos = glm::vec2{x, y};
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& Text::scale(float s) {
|
||||||
|
m_scale = s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Text::set_loc(const Shader& shader) {
|
||||||
|
m_color_loc = shader.loc("textColor");
|
||||||
|
m_mv_loc = shader.loc("mv_matrix");
|
||||||
|
}
|
||||||
|
|
||||||
|
Text& Text::text(std::string_view str) {
|
||||||
|
m_text.assign(str);
|
||||||
|
update_vertices();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Text::render() {
|
||||||
|
|
||||||
|
CUBED_ASSERT_MSG(!m_vertices.empty(), "Text String Not Set");
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY, Font::text_texture());
|
||||||
|
CUBED_ASSERT_MSG(m_color_loc, "m_color_loc is null");
|
||||||
|
|
||||||
|
m_model_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(m_pos.x, m_pos.y, 0.0f)) *
|
||||||
|
glm::scale(glm::mat4(1.0f), glm::vec3(m_scale, m_scale, 1.0f));
|
||||||
|
|
||||||
|
glUniform3f(m_color_loc, m_color.x, m_color.y, m_color.z);
|
||||||
|
glUniformMatrix4fv(m_mv_loc, 1, GL_FALSE, glm::value_ptr(m_model_matrix));
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*)0);
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*)offsetof(Vertex2D, s));
|
||||||
|
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void*)offsetof(Vertex2D, layer));
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Text::update_vertices() {
|
||||||
|
m_vertices = Font::vertices(m_text);
|
||||||
|
upload_to_gpu();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Text::upload_to_gpu() {
|
||||||
|
if (m_vbo == 0) {
|
||||||
|
glGenBuffers(1, &m_vbo);
|
||||||
|
}
|
||||||
|
CUBED_ASSERT_MSG(m_vbo, "Vbo Is Not Gen");
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex2D), m_vertices.data(), GL_DYNAMIC_DRAW);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user