Add draft for text rendering
This commit is contained in:
parent
307d000253
commit
10138d5fd8
@ -19,7 +19,7 @@ env = Environment(tools=['default', 'compilation_db'])
|
||||
env.CompilationDatabase()
|
||||
|
||||
env.Append(CPPPATH=['cpp/', 'include/'])
|
||||
env.Append(LIBS=['glfw', 'dl'])
|
||||
env.Append(LIBS=['glfw', 'dl', 'freetype'])
|
||||
|
||||
add_third_party_includes(env)
|
||||
add_strict_compile_flags(env)
|
||||
|
@ -15,6 +15,11 @@ void RenderBackend::initialize_window(unsigned int width, unsigned int height, S
|
||||
window = glfwCreateWindow(width, height, title, NULL, NULL);
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
bool RenderBackend::is_window_created() {
|
||||
|
128
cpp/TextLabel.cpp
Normal file
128
cpp/TextLabel.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
// Must be the first include
|
||||
#include <glad/glad.h>
|
||||
|
||||
// Other includes
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include "Gedeng/Logger.h"
|
||||
#include "Gedeng/TextLabel.h"
|
||||
|
||||
namespace Gedeng {
|
||||
|
||||
TextLabel::TextLabel() : shader(Shader("Shader/text.vs", "Shader/text.fs")) {
|
||||
FT_Library ft;
|
||||
if (FT_Init_FreeType(&ft)) {
|
||||
GG_CORE_ERROR("Couldn't create font library!");
|
||||
return;
|
||||
}
|
||||
|
||||
FT_Face face;
|
||||
if (FT_New_Face(ft, "Resources/Fonts/Inter.ttf", 0, &face)) {
|
||||
GG_CORE_ERROR("Couldn't load font from path!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set size
|
||||
FT_Set_Pixel_Sizes(face, 0, 48);
|
||||
|
||||
// Load first 128 ASCII Characters
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
|
||||
|
||||
for (unsigned char c = 0; c < 128; c++) {
|
||||
// load character glyph
|
||||
if (FT_Load_Char(face, c, FT_LOAD_RENDER)) {
|
||||
GG_CORE_ERROR("Couldn't load character glyph!");
|
||||
continue;
|
||||
}
|
||||
// generate texture
|
||||
unsigned int texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, face->glyph->bitmap.width, face->glyph->bitmap.rows, 0, GL_RED,
|
||||
GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
|
||||
// set texture options
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// now store character for later use
|
||||
Character character = {texture, glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
|
||||
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
|
||||
static_cast<unsigned int>(face->glyph->advance.x)};
|
||||
characters.insert(std::pair<char, Character>(c, character));
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// destroy FreeType once we're finished
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
// configure VAO/VBO for texture quads
|
||||
// -----------------------------------
|
||||
glGenVertexArrays(1, &vao);
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
void TextLabel::render_text(String text, float x, float y, float scale, Vector3 color) {
|
||||
// activate corresponding render state
|
||||
shader.use();
|
||||
|
||||
glUniform3f(glGetUniformLocation(shader.ID, "textColor"), color.x, color.y, color.z);
|
||||
|
||||
// FIXME: We need the screen size here... (or UI module size?)
|
||||
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(500), 0.0f, static_cast<float>(500));
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.ID, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
// iterate through all characters
|
||||
for (size_t i = 0; i < text.get_length(); i++) {
|
||||
Character ch = characters[text[i]];
|
||||
|
||||
float xpos = x + ch.bearing.x * scale;
|
||||
float ypos = y - (ch.size.y - ch.bearing.y) * scale;
|
||||
|
||||
float w = ch.size.x * scale;
|
||||
float h = ch.size.y * scale;
|
||||
// update VBO for each character
|
||||
float vertices[6][4] = {
|
||||
{xpos, ypos + h, 0.0f, 0.0f}, {xpos, ypos, 0.0f, 1.0f}, {xpos + w, ypos, 1.0f, 1.0f},
|
||||
|
||||
{xpos, ypos + h, 0.0f, 0.0f}, {xpos + w, ypos, 1.0f, 1.0f}, {xpos + w, ypos + h, 1.0f, 0.0f}};
|
||||
// render glyph texture over quad
|
||||
glBindTexture(GL_TEXTURE_2D, ch.texture_id);
|
||||
// update content of VBO memory
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices),
|
||||
vertices); // be sure to use glBufferSubData and not glBufferData
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
// render quad
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
||||
x += (ch.advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th
|
||||
// pixels by 64 to get amount of pixels))
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
bool TextLabel::is_valid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
} // namespace Gedeng
|
37
include/Gedeng/TextLabel.h
Normal file
37
include/Gedeng/TextLabel.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <ft2build.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <map>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include "Gedeng/Shader.h"
|
||||
#include "Gedeng/String.h"
|
||||
#include "Gedeng/Vector3.h"
|
||||
|
||||
namespace Gedeng {
|
||||
|
||||
class TextLabel {
|
||||
public:
|
||||
TextLabel();
|
||||
|
||||
void render_text(String text, float x, float y, float scale, Vector3 color);
|
||||
|
||||
bool is_valid();
|
||||
|
||||
private:
|
||||
struct Character {
|
||||
unsigned int texture_id; // ID handle of the glyph texture
|
||||
glm::ivec2 size; // Size of glyph
|
||||
glm::ivec2 bearing; // Offset from baseline to left/top of glyph
|
||||
unsigned int advance; // Offset to advance to next glyph
|
||||
};
|
||||
|
||||
std::map<char, Character> characters;
|
||||
unsigned int vao, vbo;
|
||||
bool valid;
|
||||
|
||||
Shader shader;
|
||||
};
|
||||
|
||||
} // namespace Gedeng
|
@ -2,6 +2,14 @@
|
||||
|
||||
namespace Gedeng {
|
||||
|
||||
class Vector3 {};
|
||||
class Vector3 {
|
||||
public:
|
||||
Vector3(float x, float y, float z) : x(x), y(y), z(z) {
|
||||
}
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
} // namespace Gedeng
|
@ -1,4 +1,6 @@
|
||||
#include "Gedeng/Logger.h"
|
||||
#include "Gedeng/TextLabel.h"
|
||||
#include "Gedeng/Vector3.h"
|
||||
#define GEDENG_MAIN
|
||||
#include <Gedeng.h>
|
||||
|
||||
@ -68,6 +70,9 @@ class ParallaxApp : public Gedeng::Application {
|
||||
// Quad which is rendered onto
|
||||
quad_mesh.rotate(delta * 25.0f, glm::normalize(glm::vec3(0.0, 0.0, 1.0)));
|
||||
quad_mesh.render(render_shader);
|
||||
|
||||
debug_text.render_text(Gedeng::String("This is sample text"), 25.0f, 25.0f, 1.0f,
|
||||
Gedeng::Vector3(1.0, 1.0, 0.0));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -86,6 +91,8 @@ class ParallaxApp : public Gedeng::Application {
|
||||
Gedeng::Texture normal;
|
||||
|
||||
Gedeng::QuadMesh quad_mesh;
|
||||
|
||||
Gedeng::TextLabel debug_text;
|
||||
};
|
||||
|
||||
Gedeng::Application *Gedeng::create_application() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user