From 7b6a257f4ed7f5b0dcb8f6eb1c41b4369052a54e Mon Sep 17 00:00:00 2001 From: DarkGod <darkgod@net-core.org> Date: Mon, 30 Nov 2020 17:04:53 +0100 Subject: [PATCH] cur work --- .../data/gfx/shaders/default/text.frag | 9 +- game/engines/default/engine/Module.lua | 1 + game/engines/default/modules/boot/load.lua | 2 + game/modules/tome/load.lua | 3 + src/font.cpp | 21 ++- src/font.hpp | 10 +- src/freetype-gl/texture-font.c | 6 +- src/renderer-moderngl/TextObject.cpp | 163 ++++++++++++++---- src/renderer-moderngl/TextObject.hpp | 7 +- src/renderer-moderngl/renderer-lua.cpp | 21 ++- 10 files changed, 202 insertions(+), 41 deletions(-) diff --git a/game/engines/default/data/gfx/shaders/default/text.frag b/game/engines/default/data/gfx/shaders/default/text.frag index 15ae4028ee..3172a30226 100644 --- a/game/engines/default/data/gfx/shaders/default/text.frag +++ b/game/engines/default/data/gfx/shaders/default/text.frag @@ -61,8 +61,13 @@ const float glyph_center = 0.50; void main(void) { vec4 color = texture2D(tex, te4_uv); - float dist = color.a; - + float dist = color.r; + if (outline) { + dist = color.g; + if (bold > 0.0) dist = pow(dist, 0.85); + } else { + if (bold > 0.0) dist = sqrt(dist); + } // Normal // float width = 0.3; diff --git a/game/engines/default/engine/Module.lua b/game/engines/default/engine/Module.lua index 30c6777b37..be8a0a7b57 100644 --- a/game/engines/default/engine/Module.lua +++ b/game/engines/default/engine/Module.lua @@ -939,6 +939,7 @@ function _M:instanciate(mod, name, new_game, no_reboot, extra_module_info) -- Reset white space breaking core.display.breakTextAllCharacter(false) + core.renderer.textconf.defaultOutline(0) -- Turn based by default core.game.setRealtime(0) diff --git a/game/engines/default/modules/boot/load.lua b/game/engines/default/modules/boot/load.lua index 85d8317f22..01ecc9f3f8 100644 --- a/game/engines/default/modules/boot/load.lua +++ b/game/engines/default/modules/boot/load.lua @@ -20,6 +20,8 @@ -- We are running, set a flag so that if we crash we will restart into safe mode util.setForceSafeBoot() +core.renderer.textconf.defaultOutline(1) + -- This file loads the game module, and loads data local KeyBind = require "engine.KeyBind" local DamageType = require "engine.DamageType" diff --git a/game/modules/tome/load.lua b/game/modules/tome/load.lua index b03e4d71a7..6c885b5cee 100644 --- a/game/modules/tome/load.lua +++ b/game/modules/tome/load.lua @@ -20,6 +20,9 @@ -- Configure Map --dofile("/mod/map_config.lua") +-- We want nice outlined fonts! +core.renderer.textconf.defaultOutline(1) + -- Switch to realtime mode, to get more accurate FPS core.game.setRealtime(1) diff --git a/src/font.cpp b/src/font.cpp index 2f7223e9c0..d0b82a4b94 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -87,9 +87,10 @@ FontKind::FontKind(string &name) : fontname(name) { PHYSFS_close(fff); atlas = texture_atlas_new(256, DEFAULT_ATLAS_H, 1); - font = texture_font_new_from_memory(atlas, 32, font_mem, font_mem_size); + atlas_outline = texture_atlas_new(256, DEFAULT_ATLAS_H, 1); + font = texture_font_new_from_memory(atlas, BASE_FONT_SIZE, font_mem, font_mem_size); // font->rendermode = RENDER_SIGNED_DISTANCE_FIELD; - // texture_font_load_glyphs(font, default_atlas_chars.c_str()); + texture_font_load_glyphs(font, default_atlas_chars.c_str()); lineskip = font->height; glGenTextures(1, &atlas->id); @@ -108,13 +109,27 @@ FontKind::~FontKind() { glDeleteTextures(1, &atlas->id); texture_font_delete(font); texture_atlas_delete(atlas); + texture_atlas_delete(atlas_outline); delete[] font_mem; } void FontKind::updateAtlas() { if (!atlas->changed) return; glBindTexture(GL_TEXTURE_2D, atlas->id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, atlas->width, atlas->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, atlas->data); + + unsigned char data[atlas->width * atlas->height * 4]; + for (uint32_t i = 0; i < atlas->width; i++) { + for (uint32_t j = 0; j < atlas->height; j++) { + uint32_t idx = (j * atlas->width + i); + data[idx*4+0] = atlas->data[idx]; + data[idx*4+1] = atlas_outline->data[idx]; + data[idx*4+2] = 0; + data[idx*4+3] = 1; + } + } + + // glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, atlas->width, atlas->height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, atlas->data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, atlas->width, atlas->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); atlas->changed = false; } diff --git a/src/font.hpp b/src/font.hpp index 99fce6bf5f..b8f64cde57 100644 --- a/src/font.hpp +++ b/src/font.hpp @@ -37,6 +37,7 @@ using namespace std; #define DEFAULT_ATLAS_W 2048 #define DEFAULT_ATLAS_H 2048 +#define BASE_FONT_SIZE 32 typedef enum { FONT_STYLE_NORMAL, @@ -63,6 +64,7 @@ protected: int32_t font_mem_size; float lineskip; ftgl::texture_atlas_t *atlas; + ftgl::texture_atlas_t *atlas_outline; ftgl::texture_font_t *font; CodepointGlyphMap glyph_map_normal; @@ -84,16 +86,20 @@ public: inline ftgl::texture_glyph_t* getGlyph(uint32_t codepoint) { CodepointGlyphMap *glyph_map = &glyph_map_normal; - if (font->rendermode == ftgl::RENDER_OUTLINE_POSITIVE) glyph_map = &glyph_map_outline; + if (font->rendermode == ftgl::RENDER_OUTLINE_EDGE) { + glyph_map = &glyph_map_outline; + } auto it = glyph_map->find(codepoint); if (it != glyph_map->end()) return it->second; + if (font->rendermode == ftgl::RENDER_OUTLINE_EDGE) font->atlas = atlas_outline; ftgl::texture_glyph_t *g = ftgl::texture_font_get_glyph(font, codepoint); if (g) { std::pair<uint32_t, ftgl::texture_glyph_t*> p(codepoint, g); glyph_map->insert(p); } + if (font->rendermode == ftgl::RENDER_OUTLINE_EDGE) font->atlas = atlas; return g; } }; @@ -104,7 +110,7 @@ public: float size; float scale; - FontInstance(FontKind *fk, float size) : kind(fk), scale(size / 32.0), size(size) {}; + FontInstance(FontKind *fk, float size) : kind(fk), scale(size / (float)BASE_FONT_SIZE), size(size) {}; glm::vec2 textSize(const char *str, size_t len, font_style style=FONT_STYLE_NORMAL); inline glm::vec2 textSize(string &text, font_style style=FONT_STYLE_NORMAL) { return textSize(text.c_str(), text.size(), style); } diff --git a/src/freetype-gl/texture-font.c b/src/freetype-gl/texture-font.c index 5bbd96a53b..f1d2c94022 100644 --- a/src/freetype-gl/texture-font.c +++ b/src/freetype-gl/texture-font.c @@ -566,10 +566,11 @@ cleanup_stroker: int bottom; } padding = { 0, 0, 2, 2 }; + // HACK: force to always render a distance field if(1|| self->rendermode == RENDER_SIGNED_DISTANCE_FIELD ) { - padding.top = 2; - padding.left = 2; + padding.top = 4; + padding.left = 4; } size_t src_w = ft_bitmap.width/self->atlas->depth; @@ -601,6 +602,7 @@ cleanup_stroker: src_ptr += ft_bitmap.pitch; } + // HACK: force to always render a distance field if(1|| self->rendermode == RENDER_SIGNED_DISTANCE_FIELD ) { unsigned char *sdf = make_distance_mapb( buffer, tgt_w, tgt_h ); diff --git a/src/renderer-moderngl/TextObject.cpp b/src/renderer-moderngl/TextObject.cpp index 635ec423ac..65ce9b885d 100644 --- a/src/renderer-moderngl/TextObject.cpp +++ b/src/renderer-moderngl/TextObject.cpp @@ -36,6 +36,8 @@ extern "C" { #include "colors.hpp" shader_type *DORText::default_shader = NULL; +float DORText::default_outline = 0; +vec4 DORText::default_outline_color = vec4(0, 0, 0, 1); void DORText::cloneInto(DisplayObject* _into) { DORVertexes::cloneInto(_into); @@ -128,25 +130,26 @@ int DORText::addCharQuad(const char *str, size_t len, font_style style, int bx, vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 1.0f : 0.0f)}); } - if (0&&outline) { + if (outline) { font->kind->font->outline_thickness = 2; font->kind->font->rendermode = ftgl::RENDER_OUTLINE_EDGE; ftgl::texture_glyph_t *doutline = font->kind->getGlyph(c); if (doutline) { - // float x0 = bx + x + doutline->offset_x * scale; - // float x1 = x0 + doutline->width * scale; - // float italicx = - doutline->offset_x * scale * italic; - // float y0 = by + (font->kind->font->ascender - doutline->offset_y) * scale + d->height * (base_scale - scale); - // float y1 = y0 + (doutline->height) * scale; - - vertices.push_back({{1+x0+italicx, 1+y0, 0, 1}, {doutline->s0, doutline->t0}, outline_color}); - vertices.push_back({{1+x1+italicx, 1+y0, 0, 1}, {doutline->s1, doutline->t0}, outline_color}); - vertices.push_back({{1+x1, 1+y1, 0, 1}, {doutline->s1, doutline->t1}, outline_color}); - vertices.push_back({{1+x0, 1+y1, 0, 1}, {doutline->s0, doutline->t1}, outline_color}); - vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 3.0f : 2.0f)}); - vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 3.0f : 2.0f)}); - vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 3.0f : 2.0f)}); - vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 3.0f : 2.0f)}); + float x0 = bx + x + doutline->offset_x * scale; + float x1 = x0 + doutline->width * scale; + float italicx = - doutline->offset_x * scale * italic; + float y0 = by + (font->kind->font->ascender - doutline->offset_y) * scale + d->height * (base_scale - scale); + float y1 = y0 + (doutline->height) * scale; + + vertices.push_back({{x0+italicx, y0, 0, 1}, {doutline->s0, doutline->t0}, outline_color}); + vertices.push_back({{x1+italicx, y0, 0, 1}, {doutline->s1, doutline->t0}, outline_color}); + vertices.push_back({{x1, y1, 0, 1}, {doutline->s1, doutline->t1}, outline_color}); + vertices.push_back({{x0, y1, 0, 1}, {doutline->s0, doutline->t1}, outline_color}); + float mode = (style == FONT_STYLE_BOLD ? 3.0f : 2.0f); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); } font->kind->font->outline_thickness = 0; font->kind->font->rendermode = ftgl::RENDER_SIGNED_DISTANCE_FIELD; @@ -156,15 +159,42 @@ int DORText::addCharQuad(const char *str, size_t len, font_style style, int bx, vertices.push_back({{x1+italicx, y0, 0, 1}, {d->s1, d->t0}, {r, g, b, a}}); vertices.push_back({{x1, y1, 0, 1}, {d->s1, d->t1}, {r, g, b, a}}); vertices.push_back({{x0, y1, 0, 1}, {d->s0, d->t1}, {r, g, b, a}}); - vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 1.0f : 0.0f)}); - vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 1.0f : 0.0f)}); - vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 1.0f : 0.0f)}); - vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 1.0f : 0.0f)}); + float mode = (style == FONT_STYLE_BOLD ? 1.0f : 0.0f); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); // Much trickery, such dev if (style == FONT_STYLE_UNDERLINED) { ftgl::texture_glyph_t *ul = font->kind->getGlyph('_'); if (ul) { +/* + if (outline) { + font->kind->font->outline_thickness = 2; + font->kind->font->rendermode = ftgl::RENDER_OUTLINE_EDGE; + ftgl::texture_glyph_t *doutline = font->kind->getGlyph('_'); + if (doutline) { + float x0 = bx + x; + float x1 = x0 + d->advance_x * scale; + float y0 = by + (font->kind->font->ascender * 1.05 - doutline->offset_y) * scale; + float y1 = y0 + (doutline->height) * scale; + float s2 = (doutline->s1 - doutline->s0) / 1.5; + + vertices.push_back({{x0+italicx, y0, 0, 1}, {doutline->s0, doutline->t0}, outline_color}); + vertices.push_back({{x1+italicx, y0, 0, 1}, {doutline->s1, doutline->t0}, outline_color}); + vertices.push_back({{x1, y1, 0, 1}, {doutline->s1, doutline->t1}, outline_color}); + vertices.push_back({{x0, y1, 0, 1}, {doutline->s0, doutline->t1}, outline_color}); + float mode = (style == FONT_STYLE_BOLD ? 3.0f : 2.0f); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); + vertices_kind_info.push_back({mode}); + } + font->kind->font->outline_thickness = 0; + font->kind->font->rendermode = ftgl::RENDER_SIGNED_DISTANCE_FIELD; + } +*/ float x0 = bx + x; float x1 = x0 + d->advance_x * scale; float y0 = by + (font->kind->font->ascender * 1.05 - ul->offset_y) * scale; @@ -181,7 +211,8 @@ int DORText::addCharQuad(const char *str, size_t len, font_style style, int bx, vertices_kind_info.push_back({(style == FONT_STYLE_BOLD ? 1.0f : 0.0f)}); } } - x += d->advance_x * scale * (style == FONT_STYLE_BOLD ? 1.1 : 1); + x += d->advance_x * scale; + // if (style == FONT_STYLE_BOLD) x += d->width * scale * 0.1; } } return x; @@ -199,12 +230,7 @@ void DORText::parseText() { if (!font) return; -if (outline){ - font->kind->font->outline_thickness = 2; - font->kind->font->rendermode = ftgl::RENDER_OUTLINE_EDGE; -} - size_t len = strlen(text); if (!len) { used_color = font_color; @@ -501,12 +527,90 @@ void DORText::clear() { entities_container_refs.clear(); } +// Copies how to do stuff from DORVertexes::render but do it differently for multi texturing void DORText::render(RendererGL *container, mat4& cur_model, vec4& cur_color, bool cur_visible) { if (!visible || !cur_visible) return; - DORVertexes::render(container, cur_model, cur_color, true); - mat4 emodel = cur_model * model; - vec4 ecolor = cur_color * color; - entities_container.render(container, emodel, ecolor, true); + mat4 vmodel = cur_model * model; + vec4 vcolor = cur_color * color; + + + auto dl = getDisplayList(container, tex, shader, data_kind, render_kind); + + // Make sure we do not have to reallocate each step + int nb = vertices.size(); + int startat = dl->list.size(); + dl->list.reserve(startat + nb); + // Copy & apply the model matrix + // DGDGDGDG: is it better to first copy it all and then alter it ? most likely not, change me + dl->list.insert(std::end(dl->list), std::begin(this->vertices), std::end(this->vertices)); + vertex *dest = dl->list.data(); + + if (data_kind & VERTEX_MODEL_INFO) { + // Make sure we do not have to reallocate each step + int nb = vertices.size(); + int startat = dl->list_model_info.size(); + dl->list_model_info.resize(startat + nb); + vertex_model_info vm; + vm.model = vmodel; + std::fill_n(std::begin(dl->list_model_info) + startat, nb, vm); + for (int di = startat; di < startat + nb; di++) { + dest[di].color = vcolor * dest[di].color; + } + // printf("rendering with model info\n"); + } else { + // printf("rendering withOUT model info\n"); + for (int di = startat; di < startat + nb; di++) { + dest[di].pos = vmodel * dest[di].pos; + dest[di].color = vcolor * dest[di].color; + } + } + + if (data_kind & VERTEX_KIND_INFO) { + // Make sure we do not have to reallocate each step + int nb = vertices_kind_info.size(); + int startat = dl->list_kind_info.size(); + dl->list_kind_info.reserve(startat + nb); + dl->list_kind_info.insert(std::end(dl->list_kind_info), std::begin(this->vertices_kind_info), std::end(this->vertices_kind_info)); + } + + if (data_kind & VERTEX_MAP_INFO) { + // Make sure we do not have to reallocate each step + int nb = vertices_map_info.size(); + int startat = dl->list_map_info.size(); + dl->list_map_info.reserve(startat + nb); + dl->list_map_info.insert(std::end(dl->list_map_info), std::begin(this->vertices_map_info), std::end(this->vertices_map_info)); + } + + if (data_kind & VERTEX_PICKING_INFO) { + // Make sure we do not have to reallocate each step + int nb = vertices_picking_info.size(); + int startat = dl->list_picking_info.size(); + dl->list_picking_info.reserve(startat + nb); + dl->list_picking_info.insert(std::end(dl->list_picking_info), std::begin(this->vertices_picking_info), std::end(this->vertices_picking_info)); + } + + if (data_kind & VERTEX_NORMAL_INFO) { + // Make sure we do not have to reallocate each step + int nb = vertices_normal_info.size(); + int startat = dl->list_normal_info.size(); + dl->list_normal_info.reserve(startat + nb); + dl->list_normal_info.insert(std::end(dl->list_normal_info), std::begin(this->vertices_normal_info), std::end(this->vertices_normal_info)); + + // Apply rotations + if (!(data_kind & VERTEX_MODEL_INFO)) { + vertex_normal_info *dest = dl->list_normal_info.data(); + mat3 rotmat(vmodel); + rotmat = glm::transpose(glm::inverse(rotmat)); + for (int di = startat; di < startat + nb; di++) { + dest[di].normal = glm::normalize(rotmat * dest[di].normal); + } + } + } + + resetChanged(); + + // Add the sub entities we need to display + entities_container.render(container, vmodel, vcolor, true); } // void DORText::renderZ(RendererGL *container, mat4& cur_model, vec4& cur_color, bool cur_visible) { @@ -524,6 +628,7 @@ DORText::DORText() { entities_container.setParent(this); if (default_shader) setShader(default_shader); setDataKinds(VERTEX_BASE + VERTEX_KIND_INFO); + setOutline(default_outline, default_outline_color); }; DORText::~DORText() { diff --git a/src/renderer-moderngl/TextObject.hpp b/src/renderer-moderngl/TextObject.hpp index 3320d4329e..4df2353ee2 100644 --- a/src/renderer-moderngl/TextObject.hpp +++ b/src/renderer-moderngl/TextObject.hpp @@ -29,6 +29,8 @@ class DORText : public DORVertexes{ private: static shader_type *default_shader; + static float default_outline; + static vec4 default_outline_color; DORContainer entities_container; vector<int> entities_container_refs; @@ -52,8 +54,8 @@ private: float shadow_x = 0, shadow_y = 0; vec4 shadow_color; - float outline = 0; - vec4 outline_color; + float outline = 1; + vec4 outline_color = vec4(0, 0, 0, 1); bool small_caps = false; @@ -92,6 +94,7 @@ public: void setShadow(float offx, float offy, vec4 color) { shadow_x = offx; shadow_y = offy; shadow_color = color; }; void setOutline(float o, vec4 color) { outline = o; outline_color = color; }; + static void setOutlineDefault(float o, vec4 color) { default_outline = o; default_outline_color = color; }; virtual void clear(); diff --git a/src/renderer-moderngl/renderer-lua.cpp b/src/renderer-moderngl/renderer-lua.cpp index 96646e6a38..0215c4ab67 100644 --- a/src/renderer-moderngl/renderer-lua.cpp +++ b/src/renderer-moderngl/renderer-lua.cpp @@ -1337,7 +1337,7 @@ static int gl_text_shadow(lua_State *L) static int gl_text_outline(lua_State *L) { DORText *v = userdata_to_DO<DORText>(L, 1, "gl{text}"); - vec4 color = {0, 0, 0, 0.7}; + vec4 color = {0, 0, 0, 1}; if (lua_isnumber(L, 3)) { color.r = lua_tonumber(L, 3); color.g = lua_tonumber(L, 4); @@ -1350,6 +1350,19 @@ static int gl_text_outline(lua_State *L) return 1; } +static int gl_text_static_default_outline(lua_State *L) +{ + vec4 color = {0, 0, 0, 1}; + if (lua_isnumber(L, 2)) { + color.r = lua_tonumber(L, 2); + color.g = lua_tonumber(L, 3); + color.b = lua_tonumber(L, 4); + color.a = lua_tonumber(L, 5); + } + DORText::setOutlineDefault(lua_tonumber(L, 1), color); + return 0; +} + static int gl_text_style(lua_State *L) { DORText *v = userdata_to_DO<DORText>(L, 1, "gl{text}"); @@ -2311,6 +2324,11 @@ const luaL_Reg rendererlib[] = { {NULL, NULL} }; +const luaL_Reg textslib[] = { + {"defaultOutline", gl_text_static_default_outline}, + {NULL, NULL} +}; + const luaL_Reg physicslib[] = { {"pause", physic_world_pause}, {"sleepAll", physic_world_sleep_all}, @@ -2341,6 +2359,7 @@ int luaopen_renderer(lua_State *L) auxiliar_newclass(L, "gl{view}", gl_view_reg); auxiliar_newclass(L, "gl{vbo}", gl_vbo_reg); luaL_openlib(L, "core.renderer", rendererlib, 0); + luaL_openlib(L, "core.renderer.textconf", textslib, 0); luaL_openlib(L, "core.physics", physicslib, 0); // Build the weak self store registry -- GitLab