Initial font meshing setup. Also various cleanups.

This commit is contained in:
Relintai 2024-01-04 14:37:11 +01:00
parent 5a572e2dc5
commit 80172bfee4
6 changed files with 330 additions and 198 deletions

View File

@ -98,6 +98,8 @@ void GameScene::render() {
_font_test_sprite->render();
_font_test_mi->render();
//TextRenderer::get_singleton()->font_init();
//TextRenderer::get_singleton()->font_print("test");
}
@ -120,7 +122,7 @@ GameScene::GameScene() {
_font_test_sprite = memnew(Sprite);
_font_test_mat = new TextureMaterial2D();
_font_test_mat = memnew(TextureMaterial2D());
_font_test_mat->texture = _font->get_texture().ptr();
_font_test_sprite->mesh_instance->material = _font_test_mat;
_font_test_sprite->width = _font->get_atlas_width();
@ -128,6 +130,17 @@ GameScene::GameScene() {
_font_test_sprite->transform.set_origin(Vector2(1000, 100));
_font_test_sprite->update_mesh();
_font_test_mesh.instance();
_font_test_mi = memnew(MeshInstance2D());
_font_test_mi->material = _font_test_mat;
_font_test_mi->mesh = _font_test_mesh.ptr();
//_font_test_mi->transform.scale(Vector2(32, 32));
_font_test_mi->transform.set_origin(Vector2(1000, 500));
_font->generate_mesh("asdfghjklqwetyuiop\nzxcvbnm", _font_test_mesh);
_font_test_mesh->upload();
image.instance();
image->load_from_file("icon.png");
//image->bumpmap_to_normalmap();

View File

@ -13,6 +13,7 @@
#include "render_core/texture_material_2d.h"
#include "render_objects/camera_2d.h"
#include "render_objects/camera_3d.h"
#include "render_objects/mesh_instance_2d.h"
#include "render_objects/mesh_instance_3d.h"
#include "render_objects/sprite.h"
#include "render_objects/tile_map.h"
@ -41,6 +42,9 @@ public:
Sprite *_font_test_sprite;
TextureMaterial2D *_font_test_mat;
Ref<Mesh> _font_test_mesh;
MeshInstance2D *_font_test_mi;
Camera2D *camera_2d;
TileMap *tile_map;
Sprite *sprite;

View File

@ -43,6 +43,7 @@
#include "font_data_tables.inc.h"
#include "render_core/image.h"
#include "render_core/mesh.h"
#include "render_core/texture.h"
void Font::load_default(const float size, const uint32_t flags) {
@ -287,23 +288,33 @@ void Font::font_face_from_mem(const void *ttf_data, uint32_t ttf_len, float font
}
stbtt_packedchar *cd = &_cdata[cp - _begin];
// if(cd->x1==cd->x0) { _iter2cp[i] = _cp2iter[cp - _begin] = 0xFFFD; continue; }
TextureOffset offset;
offset.x = cd->x0 / (double)_width;
offset.y = cd->y0 / (double)_height;
offset.w = (cd->x1 - cd->x0) / (double)_width;
offset.h = (cd->y1 - cd->y0) / (double)_height;
offset.x0 = cd->x0 / (double)_width;
offset.y0 = cd->y0 / (double)_height;
//offset.x1 = (cd->x1 - cd->x0) / (double)_width;
//offset.y1 = (cd->y1 - cd->y0) / (double)_height;
offset.x1 = cd->x1 / (double)_width;
offset.y1 = cd->y1 / (double)_height;
offset.xoff = cd->xoff / (double)_width;
offset.yoff = cd->yoff / (double)_height;
offset.woff = cd->xoff2 / (double)_width;
offset.hoff = cd->yoff2 / (double)_height;
//offset.xoff = cd->xoff / (double)_width;
//offset.yoff = cd->yoff / (double)_height;
//offset.xoff2 = cd->xoff / (double)_width;
//offset.yoff2 = cd->yoff / (double)_height;
//offset.xadvance = cd->xadvance / (double)_width;
offset.xoff = cd->xoff;
offset.yoff = cd->yoff;
offset.xoff2 = cd->xoff;
offset.yoff2 = cd->yoff;
offset.xadvance = cd->xadvance;
_texture_offsets.write[i] = offset;
}
_initialized = true;
/*
float *texture_offsets = memnew_arr(float, 8 * _num_glyphs);
@ -355,6 +366,74 @@ void Font::font_face(const char *filename_ttf, float font_size, unsigned flags)
*/
}
Vector2 Font::generate_mesh(const String &p_text, Ref<Mesh> &p_into, const Color &p_color) {
ERR_FAIL_COND_V(!_initialized, Vector2());
ERR_FAIL_COND_V(!p_into.is_valid(), Vector2());
float X = 0;
float Y = 0;
float W = 0;
float L = _ascent * _factor * _scale;
float LL = L; // LL=largest linedist
float current_x_pos = 0;
// parse string
for (int i = 0, end = p_text.length(); i < end; ++i) {
uint32_t ch = p_text[i];
if (ch == '\n') {
// change cursor, advance y, record largest x as width, increase height
if (X > W) {
W = X;
}
X = 0.0;
Y += _linedist * _factor * _scale;
if (i + 1 == end) { //@hack: ensures we terminate the height at the correct position
Y += (_descent + _linegap) * _factor * _scale;
}
continue;
}
int cp = ch - _begin;
//*t++ = X;
//*t++ = Y;
//*t++ = _cp2iter[cp];
//*t++ = col ? col[i] : color;
const TextureOffset &t = _texture_offsets[_cp2iter[cp]];
p_into->add_uv(t.x0, t.y0);
p_into->add_color(p_color);
p_into->add_vertex2(current_x_pos, Y);
p_into->add_uv(t.x1, t.y1);
p_into->add_color(p_color);
p_into->add_vertex2(current_x_pos + 20, Y + 20);
p_into->add_uv(t.x0, t.y1);
p_into->add_color(p_color);
p_into->add_vertex2(current_x_pos, Y + 20);
p_into->add_uv(t.x1, t.y0);
p_into->add_color(p_color);
p_into->add_vertex2(current_x_pos + 20, Y + 20);
p_into->add_triangle(1, 0, 2);
p_into->add_triangle(0, 1, 3);
current_x_pos += 20;
X += _cdata[cp].xadvance * _scale;
}
return Vector2(W * W > X * X ? W : X, Y * Y > LL * LL ? Y : LL).abs();
}
void Font::font_draw_cmd(const float *glyph_data, int glyph_idx, float factor, Vector2 offset) {
/*
// Backup GL state
@ -533,43 +612,65 @@ Vector2 Font::font_draw_ex(const String &text, Vector2 offset, const char *col,
return Vector2();
}
// Return cursor
Vector2 Font::font_xy() {
return gotoxy;
}
// Relocate cursor
void Font::font_goto(float x, float y) {
gotoxy = Vector2(x, y);
}
// Calculate the size of a string, in the pixel size specified. Count stray newlines too.
Vector2 Font::font_rect(const String &str) {
return font_draw_ex(str, gotoxy, NULL, NULL);
}
Vector2 Font::get_string_size(const String &text) {
ERR_FAIL_COND_V(!_initialized, Vector2());
Font::font_metrics_t Font::font_metrics(const String &text) {
font_metrics_t m = { 0 };
// sanity checks
int len = text.length();
/*
// ready
float X = 0;
float Y = 0;
float W = 0;
float L = _ascent * _factor * _scale;
float LL = L; // LL=largest linedist
// parse string
for (int i = 0, end = text.length(); i < end; ++i) {
for (int i = 0; i < len; ++i) {
uint32_t ch = text[i];
if (ch >= 1 && ch <= 6) {
S = ch;
continue;
}
if (ch >= 0x1a && ch <= 0x1f) {
if (fonts[ch - 0x1a].initialized) {
// change face
f = &fonts[ch - 0x1a];
if (ch == '\n') {
// change cursor, advance y, record largest x as width, increase height
if (X > W) {
W = X;
}
X = 0.0;
Y -= _linedist * _factor * _scale;
if (i + 1 == len) { //@hack: ensures we terminate the height at the correct position
Y -= (_descent + _linegap) * _factor * _scale;
}
continue;
}
if (ch >= 1 && ch <= 6) {
L = _ascent * _factor * _scale;
if (L > LL) {
LL = L;
}
continue;
}
int cp = ch - _begin;
//*t++ = X;
//*t++ = Y;
//*t++ = _cp2iter[cp];
//*t++ = col ? col[i] : color;
X += _cdata[cp].xadvance * _scale;
}
*/
return Vector2(W * W > X * X ? W : X, Y * Y > LL * LL ? Y : LL).abs();
}
Font::FontMetrics Font::font_metrics() {
FontMetrics m;
m.ascent = _ascent * _factor * _scale;
m.descent = _descent * _factor * _scale;

View File

@ -5,6 +5,9 @@
// font framework originally from FWK
// - rlyeh, public domain
#include "core/color.h"
#include "core/ustring.h"
#include "object/resource.h"
#include "core/ustring.h"
@ -15,6 +18,7 @@
class Image;
class Texture;
class Mesh;
class Font : public Resource {
SFW_OBJECT(Font, Resource);
@ -51,12 +55,12 @@ public:
// FONT_DEFAULTS = FONT_512 | FONT_NO_OVERSAMPLE | FONT_ASCII,
};
typedef struct font_metrics_t {
struct FontMetrics {
float ascent; // max distance above baseline for all glyphs
float descent; // max distance below baseline for all glyphs
float linegap; // distance betwen ascent of next line and descent of current line
float linedist; // distance between the baseline of two lines (ascent - descent + linegap)
} font_metrics_t;
};
void load_default(const float size, const uint32_t flags = 0);
@ -68,11 +72,10 @@ public:
void font_face_from_mem(const void *ttf_buffer, uint32_t ttf_len, float font_size, uint32_t flags);
// commands
Vector2 font_xy();
void font_goto(float x, float y);
Vector2 generate_mesh(const String &p_text, Ref<Mesh> &p_into, const Color &p_color = Color(1, 1, 1, 1));
Vector2 font_print(const String &text);
Vector2 font_rect(const String &str);
font_metrics_t font_metrics(const String &text);
Vector2 get_string_size(const String &text);
FontMetrics font_metrics();
int get_atlas_width();
int get_atlas_height();
@ -111,23 +114,22 @@ protected:
Ref<Texture> _texture;
struct TextureOffset {
float x;
float y;
float w;
float h;
float x0;
float y0;
float x1;
float y1;
float xoff;
float xoff2;
float xadvance;
float yoff;
float woff;
float hoff;
float yoff2;
};
Vector<TextureOffset> _texture_offsets;
static void font_draw_cmd(const float *glyph_data, int glyph_idx, float factor, Vector2 offset);
Vector2 font_draw_ex(const String &text, Vector2 offset, const char *col, void (*draw_cmd)(const float *, int, float, Vector2));
Vector2 gotoxy;
};
#endif

View File

@ -3,185 +3,191 @@
#include "render_core/shader.h"
void Mesh::add_vertex2(float x, float y) {
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(x);
vertices.push_back(y);
}
void Mesh::add_vertex3(float x, float y, float z) {
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(z);
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(z);
}
void Mesh::add_normal(float x, float y, float z) {
normals.push_back(x);
normals.push_back(y);
normals.push_back(z);
normals.push_back(x);
normals.push_back(y);
normals.push_back(z);
}
void Mesh::add_color(float r, float g, float b, float a) {
colors.push_back(r);
colors.push_back(g);
colors.push_back(b);
colors.push_back(a);
colors.push_back(r);
colors.push_back(g);
colors.push_back(b);
colors.push_back(a);
}
void Mesh::add_color(const Color &p_color) {
colors.push_back(p_color.r);
colors.push_back(p_color.g);
colors.push_back(p_color.b);
colors.push_back(p_color.a);
}
void Mesh::add_uv(float u, float v) {
uvs.push_back(u);
uvs.push_back(v);
uvs.push_back(u);
uvs.push_back(v);
}
void Mesh::add_index(uint32_t index) {
indices.push_back(index);
indices.push_back(index);
}
void Mesh::add_triangle(uint32_t i1, uint32_t i2, uint32_t i3) {
indices.push_back(i1);
indices.push_back(i2);
indices.push_back(i3);
indices.push_back(i1);
indices.push_back(i2);
indices.push_back(i3);
}
void Mesh::clear() {
vertices.clear();
normals.clear();
colors.clear();
uvs.clear();
indices.clear();
vertices.clear();
normals.clear();
colors.clear();
uvs.clear();
indices.clear();
}
void Mesh::upload() {
if (vertices.size() == 0) {
return;
}
if (vertices.size() == 0) {
return;
}
if (!VBO) {
glGenBuffers(1, &VBO);
}
if (!VBO) {
glGenBuffers(1, &VBO);
}
vertices_vbo_size = sizeof(float) * vertices.size();
normals_vbo_size = sizeof(float) * normals.size();
colors_vbo_size = sizeof(float) * colors.size();
uvs_vbo_size = sizeof(float) * uvs.size();
indices_vbo_size = sizeof(float) * indices.size();
vertices_vbo_size = sizeof(float) * vertices.size();
normals_vbo_size = sizeof(float) * normals.size();
colors_vbo_size = sizeof(float) * colors.size();
uvs_vbo_size = sizeof(float) * uvs.size();
indices_vbo_size = sizeof(float) * indices.size();
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, NULL, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size + uvs_vbo_size, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_vbo_size, vertices.ptr());
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices_vbo_size, vertices.ptr());
if (normals_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size, normals_vbo_size, normals.ptr());
}
if (normals_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size, normals_vbo_size, normals.ptr());
}
if (colors_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size, colors_vbo_size, colors.ptr());
}
if (colors_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size, colors_vbo_size, colors.ptr());
}
if (uvs_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size, uvs_vbo_size, uvs.ptr());
}
if (uvs_vbo_size > 0) {
glBufferSubData(GL_ARRAY_BUFFER, vertices_vbo_size + normals_vbo_size + colors_vbo_size, uvs_vbo_size, uvs.ptr());
}
if (indices_vbo_size > 0) {
if (!IBO) {
glGenBuffers(1, &IBO);
}
if (indices_vbo_size > 0) {
if (!IBO) {
glGenBuffers(1, &IBO);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_vbo_size, indices.ptr(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_vbo_size, indices.ptr(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Mesh::destroy() {
if (VBO) {
glDeleteBuffers(1, &VBO);
VBO = 0;
}
if (VBO) {
glDeleteBuffers(1, &VBO);
VBO = 0;
}
if (IBO) {
glDeleteBuffers(1, &IBO);
IBO = 0;
}
if (IBO) {
glDeleteBuffers(1, &IBO);
IBO = 0;
}
}
void Mesh::render() {
if (vertices.size() == 0) {
return;
}
if (vertices.size() == 0) {
return;
}
if (!Shader::current_shader) {
return;
}
if (!Shader::current_shader) {
return;
}
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(Shader::ATTRIBUTE_POSITION, vertex_dimesions, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(Shader::ATTRIBUTE_POSITION);
glVertexAttribPointer(Shader::ATTRIBUTE_POSITION, vertex_dimesions, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(Shader::ATTRIBUTE_POSITION);
if (normals_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, (void*)(uintptr_t)(vertices_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_NORMAL);
}
if (normals_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_NORMAL, 3, GL_FLOAT, GL_FALSE, 0, (void *)(uintptr_t)(vertices_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_NORMAL);
}
if (colors_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_FALSE, 0, (void*)(uintptr_t)(vertices_vbo_size + normals_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_COLOR);
}
if (colors_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_FALSE, 0, (void *)(uintptr_t)(vertices_vbo_size + normals_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_COLOR);
}
if (uvs_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_UV, 2, GL_FLOAT, GL_FALSE, 0, (void*)(uintptr_t)(vertices_vbo_size + normals_vbo_size + colors_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_UV);
}
if (uvs_vbo_size > 0) {
glVertexAttribPointer(Shader::ATTRIBUTE_UV, 2, GL_FLOAT, GL_FALSE, 0, (void *)(uintptr_t)(vertices_vbo_size + normals_vbo_size + colors_vbo_size));
glEnableVertexAttribArray(Shader::ATTRIBUTE_UV);
}
if (indices_vbo_size > 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
if (indices_vbo_size > 0) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (GLvoid*)0);
} else {
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
}
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (GLvoid *)0);
} else {
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
}
glDisableVertexAttribArray(Shader::ATTRIBUTE_POSITION);
glDisableVertexAttribArray(Shader::ATTRIBUTE_POSITION);
if (normals_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_NORMAL);
}
if (normals_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_NORMAL);
}
if (colors_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_COLOR);
}
if (colors_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_COLOR);
}
if (uvs_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_UV);
}
if (uvs_vbo_size > 0) {
glDisableVertexAttribArray(Shader::ATTRIBUTE_UV);
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
Mesh::Mesh() {
VBO = 0;
IBO = 0;
VBO = 0;
IBO = 0;
vertex_dimesions = 3;
vertex_dimesions = 3;
vertices_vbo_size = 0;
normals_vbo_size = 0;
colors_vbo_size = 0;
uvs_vbo_size = 0;
indices_vbo_size = 0;
vertices_vbo_size = 0;
normals_vbo_size = 0;
colors_vbo_size = 0;
uvs_vbo_size = 0;
indices_vbo_size = 0;
}
Mesh::Mesh(int vert_dim) {
VBO = 0;
IBO = 0;
VBO = 0;
IBO = 0;
vertex_dimesions = vert_dim;
vertex_dimesions = vert_dim;
vertices_vbo_size = 0;
normals_vbo_size = 0;
colors_vbo_size = 0;
uvs_vbo_size = 0;
indices_vbo_size = 0;
vertices_vbo_size = 0;
normals_vbo_size = 0;
colors_vbo_size = 0;
uvs_vbo_size = 0;
indices_vbo_size = 0;
}
Mesh::~Mesh() {
destroy();
clear();
destroy();
clear();
}

View File

@ -3,49 +3,55 @@
#include "core/vector.h"
#include <inttypes.h>
#include "core/color.h"
#include "object/resource.h"
#include "render_core/3rd_glad.h"
class Mesh {
class Mesh : public Resource {
SFW_OBJECT(Mesh, Resource);
public:
void add_vertex2(float x, float y);
void add_vertex3(float x, float y, float z);
void add_vertex2(float x, float y);
void add_vertex3(float x, float y, float z);
void add_normal(float x, float y, float z);
void add_color(float r = 1, float g = 1, float b = 1, float a = 1);
void add_normal(float x, float y, float z);
void add_color(float r = 1, float g = 1, float b = 1, float a = 1);
void add_color(const Color &p_color);
void add_uv(float u, float v);
void add_uv(float u, float v);
void add_index(uint32_t index);
void add_triangle(uint32_t i1, uint32_t i2, uint32_t i3);
void add_index(uint32_t index);
void add_triangle(uint32_t i1, uint32_t i2, uint32_t i3);
void clear();
void clear();
void upload();
void destroy();
void render();
void upload();
void destroy();
void render();
Mesh();
Mesh(int vert_dim);
virtual ~Mesh();
Mesh();
Mesh(int vert_dim);
virtual ~Mesh();
GLuint VBO;
GLuint IBO;
GLuint VBO;
GLuint IBO;
int vertex_dimesions;
int vertex_dimesions;
Vector<float> vertices;
Vector<float> normals;
Vector<float> colors;
Vector<float> uvs;
Vector<uint32_t> indices;
Vector<float> vertices;
Vector<float> normals;
Vector<float> colors;
Vector<float> uvs;
Vector<uint32_t> indices;
protected:
uint32_t vertices_vbo_size;
uint32_t normals_vbo_size;
uint32_t colors_vbo_size;
uint32_t uvs_vbo_size;
uint32_t indices_vbo_size;
uint32_t vertices_vbo_size;
uint32_t normals_vbo_size;
uint32_t colors_vbo_size;
uint32_t uvs_vbo_size;
uint32_t indices_vbo_size;
};
#endif // MESH_H