Brenta Engine 1.1
Loading...
Searching...
No Matches
text.cpp
1/*
2 * MIT License
3 *
4 * Copyright (c) 2024 Giovanni Santini
5
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 */
26
27#include "text.hpp"
28
29#include "engine_logger.hpp"
30
31#include <filesystem>
32
33using namespace brenta;
34using namespace brenta::types;
35
36types::shader_name_t text::text_shader;
37types::vao text::text_vao;
38types::buffer text::text_vbo;
39std::map<char, types::character> text::characters;
40
42{
43 text::text_vbo = types::buffer(GL_ARRAY_BUFFER);
44 text::text_vao.init();
45
46 INFO("Text initialized");
47}
48
49void text::load(std::string font, unsigned int font_size)
50{
51 if (text_vao.get_vao() == 0)
52 {
53 ERROR("Text not initialized");
54 return;
55 }
56 FT_Library ft;
57 if (FT_Init_FreeType(&ft))
58 {
59 ERROR("Could not init FreeType library");
60 return;
61 }
62
63 shader::create("TextShader", GL_VERTEX_SHADER,
64 std::filesystem::absolute("engine/shaders/text.vs"),
65 GL_FRAGMENT_SHADER,
66 std::filesystem::absolute("engine/shaders/text.fs"));
67 text_shader = "TextShader";
68 shader::use(text_shader);
69
70 // find path to font
71 std::string font_name = std::filesystem::absolute("assets/fonts/" + font);
72 if (font_name.empty())
73 {
74 ERROR("Could not find font");
75 return;
76 }
77
78 FT_Face face;
79 if (FT_New_Face(ft, font_name.c_str(), 0, &face))
80 {
81 ERROR("Could not load font");
82 return;
83 }
84 else
85 {
86 // set size to load glyphs as
87 FT_Set_Pixel_Sizes(face, 0, 48);
88
89 // disable byte-alignment restriction
90 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
91
92 // load first 128 characters of ASCII set
93 for (unsigned char c = 0; c < 128; c++)
94 {
95 // Load character glyph
96 if (FT_Load_Char(face, c, FT_LOAD_RENDER))
97 {
98 ERROR("Could not load glyph");
99 continue;
100 }
101 // generate texture
102 unsigned int texture;
103 glGenTextures(1, &texture);
104 texture::bind_texture(GL_TEXTURE_2D, texture);
105 glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, face->glyph->bitmap.width,
106 face->glyph->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE,
107 face->glyph->bitmap.buffer);
108 // set texture options
109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
113 // now store character for later use
114 character character_ = {
115 texture,
116 glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
117 glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
118 static_cast<unsigned int>(face->glyph->advance.x)};
119 characters.insert(std::pair<char, character>(c, character_));
120 }
121 texture::bind_texture(GL_TEXTURE_2D, 0);
122 }
123 // destroy FreeType once we're finished
124 FT_Done_Face(face);
125 FT_Done_FreeType(ft);
126
127 // configure VAO/VBO for texture quads
128 text_vao.bind();
129 text_vbo.bind();
130 glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
131 glEnableVertexAttribArray(0);
132 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
133 text_vbo.unbind();
134 text_vao.unbind();
135}
136
137void text::render_text(std::string text, float x, float y, float scale,
138 glm::vec3 color)
139{
140 if (text_vao.get_vao() == 0)
141 {
142 ERROR("Text not initialized");
143 return;
144 }
145
146 shader::use(text_shader);
147 unsigned int textShaderId = shader::get_id(text_shader);
148
149 glUniform3f(glGetUniformLocation(textShaderId, "textColor"), color.x,
150 color.y, color.z);
151
152 glm::mat4 projection =
153 glm::ortho(0.0f, static_cast<float>(screen::get_width()), 0.0f,
154 static_cast<float>(screen::get_height()));
155 glUniformMatrix4fv(glGetUniformLocation(textShaderId, "projection"), 1,
156 GL_FALSE, glm::value_ptr(projection));
157
158 glActiveTexture(GL_TEXTURE0);
159 text_vao.bind();
160
161 // iterate through all characters
162 std::string::const_iterator c;
163 for (c = text.begin(); c != text.end(); c++)
164 {
165 character ch = characters[*c];
166
167 float xpos = x + ch.bearing.x * scale;
168 float ypos = y - (ch.size.y - ch.bearing.y) * scale;
169
170 float w = ch.size.x * scale;
171 float h = ch.size.y * scale;
172
173 // update VBO for each character
174
175 float vertices[6][4] = {
176 {xpos, ypos + h, 0.0, 0.0}, {xpos, ypos, 0.0, 1.0},
177 {xpos + w, ypos, 1.0, 1.0},
178
179 {xpos, ypos + h, 0.0, 0.0}, {xpos + w, ypos, 1.0, 1.0},
180 {xpos + w, ypos + h, 1.0, 0.0}};
181
182 // render glyph texture over quad
183 glBindTexture(GL_TEXTURE_2D, ch.texture_id);
184
185 // update content of VBO memory
186 glBindBuffer(GL_ARRAY_BUFFER, text_vbo.id);
187 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
188
189 glBindBuffer(GL_ARRAY_BUFFER, 0);
190 // render quad
191 glDrawArrays(GL_TRIANGLES, 0, 6);
192 // now advance cursors for next glyph (note that advance is number
193 // of 1/64 pixels)
194 x += (ch.advance >> 6)
195 * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
196 }
197 glBindVertexArray(0);
198 glBindTexture(GL_TEXTURE_2D, 0);
199
200 /*
201 // Render a test triangle
202 Shader::Use(textShader);
203
204 float vertices[6][4] = {
205 -0.5f, -0.5f, 0.0f, 0.0f,
206 0.5f, -0.5f, 0.0f, 0.0f,
207 0.0f, 0.5f, 0.0f, 1.0f,
208
209 -0.5f, -0.5f, 0.0f, 0.0f,
210 0.5f, -0.5f, 0.0f, 0.0f,
211 0.0f, 0.5f, 0.0f, 0.0f
212 };
213 textVao.Bind();
214 textVbo.Bind();
215 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
216 textVbo.Unbind();
217
218 glDrawArrays(GL_TRIANGLES, 0, 6);
219 */
220}
static int get_width()
Get the width of the window.
Definition screen.cpp:105
static int get_height()
Get the height of the window.
Definition screen.cpp:110
static void create(std::string shader_name, GLenum type, std::string path, Args... args)
Create a new shader.
Definition shader.hpp:93
static void use(types::shader_name_t shader_name)
Use the shader.
Definition shader.cpp:43
static unsigned int get_id(types::shader_name_t shader_name)
Get the ID of a shader.
Definition shader.cpp:33
Text subsystem.
Definition text.hpp:71
static void render_text(std::string text, float x, float y, float scale, glm::vec3 color)
Render text.
Definition text.cpp:137
static void init()
Initialize the text subsystem.
Definition text.cpp:41
static void load(std::string font_name, unsigned int font_size)
Load a font.
Definition text.cpp:49
static std::map< char, types::character > characters
Map of characters.
Definition text.hpp:78
Texture class.
Definition texture.hpp:41
static void bind_texture(GLenum target, unsigned int texture, GLint wrapping=GL_REPEAT, GLint filtering_min=GL_NEAREST, GLint filtering_mag=GL_NEAREST, GLboolean hasMipmap=GL_TRUE, GLint mipmap_min=GL_LINEAR_MIPMAP_LINEAR, GLint mipmap_mag=GL_LINEAR)
Bind a texture.
Definition texture.cpp:57
Buffer wrapper around OpenGL buffer objects.
Definition buffer.hpp:50
void unbind()
Unbind the buffer object.
Definition buffer.cpp:72
unsigned int id
Buffer object id, generated by OpenGL.
Definition buffer.hpp:55
void bind()
Bind the buffer object.
Definition buffer.cpp:62
Vertex Array Object (VAO)
Definition vao.hpp:45
void bind()
Bind the VAO.
Definition vao.cpp:49
unsigned int get_vao()
Get the VAO.
Definition vao.cpp:39
void unbind()
Unbind the VAO.
Definition vao.cpp:59
void init()
Init Constructor.
Definition vao.cpp:33
Character struct.
Definition text.hpp:54