Skip to content

Commit 5ca7927

Browse files
committed
["fix"] GLES3 font quality not enough, but temp-fixed
1 parent 14dedc1 commit 5ca7927

File tree

14 files changed

+366
-201
lines changed

14 files changed

+366
-201
lines changed

devlog/commit.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,4 +231,5 @@
231231
-- Added an unsafe function `ekg::draw::scissor`/method to explicit display a new scissor placement (position and size).
232232
-- Solved a visual-glitch where the line always was zero on listbox header(s) and item(s) text-label.
233233
-- Fixed a glitch where dragging and swap was not working out of header(s)-rect boudings.
234-
-- Added WASM build-type compatibility.
234+
-- Added WASM build-type compatibility.
235+
-- Fixed GLES3 font, but not quality not enough to be totally fixed.

ekg-ui-library.sublime-project

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,34 @@
1414
{
1515
"initializationOptions":
1616
{
17-
"clangd.compile-commands-dir": "./cmake-build"
18-
}
19-
}
20-
},
21-
"SublimeLinter.linters.clangtidy.compile_commands": "./cmake-build",
17+
"clangd.compile-commands-dir": "cd $folder && ./cmake-build",
18+
},
19+
20+
"enabled": true,
21+
},
22+
},
2223
},
2324
"build_systems":
2425
[
2526
{
2627
"name": "Linux Build-&-Test GNU",
2728
"shell_cmd":
28-
"cd $folder && cmake -S . -B ./cmake-build/ -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build/ && cd ./test && cmake -S . -B ./cmake-build -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build && cd ./bin && ./ekg-gui-showcase-test"
29+
"cd $folder && cmake -S . -B ./cmake-build/ -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build/ && cd ./test && cmake -S . -B ./cmake-build -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build && cd ./bin && ./ekg-gui-showcase-test",
2930
},
3031
{
3132
"name": "Windows Build-&-Test",
3233
"shell_cmd":
33-
"cd $folder && cmake -S . -B ./cmake-build/ -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build/ && cd ./test && cmake -S . -B ./cmake-build -G Ninja -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build && cd ./bin && ./ekg-gui-showcase-test"
34+
"cd $folder && cmake -S . -B ./cmake-build/ -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build/ && cd ./test && cmake -S . -B ./cmake-build -G Ninja -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build && cd ./bin && ./ekg-gui-showcase-test",
3435
},
3536
{
3637
"name": "Linux Build-&-Test Clang",
3738
"shell_cmd":
38-
"cd $folder && cmake -S . -B ./cmake-build/ -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build/ && cd ./test && cmake -S . -B ./cmake-build -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build && cd ./bin && ./ekg-gui-showcase-test"
39+
"cd $folder && cmake -S . -B ./cmake-build/ -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build/ && cd ./test && cmake -S . -B ./cmake-build -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DEKG_LINUX_NOT_FOUND_FREETYPE=1 && cmake --build ./cmake-build && cd ./bin && ./ekg-gui-showcase-test",
3940
},
4041
{
4142
"name": "Linux Build WASM",
4243
"shell_cmd":
43-
"cd $folder && emcmake cmake -S . -B ./cmake-build/ -G Ninja -DEKG_LINUX_NOT_FOUND_FREETYPE=1 -DCMAKE_CXX_COMPILER=/home/rina/emsdk/emsdk/upstream/emscripten/emcc -DCMAKE_EXPORT_COMPILE_COMMANDS=1 && cmake --build ./cmake-build"
44+
"cd $folder && emcmake cmake -S . -B ./cmake-build/ -G Ninja -DEKG_LINUX_NOT_FOUND_FREETYPE=1 -DCMAKE_CXX_COMPILER=/home/rina/emsdk/emsdk/upstream/emscripten/emcc -DCMAKE_EXPORT_COMPILE_COMMANDS=1 && cmake --build ./cmake-build",
4445
}
4546
],
4647
}

include/ekg/draw/font_renderer.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ namespace ekg::draw {
6565
FT_UInt ft_uint_previous {};
6666

6767
std::string_view font_path {};
68-
uint32_t font_size {18};
68+
uint32_t font_size {};
6969
ekg::gpu::sampler_t sampler_texture {};
7070

7171
int32_t full_width {};

include/ekg/gpu/api.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@
3131
#include <vector>
3232
#include <unordered_map>
3333

34-
#include <ft2build.h>
35-
#include FT_FREETYPE_H
36-
3734
#include "ekg/util/geometry.hpp"
3835
#include "ekg/draw/typography.hpp"
3936

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef EKG_GPU_OPENGL_PIPELINE_TEMPLATE_HPP
2+
#define EKG_GPU_OPENGL_PIPELINE_TEMPLATE_HPP
3+
4+
#include "ekg/os/ekg_opengl.hpp"
5+
6+
namespace ekg::gpu {
7+
void get_standard_vertex_shader(
8+
std::string glsl_version,
9+
ekg::os::opengl_version opengl_version,
10+
std::string &output_kernel_source
11+
);
12+
13+
void get_standard_fragment_shader(
14+
std::string glsl_version,
15+
ekg::os::opengl_version opengl_version,
16+
std::string &output_kernel_source
17+
);
18+
}
19+
20+
#endif

include/ekg/util/image.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef EKG_UTIL_IMAGE_HPP
2+
#define EKG_UTIL_IMAGE_HPP
3+
4+
#include <ft2build.h>
5+
#include FT_FREETYPE_H
6+
7+
#include <vector>
8+
9+
namespace ekg {
10+
enum format_convert_result {
11+
success,
12+
failed
13+
};
14+
15+
ekg::format_convert_result image_src_r8_convert_to_r8g8b8a8(
16+
FT_Vector size,
17+
const unsigned char *p_src,
18+
std::vector<unsigned char> &dst
19+
);
20+
}
21+
22+
#endif

include/ekg/util/io.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
* Note: this macro call console out (`std::cout`) directly, not safe for official log trace.
5050
**/
5151
#define ekg_log(msg) std::cout << msg << std::endl;
52+
#define ekg_log_assert(assert, msg) if (!assert) ekg_log(msg);
5253

5354
namespace ekg {
5455
typedef uint32_t flags;

src/draw/font_renderer.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ void ekg::draw::font_renderer::set_size(uint32_t size) {
193193
}
194194

195195
void ekg::draw::font_renderer::reload() {
196+
if (this->font_size == 0) {
197+
return;
198+
}
199+
196200
if (
197201
(!this->font_face_text.font_path.empty() && ekg::draw::reload_font_face(&this->font_face_text, this->font_size_changed, this->font_size)) ||
198202
(!this->font_face_emoji.font_path.empty() && ekg::draw::reload_font_face(&this->font_face_emoji, this->font_size_changed, this->font_size))
@@ -218,22 +222,26 @@ void ekg::draw::font_renderer::reload() {
218222
FT_GlyphSlot ft_glyph_slot {};
219223
FT_Face ft_face {};
220224

225+
ekg::flags flags {};
226+
221227
for (char32_t &char32 : this->loaded_sampler_generate_list) {
222228
switch (char32 < 256 || !this->font_face_emoji.font_face_loaded) {
223229
case true: {
224230
ft_face = this->font_face_text.ft_face;
225231
ft_glyph_slot = this->font_face_text.ft_face->glyph;
232+
flags = FT_LOAD_RENDER;
226233
break;
227234
}
228235

229236
default: {
230237
ft_face = this->font_face_emoji.ft_face;
231238
ft_glyph_slot = this->font_face_emoji.ft_face->glyph;
239+
flags = FT_LOAD_RENDER | FT_LOAD_COLOR;
232240
break;
233241
}
234242
}
235243

236-
if (FT_Load_Char(ft_face, char32, FT_LOAD_RENDER | FT_LOAD_DEFAULT | FT_LOAD_COLOR)) {
244+
if (FT_Load_Char(ft_face, char32, flags)) {
237245
continue;
238246
}
239247

src/ekg.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ void ekg::init(
5959
ekg::runtime *p_ekg_runtime,
6060
ekg::runtime_property *p_ekg_runtime_property
6161
) {
62+
ekg::log() << "Initializing FreeType library";
63+
64+
if (FT_Init_FreeType(&ekg::draw::font_renderer::ft_library)) {
65+
ekg::log() << "Error: Failed to init FreeType library";
66+
}
67+
6268
ekg::log() << "Initializing built-in OS platform-interface";
6369

6470
p_ekg_runtime->p_os_platform = p_ekg_runtime_property->p_os_platform;
@@ -72,10 +78,6 @@ void ekg::init(
7278

7379
ekg::log() << "Initializing EKG";
7480

75-
if (FT_Init_FreeType(&ekg::draw::font_renderer::ft_library)) {
76-
ekg::log() << "Error: Failed to init FreeType library";
77-
}
78-
7981
ekg::core = p_ekg_runtime;
8082
ekg::running = true;
8183

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#include "ekg/gpu/opengl_pipeline_template.hpp"
2+
3+
void ekg::gpu::get_standard_vertex_shader(
4+
std::string glsl_version,
5+
ekg::os::opengl_version opengl_version,
6+
std::string &output_kernel_source
7+
) {
8+
output_kernel_source = glsl_version + R"(
9+
layout (location = 0) in vec2 aPos;
10+
layout (location = 1) in vec2 aTexCoord;
11+
12+
uniform mat4 uProjection;
13+
uniform vec4 uRect;
14+
15+
out vec2 vTexCoord;
16+
out vec2 vPos;
17+
out vec4 vRect;
18+
19+
void main() {
20+
vec2 vertex = aPos;
21+
22+
if (uRect.z > -1.0f && uRect.w > -1.0f) {
23+
vertex *= uRect.zw;
24+
}
25+
26+
vertex += uRect.xy;
27+
28+
gl_Position = uProjection * vec4(vertex, 0.0f, 1.0f);
29+
vTexCoord = aTexCoord;
30+
vRect = uRect;
31+
vPos = aPos;
32+
}
33+
)";
34+
}
35+
36+
void ekg::gpu::get_standard_fragment_shader(
37+
std::string glsl_version,
38+
ekg::os::opengl_version opengl_version,
39+
std::string &output_kernel_source
40+
) {
41+
output_kernel_source = glsl_version + R"(
42+
layout (location = 0) out vec4 aFragColor;
43+
uniform sampler2D uTextureSampler;
44+
45+
in vec2 vTexCoord;
46+
in vec2 vPos;
47+
in vec4 vRect;
48+
49+
uniform int uLineThickness;
50+
uniform int uActiveTexture;
51+
uniform float uViewportHeight;
52+
uniform float uContent[8];
53+
54+
void main() {
55+
aFragColor = vec4(
56+
uContent[0],
57+
uContent[1],
58+
uContent[2],
59+
uContent[3]
60+
);
61+
62+
vec2 fragPos = vec2(gl_FragCoord.x, uViewportHeight - gl_FragCoord.y);
63+
64+
/**
65+
* The scissoring works like swapchain-one (does not stack), of course,
66+
* this scissor is a little different, the pixel-perfect precision makes
67+
* a better cut of fragments. And does not require any overhead from
68+
* calling command buffers to GPU rastarizer.
69+
**/
70+
bool shouldDiscard = (
71+
fragPos.x <= uContent[4] ||
72+
fragPos.y <= uContent[5] ||
73+
fragPos.x >= uContent[4] + uContent[6] ||
74+
fragPos.y >= uContent[5] + uContent[7]
75+
);
76+
77+
float lineThicknessf = float(uLineThickness);
78+
79+
/**
80+
* The pixel-perfect outline is possible on fragment shader,
81+
* due the precision of fragments position, and the
82+
* normalised-space.
83+
**/
84+
if (uLineThickness > 0) {
85+
vec4 outline = vec4(
86+
vRect.x + lineThicknessf,
87+
vRect.y + lineThicknessf,
88+
vRect.z - (lineThicknessf * 2.0f),
89+
vRect.w - (lineThicknessf * 2.0f)
90+
);
91+
92+
shouldDiscard = (
93+
shouldDiscard || (
94+
fragPos.x > outline.x &&
95+
fragPos.x < outline.x + outline.z &&
96+
fragPos.y > outline.y &&
97+
fragPos.y < outline.y + outline.w
98+
)
99+
);
100+
} else if (uLineThickness < 0) {
101+
float radius = vRect.z / 2.0f;
102+
103+
vec2 diff = vec2(
104+
(vRect.x + radius) - fragPos.x,
105+
(vRect.y + radius) - fragPos.y
106+
);
107+
108+
float dist = (diff.x * diff.x + diff.y * diff.y);
109+
aFragColor.w = (
110+
1.0f - smoothstep(0.0, radius * radius, dot(dist, dist))
111+
);
112+
}
113+
114+
/**
115+
* The discard must not call `discard` keyword,
116+
* discarding pixels using keyword is performanceless
117+
* comparated to alpha blending equals to zero.
118+
**/
119+
if (shouldDiscard) {
120+
aFragColor.w = 0.0f;
121+
} else {
122+
vec4 textureColor;
123+
switch (uActiveTexture) {
124+
case 1:
125+
textureColor = texture(uTextureSampler, vTexCoord);
126+
127+
/**
128+
* The sampler used here is the font, and this sampler needs swizzled mapped,
129+
* instead of doing swizzling on CPU-side, here is actually the best place.
130+
* Due the necessity of put swizzle for ttf text fonts, the emojis must not swizzle.
131+
* The non swizzable range masterfully fix it.
132+
*
133+
* vRect.z is negative, because any concave rendering shape does not have a fixed
134+
* dimension size. So the rendering engine re-uses the Rect width to calculate
135+
* when must stop the GPU-side swizzle.
136+
**/
137+
float non_swizzlable_range = -vRect.z;
138+
139+
if (vTexCoord.x < non_swizzlable_range) {
140+
textureColor = textureColor.aaar;
141+
textureColor = vec4(
142+
textureColor.rgb * aFragColor.rgb,
143+
textureColor.a
144+
);
145+
}
146+
147+
aFragColor = vec4(
148+
textureColor.rgb,
149+
textureColor.a - (1.0f - aFragColor.a)
150+
);
151+
152+
//aFragColor = vec4(aFragColor.a, 0.0f, 0.0f, 1.0f);
153+
break;
154+
case 2:
155+
textureColor = texture(uTextureSampler, vPos);
156+
157+
aFragColor = vec4(
158+
textureColor.rgb,
159+
textureColor.a - (1.0f - aFragColor.a)
160+
);
161+
break;
162+
}
163+
}
164+
}
165+
)";
166+
}

0 commit comments

Comments
 (0)