Compare commits

...

7 Commits

Author SHA1 Message Date
c62b58aa16 Font cache
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m34s
2024-07-06 22:51:25 -04:00
11ce9ac5fe ReCI test
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m18s
2024-07-05 11:44:34 -04:00
7310825ddd ReCI test
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m28s
2024-07-05 11:38:48 -04:00
513dc1e332 fixed syntax error in reci script
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m2s
2024-07-05 10:56:43 -04:00
63bbb8794e Wrote local ReCI script for JGL
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 39s
2024-07-05 10:54:59 -04:00
178f328728 ReCI test
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 58s
2024-07-05 09:35:51 -04:00
1c74ee9c71 Add ReCI build test 2024-07-05 09:30:20 -04:00
8 changed files with 284 additions and 57 deletions

View File

@@ -0,0 +1,24 @@
name: Run ReCI Build Test
run-name: Run ReCI Build Test For ${{ gitea.repository }}.
on: [push]
jobs:
Explore-Gitea-Actions:
runs-on: ubuntu-22.04
env:
RECI_GIT: https://git.redacted.cc/maxine/ReCI
RECI: /RECI
steps:
- run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event."
- run: echo "This job is now running on a ${{ runner.os }} server hosted by Gitea!"
- run: echo "The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
- name: Check out repository code
uses: actions/checkout@v3
- run: echo "The ${{ gitea.repository }} repository has been cloned to the runner."
- run: echo "The workflow is now ready to run your tests on the runner."
- run: echo "Install toolchain and run ReCI build test"
- run: apt-get update && apt-get install -y git && git clone $RECI_GIT $RECI
- run: bash $RECI/scripts/setup_build_tools.sh
- run: bash reci/scripts/install_build_dependencies.sh
- run: bash $RECI/scripts/run_buildtest.sh ${{ gitea.repository }}
- run: echo "This job's status is ${{ job.status }}."

View File

@@ -8,4 +8,5 @@
# Non-Goals
* Full Rendering Engine
* OpenGL/Vulkan Wrapper
* Asset Loading & Management
* Asset Loading & Management

53
include/JGL/FontCache.h Normal file
View File

@@ -0,0 +1,53 @@
#pragma once
#include <vector>
#include <glad/glad.h>
namespace JGL {
class CachedGlyph;
class CachedFont;
class FontCache;
}
class JGL::CachedGlyph {
private:
GLuint texture = 0;
char character;
public:
int x2offset = 0, y2offset = 0, w = 0, h = 0;
float advanceX = 0, advanceY = 0;
//CachedGlyph(GLuint texture_id, char c);
CachedGlyph(GLuint texture_id, char c, float x2o, float y2o, float w, float h, float advX, float advY);
char getCharacter();
const GLuint* getTexture();
};
class JGL::CachedFont {
private:
std::vector<CachedGlyph*> glyphs{};
unsigned int font_size = 0;
unsigned int font_index = 0;
public:
void appendGlyph(CachedGlyph* glyph);
void eraseGlyph(CachedGlyph* glyph);
void eraseGlyph(char c);
void eraseGlyph(GLuint texture_id);
unsigned int getFontSize();
unsigned int getFontIndex();
CachedGlyph* getGlyph(char c);
std::vector<CachedGlyph*>* getGlyphs();
CachedFont(unsigned int font_size, unsigned int font_index);
};
class JGL::FontCache {
private:
std::vector<CachedFont*> cachedFonts = {};
public:
std::vector<CachedFont*>* getFonts();
CachedFont* getFont(unsigned int font_size, unsigned int font_index);
void appendFont(CachedFont* font);
void newFont(unsigned int font_size, unsigned int font_index);
void eraseFont(CachedFont* font);
void purgeCache();
};

View File

@@ -6,6 +6,7 @@
#include <string>
#include <iostream>
#include <JGL/Color3.h>
#include <JGL/FontCache.h>
#include <J3ML/LinearAlgebra.h>
#include <J3ML/LinearAlgebra/Vector2.h>
#include <J3ML/LinearAlgebra/Vector3.h>
@@ -49,7 +50,9 @@ namespace JGL {
};
bool InitTextEngine();
inline FontCache fontCache;
int LoadFont(const std::string& font_path);
void UnloadFont(int font_index);
// TODO: implement correct coloring

View File

@@ -34,14 +34,9 @@ class JGLDemoWindow : public ReWindow::RWindow
public:
JGLDemoWindow() : ReWindow::RWindow() {}
JGLDemoWindow(const std::string& title, int width, int height) :
ReWindow::RWindow(title, width, height)
{
JGLDemoWindow(const std::string& title, int width, int height) : ReWindow::RWindow(title, width, height){}
}
void initGL()
{
void initGL() {
gladLoadGL();
glMatrixMode(GL_PROJECTION);
@@ -64,7 +59,6 @@ public:
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, getSize().x, getSize().y, 0, -1, 1);

View File

@@ -0,0 +1,7 @@
source $RECI/shlib/info.sh
INFO "Installing build dependencies for JGL"
GROUP="Install build dependencies" RUN '
apt-get install -yq libgl1-mesa-dev libfreetype-dev
'

119
src/FontCache.cpp Normal file
View File

@@ -0,0 +1,119 @@
#include <JGL/FontCache.h>
using namespace JGL;
char CachedGlyph::getCharacter() {
return character;
}
const GLuint* CachedGlyph::getTexture() {
return &texture;
}
CachedGlyph::CachedGlyph(GLuint texture_id, char c, float x2offset, float y2offset, float w, float h, float advanceX, float advanceY) {
texture = texture_id;
character = c;
this->x2offset = x2offset;
this->y2offset = y2offset;
this->w = w;
this->h = h;
this->advanceX = advanceX;
this->advanceY = advanceY;
}
void JGL::CachedFont::appendGlyph(JGL::CachedGlyph* glyph) {
glyphs.push_back(glyph);
}
unsigned int JGL::CachedFont::getFontSize() {
return font_size;
}
unsigned int JGL::CachedFont::getFontIndex() {
return font_index;
}
CachedGlyph* JGL::CachedFont::getGlyph(char c) {
for (const auto& g : glyphs)
if (c == g->getCharacter())
return g;
return nullptr;
}
CachedFont::CachedFont(unsigned int font_size, unsigned int font_index) {
this->font_size = font_size;
this->font_index = font_index;
}
void CachedFont::eraseGlyph(CachedGlyph* glyph) {
if (glyph == nullptr)
return;
for (int i = 0; i < glyphs.size(); i++)
if (glyphs[i] == glyph)
glDeleteTextures(1, glyphs[i]->getTexture()),
delete glyphs[i],
glyphs.erase(glyphs.begin() + i);
}
void CachedFont::eraseGlyph(char c) {
for (int i = 0; i < glyphs.size(); i++)
if (glyphs[i]->getCharacter() == c)
glDeleteTextures(1, glyphs[i]->getTexture()),
delete glyphs[i],
glyphs.erase(glyphs.begin() + i);
}
void CachedFont::eraseGlyph(GLuint texture_id) {
for (int i = 0; i < glyphs.size(); i++)
if (glyphs[i]->getTexture() == &texture_id)
glDeleteTextures(1, glyphs[i]->getTexture()),
delete glyphs[i],
glyphs.erase(glyphs.begin() + i);
}
std::vector<CachedGlyph*>* CachedFont::getGlyphs() {
return &glyphs;
}
void FontCache::appendFont(CachedFont* font) {
cachedFonts.push_back(font);
}
void FontCache::newFont(unsigned int font_size, unsigned int font_index) {
auto* font = new CachedFont(font_size, font_index);
cachedFonts.push_back(font);
}
void FontCache::eraseFont(CachedFont* font) {
for (int i = 0; i < cachedFonts.size(); i++) {
if (cachedFonts[i] == font) {
for (auto& g: *cachedFonts[i]->getGlyphs())
cachedFonts[i]->eraseGlyph(g);
delete cachedFonts[i];
cachedFonts.erase(cachedFonts.begin() + i);
}
}
}
void FontCache::purgeCache() {
//Remove every font from the cache.
for (const auto& font : cachedFonts)
eraseFont(font);
cachedFonts = {};
}
std::vector<CachedFont*>* FontCache::getFonts() {
return &cachedFonts;
}
CachedFont* FontCache::getFont(unsigned int font_size, unsigned int font_index) {
if (cachedFonts.empty())
return nullptr;
for (auto* f : cachedFonts)
if (f->getFontIndex() == font_index && f->getFontSize() == font_size)
return f;
return nullptr;
}

View File

@@ -37,6 +37,7 @@ namespace JGL
int LoadFont(const std::string &font_path) {
if (ft == nullptr)
return -1;
Font font;
if (FT_New_Face(ft, font_path.c_str(), 0, &font.face)) {
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
@@ -47,9 +48,9 @@ namespace JGL
for (const auto& f : faces)
if (f.index >= newIndex)
newIndex = f.index + 1;
font.index = newIndex;
faces.push_back(font);
std::cout << "Loaded font from " << font_path << " with index " << newIndex << std::endl;
return newIndex;
}
@@ -61,13 +62,12 @@ namespace JGL
faces.erase(faces.begin() + i);
}
namespace J2D
{
namespace J2D {
void FillRect2D(const Color3 &color, const Vector2 &pos, const Vector2 &size) {
auto vp_pos = pos;
auto vp_size = size;
glBegin(GL_QUADS);
glColor3f(color.r/255.f, color.g/255.f, color.b/255.f);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(vp_pos.x, vp_pos.y);
glVertex2f(vp_pos.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y + vp_size.y);
@@ -122,9 +122,8 @@ namespace JGL
glBegin(GL_LINE_LOOP);
GLfloat angle;
glColor3f(color.r, color.g, color.b);
float step = (2.f * M_PI) / (float)subdivisions;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step)
{
float step = (2.f * M_PI) / (float) subdivisions;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step) {
GLfloat x = radius * sin(angle);
GLfloat y = radius * cos(angle);
x += center.x;
@@ -138,9 +137,8 @@ namespace JGL
glBegin(GL_POLYGON);
GLfloat angle;
glColor3f(color.r, color.g, color.b);
float step = (2.f * M_PI) / (float)subdivisions;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step)
{
float step = (2.f * M_PI) / (float) subdivisions;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step) {
GLfloat x = radius * sin(angle);
GLfloat y = radius * cos(angle);
x += center.x;
@@ -150,20 +148,18 @@ namespace JGL
glEnd();
}
void OutlineTriangle2D(const Color3& color, const Triangle2D& tri)
{
void OutlineTriangle2D(const Color3 &color, const Triangle2D &tri) {
glBegin(GL_LINE_LOOP);
glColor3f(color.r/255.f, color.g/255.f, color.b/255.f);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(tri.A.x, tri.A.y);
glVertex2f(tri.B.x, tri.B.y);
glVertex2f(tri.C.x, tri.C.y);
glEnd();
}
void FillTriangle2D(const Color3& color, const Triangle2D& tri)
{
void FillTriangle2D(const Color3 &color, const Triangle2D &tri) {
glBegin(GL_LINE_LOOP);
glColor3f(color.r/255.f, color.g/255.f, color.b/255.f);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(tri.A.x, tri.A.y);
glVertex2f(tri.B.x, tri.B.y);
glVertex2f(tri.C.x, tri.C.y);
@@ -174,46 +170,79 @@ namespace JGL
glUseProgram(0); // Fixed-function pipeline.
Font font{};
CachedFont* cachedFont = fontCache.getFont(size, font_index);
//If the font doesn't exist in the cache yet.
if (!cachedFont) {
fontCache.newFont(size, font_index);
cachedFont = fontCache.getFont(size, font_index);
}
//Set up the regular font.
for (const auto& f : faces)
if (f.index == font_index)
font = f;
if (font.face == NULL) {
std::cout << "null font" << std::endl;
if (font.face == nullptr)
return;
}
GLfloat currentColor[4];
glGetFloatv(GL_CURRENT_COLOR, currentColor);
glColor3f(color.r/255.f, color.g/255.f, color.b/255.f);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, 1.0f);
FT_Set_Pixel_Sizes(font.face, 0, size);
std::vector<GLuint> textures(text.length());
for (int i = 0; i < text.length(); i++)
{
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
continue;
FT_GlyphSlot g = font.face->glyph;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &textures.at(i));
glBindTexture(GL_TEXTURE_2D, textures[i]);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
float x2 = x + g->bitmap_left * scale;
float y2 = -y - g->bitmap_top * scale; // Adjust y-coordinate
float w = g->bitmap.width * scale;
float h = g->bitmap.rows * scale;
//For each character
for (int i = 0; i < text.length(); i++) {
float x2, y2, w, h;
//If the font is in the cache already.
if (cachedFont->getGlyph(text.c_str()[i])) {
CachedGlyph* glyph = cachedFont->getGlyph(text.c_str()[i]);
glBindTexture(GL_TEXTURE_2D, *glyph->getTexture());
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
x2 = x + glyph->x2offset * scale;
y2 = -y - glyph->y2offset * scale; // Adjust y-coordinate
w = glyph->w * scale;
h = glyph->h * scale;
x += glyph->advanceX * scale;
y += glyph->advanceY * scale;
} else {
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
continue;
FT_GlyphSlot g = font.face->glyph;
glGenTextures(1, &textures.at(i));
glBindTexture(GL_TEXTURE_2D, textures[i]);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
x2 = x + g->bitmap_left * scale;
y2 = -y - g->bitmap_top * scale; // Adjust y-coordinate
w = g->bitmap.width * scale;
h = g->bitmap.rows * scale;
x += (g->advance.x >> 6) * scale;
y += (g->advance.y >> 6) * scale;
cachedFont->appendGlyph(new CachedGlyph(textures.at(i), text.c_str()[i], g->bitmap_left, g->bitmap_top, g->bitmap.width, g->bitmap.rows, (g->advance.x >> 6), (g->advance.y >> 6)));
}
glBegin(GL_TRIANGLES);
@@ -236,12 +265,10 @@ namespace JGL
glVertex2f(x2 + w, y2);
glEnd();
x += (g->advance.x >> 6) * scale;
y += (g->advance.y >> 6) * scale;
}
for (unsigned int& texture : textures)
glDeleteTextures(1, &texture);
//for (unsigned int& texture : textures)
//glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
@@ -250,7 +277,6 @@ namespace JGL
}
}
namespace J3D
{
void DrawLine3D(const Color3& color, const Vector3& A, const Vector3& B, float thickness)