shmup
This commit is contained in:
223
application/include/overlay.hpp
Normal file
223
application/include/overlay.hpp
Normal file
@@ -0,0 +1,223 @@
|
||||
#ifndef OVERLAY_HPP
|
||||
#define OVERLAY_HPP
|
||||
|
||||
/*
|
||||
"""
|
||||
Portions of this software are copyright © 2025 The FreeType
|
||||
Project (https://freetype.org). All rights reserved.
|
||||
"""
|
||||
*/
|
||||
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <open_engine.hpp>
|
||||
|
||||
#include "freetype/fttypes.h"
|
||||
#include "open_engine/events/event.hpp"
|
||||
#include "open_engine/logging.hpp"
|
||||
#include "open_engine/renderer/shader.hpp"
|
||||
#include <freetype2/ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <map>
|
||||
|
||||
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
|
||||
FT_Long advance; // Offset to advance to next glyph
|
||||
};
|
||||
|
||||
class Overlay : public OpenEngine::Layer
|
||||
{
|
||||
public:
|
||||
Overlay()
|
||||
{};
|
||||
|
||||
~Overlay() {};
|
||||
|
||||
void RenderText(std::string text, float x, float y, float scale, glm::vec3 color)
|
||||
{
|
||||
// activate corresponding render state
|
||||
text_shader->Bind();
|
||||
text_shader->SetVec3("textColor", glm::vec3(color.x, color.y, color.z));
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
// iterate through all characters
|
||||
std::string::const_iterator c;
|
||||
for (c = text.begin(); c != text.end(); c++)
|
||||
{
|
||||
Character ch = characters[*c];
|
||||
|
||||
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);
|
||||
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)
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
glm::vec2 GetTextSize(const std::string& text, float scale)
|
||||
{
|
||||
float width = 0.0f;
|
||||
float height = 0.0f;
|
||||
|
||||
for (char c : text)
|
||||
{
|
||||
Character ch = characters[c];
|
||||
width += (ch.advance >> 6) * scale; // Accumulate total width
|
||||
|
||||
// Track the maximum height
|
||||
float char_height = ch.size.y * scale;
|
||||
if (char_height > height)
|
||||
height = char_height;
|
||||
}
|
||||
|
||||
return glm::vec2(width, height);
|
||||
}
|
||||
|
||||
void RenderTextCentered(std::string text, float center_x, float center_y, float scale, glm::vec3 color)
|
||||
{
|
||||
glm::vec2 text_size = GetTextSize(text, scale);
|
||||
|
||||
// Calculate top-left position to make text centered
|
||||
float x = center_x - (text_size.x / 2.0f);
|
||||
float y = center_y - (text_size.y / 2.0f);
|
||||
|
||||
RenderText(text, x, y, scale, color);
|
||||
}
|
||||
|
||||
private:
|
||||
void OnAttach() override
|
||||
{
|
||||
OE_INFO("Loading Freetype...");
|
||||
|
||||
int error;
|
||||
|
||||
FT_Library ft;
|
||||
error = FT_Init_FreeType(&ft);
|
||||
if (error != 0) {
|
||||
OE_ERROR("FREETYPE: Could not init FreeType Library");
|
||||
return;
|
||||
}
|
||||
|
||||
FT_Face face;
|
||||
error = FT_New_Face(ft, "/usr/share/fonts/TTF/JetBrainsMono-Regular.ttf", 0, &face);
|
||||
if (error != 0) {
|
||||
OE_ERROR("FREETYPE: Failed to load font");
|
||||
return;
|
||||
}
|
||||
|
||||
FT_Set_Pixel_Sizes(face, 0, 48);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
for (unsigned char c = 0; c < 128; c++)
|
||||
{
|
||||
// load character glyph
|
||||
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
|
||||
{
|
||||
OE_ERROR("FREETYTPE: Failed to load Glyph: {}", c);
|
||||
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),
|
||||
face->glyph->advance.x
|
||||
};
|
||||
characters.insert(std::pair<char, Character>(c, character));
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
text_shader = OpenEngine::Shader::Create("assets/shaders/text.glsl");
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
void OnUpdate() override
|
||||
{
|
||||
text_shader->Bind();
|
||||
int width = OpenEngine::Application::Get().GetWindow().GetWidth();
|
||||
int height = OpenEngine::Application::Get().GetWindow().GetHeight();
|
||||
|
||||
projection = glm::ortho(0.0f, static_cast<float>(width),
|
||||
0.0f, static_cast<float>(height));
|
||||
|
||||
text_shader->SetMat4("u_ViewProjection", projection);
|
||||
|
||||
float x = height - 40;
|
||||
float y = 0;
|
||||
//RenderText("Test String", 0.0f, 0.0f, 1.0f, {0.8f, 0.3f, 0.2f});
|
||||
};
|
||||
|
||||
void OnEvent(OpenEngine::Event& event) override
|
||||
{
|
||||
};
|
||||
|
||||
private:
|
||||
std::map<char, Character> characters;
|
||||
OpenEngine::Ref<OpenEngine::Shader> text_shader;
|
||||
glm::mat4 projection;
|
||||
|
||||
unsigned int VAO, VBO;
|
||||
};
|
||||
|
||||
#endif // OVERLAY_HPP
|
||||
Reference in New Issue
Block a user