laughs in french

master
Alessandro Mauri 2 years ago
parent 884d5a1987
commit a697fec5d1
Signed by: alema
GPG Key ID: 2B7BF9531FF03BE8
  1. BIN
      text_rendering/atlas.png
  2. 7
      text_rendering/font_fragshader.glsl
  3. 12
      text_rendering/font_vertshader.glsl
  4. 12
      text_rendering/main.c
  5. 97
      text_rendering/ren.c
  6. BIN
      text_rendering/test

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 11 KiB

@ -6,10 +6,13 @@ uniform ivec2 texturesize;
// texture uv coordinate in texture space // texture uv coordinate in texture space
in vec2 uv; in vec2 uv;
uniform sampler2D ts; uniform sampler2DRect ts;
const vec3 textcolor = vec3(1.0, 1.0, 1.0);
void main() void main()
{ {
//gl_FragColor = vec4(1.0f,0.0f,0.0f,1.0f); //gl_FragColor = vec4(1.0f,0.0f,0.0f,1.0f);
gl_FragColor = texture(ts, uv); gl_FragColor = vec4(textcolor, texture(ts, uv));
} }

@ -13,14 +13,14 @@ out vec2 uv;
void main() void main()
{ {
// matrix to change from image coordinates to opengl coordinates
mat2 transform = mat2(vec2(0.0f, -1.0f), vec2(1.0f, 0.0f));
vec2 v = vec2(float(viewsize.x), float(viewsize.y)); vec2 v = vec2(float(viewsize.x), float(viewsize.y));
vec2 h = v/2.0f;
vec2 p = ((position-h)/ h); // vec2 p = vec2(position.x*2.0f/v.x - 1.0f, position.y*2.0f/v.y - 1.0f);
vec2 p = vec2(position.x*2.0/v.x - 1.0, 1.0 - position.y*2.0/v.y);
vec4 pos = vec4(p.x, p.y, 0.0f, 1.0f); vec4 pos = vec4(p.x, p.y, 0.0f, 1.0f);
gl_Position = pos; gl_Position = pos;
uv = vec2(txcoord.x / float(texturesize.x), (float(texturesize.y) - txcoord.y) / float(texturesize.y)); // since the texture is a GL_TEXTURE_RECTANGLE the coordintes do not need to
// be normalized
uv = vec2(txcoord.x, txcoord.y);
} }

@ -10,6 +10,10 @@
int main(void) int main(void)
{ {
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
SDL_Window *win = SDL_CreateWindow( SDL_Window *win = SDL_CreateWindow(
"test render", "test render",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
@ -22,8 +26,7 @@ int main(void)
return 1; return 1;
} }
ren_render_text("ciao mamma", 0, 0, 100, 100, 12); const char *str = "Ciao Mamma!\nprova: òçà°ù§|¬³¼$£ì";
SDL_GL_SwapWindow(win);
SDL_Event e; SDL_Event e;
while(1) { while(1) {
@ -35,8 +38,11 @@ int main(void)
case SDL_WINDOWEVENT_RESIZED: case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED: case SDL_WINDOWEVENT_SIZE_CHANGED:
ren_update_viewport(e.window.data1, e.window.data2); ren_update_viewport(e.window.data1, e.window.data2);
ren_render_text(str, 0, 0, 100, 100, 12);
SDL_GL_SwapWindow(win);
break;
case SDL_WINDOWEVENT_EXPOSED: case SDL_WINDOWEVENT_EXPOSED:
ren_render_text("ciao mamma", 0, 0, 100, 100, 12); ren_render_text(str, 0, 0, 100, 100, 12);
SDL_GL_SwapWindow(win); SDL_GL_SwapWindow(win);
break; break;
default: break; default: break;

@ -10,8 +10,14 @@
#include "ren.h" #include "ren.h"
#define GLERR() {int a = glGetError(); if (a != GL_NO_ERROR) printf("(%s:%d %s) glError: 0x%x %s\n", __FILE__, __LINE__, __func__, a, glerr[a]);} #define GLERR(x) \
#define GL(f) f; GLERR() { \
int a = glGetError(); \
if (a != GL_NO_ERROR) \
printf("(%s:%d %s:%s) glError: 0x%x %s\n", \
__FILE__, __LINE__, __func__, x, a, glerr[a]); \
}
#define GL(f) f; GLERR(#f)
enum REN_ERR { enum REN_ERR {
@ -270,19 +276,44 @@ static GLuint ren_texturer_2d(const char *buf, int w, int h, int upscale, int do
} }
static GLuint ren_texturer_rect(const char *buf, int w, int h, int upscale, int downscale)
{
GLuint t;
if (!buf || w <= 0 || h <= 0)
REN_RET(0, REN_INVAL)
GL(glGenTextures(1, &t))
if (!t) REN_RET(0, REN_TEXTURE)
GL(glBindTexture(GL_TEXTURE_RECTANGLE, t))
GL(glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, buf))
// a limitation of recatngle textures is that the wrapping mode is limited
// to either clamp-to-edge or clamp-to-border
GL(glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE))
GL(glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE))
GL(glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, downscale))
GL(glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, upscale))
return t;
}
// FIXME: update only the newly generated character instead of the whole texture // FIXME: update only the newly generated character instead of the whole texture
static int update_font_texture(void) static int update_font_texture(void)
{ {
glUseProgram(ren.font_prog);
GL(glTexSubImage2D( GL(glTexSubImage2D(
ren.font_texture, GL_TEXTURE_RECTANGLE,
0, 0, 0, 0, 0, 0,
ren.font->width, ren.font->width,
ren.font->height, ren.font->height,
GL_R, GL_RED,
GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE,
ren.font->atlas)) ren.font->atlas))
font_dump(ren.font, "./atlas.png"); font_dump(ren.font, "./atlas.png");
glUseProgram(0);
return 0; return 0;
} }
@ -303,6 +334,7 @@ int ren_init(SDL_Window *w)
GL(glDisable(GL_DEPTH_TEST)) GL(glDisable(GL_DEPTH_TEST))
GL(glEnable(GL_SCISSOR_TEST)) GL(glEnable(GL_SCISSOR_TEST))
GL(glEnable(GL_TEXTURE_2D)) GL(glEnable(GL_TEXTURE_2D))
GL(glEnable(GL_TEXTURE_RECTANGLE))
GLenum glew_err = glewInit(); GLenum glew_err = glewInit();
if (glew_err != GLEW_OK) if (glew_err != GLEW_OK)
@ -313,7 +345,7 @@ int ren_init(SDL_Window *w)
if (font_load(ren.font, FONT_PATH, 20)) REN_RET(-1, REN_FONT) if (font_load(ren.font, FONT_PATH, 20)) REN_RET(-1, REN_FONT)
font_dump(ren.font, "./atlas.png"); font_dump(ren.font, "./atlas.png");
ren.font_texture = ren_texturer_2d( ren.font_texture = ren_texturer_rect(
(const char *)ren.font->atlas, (const char *)ren.font->atlas,
ren.font->width, ren.font->width,
ren.font->height, ren.font->height,
@ -330,11 +362,14 @@ int ren_init(SDL_Window *w)
GL(glGenBuffers(1, &ren.font_buffer)) GL(glGenBuffers(1, &ren.font_buffer))
if (!ren.font_buffer) REN_RET(-1, REN_BUFFER) if (!ren.font_buffer) REN_RET(-1, REN_BUFFER)
// create the uniforms // create the uniforms, if the returned value is -1 then the uniform may have
// been optimized away, in any case do not return, just give a warning
ren.viewsize_loc = GL(glGetUniformLocation(ren.font_prog, "viewsize")) ren.viewsize_loc = GL(glGetUniformLocation(ren.font_prog, "viewsize"))
if (ren.viewsize_loc == -1) REN_RET(-1, REN_UNIFORM) if (ren.viewsize_loc == -1)
printf("uniform %s was optimized away\n", "viewsize");
ren.texturesize_loc = GL(glGetUniformLocation(ren.font_prog, "texturesize")) ren.texturesize_loc = GL(glGetUniformLocation(ren.font_prog, "texturesize"))
if (ren.texturesize_loc == -1) REN_RET(-1, REN_UNIFORM) if (ren.texturesize_loc == -1)
printf("uniform %s was optimized away\n", "texturesize");
int width, height; int width, height;
SDL_GetWindowSize(w, &width, &height); SDL_GetWindowSize(w, &width, &height);
@ -352,7 +387,10 @@ static int ren_draw_font_stack(void)
GL(glBindBuffer(GL_ARRAY_BUFFER, ren.font_buffer)) GL(glBindBuffer(GL_ARRAY_BUFFER, ren.font_buffer))
GL(glViewport(0, 0, ren.width, ren.height)) GL(glViewport(0, 0, ren.width, ren.height))
GL(glScissor(ren.s_x, ren.s_y, ren.s_w, ren.s_h)) GL(glScissor(0, 0, ren.width, ren.height))
GL(glClear(GL_COLOR_BUFFER_BIT));
// this has caused me some trouble, convert from image coordiates to viewport
//GL(glScissor(ren.s_x, ren.height-ren.s_y-ren.s_h, ren.s_w, ren.s_h))
GL(glUniform2i(ren.viewsize_loc, ren.width, ren.height)) GL(glUniform2i(ren.viewsize_loc, ren.width, ren.height))
GL(glUniform2i(ren.texturesize_loc, ren.font->width, ren.font->height)) GL(glUniform2i(ren.texturesize_loc, ren.font->width, ren.font->height))
@ -431,6 +469,7 @@ int ren_render_text(const char *str, int x, int y, int w, int h, int size)
uint_least32_t cp; uint_least32_t cp;
int updated, gx = x, gy = y; int updated, gx = x, gy = y;
struct v_text v; struct v_text v;
printf("rendering text: %s\n", str);
for (off = 0; (ret = grapheme_decode_utf8(str+off, SIZE_MAX, &cp)) > 0 && cp != 0; off += ret) { for (off = 0; (ret = grapheme_decode_utf8(str+off, SIZE_MAX, &cp)) > 0 && cp != 0; off += ret) {
g = font_get_glyph_texture(ren.font, cp, &updated); g = font_get_glyph_texture(ren.font, cp, &updated);
if (!g) REN_RET(-1, REN_FONT); if (!g) REN_RET(-1, REN_FONT);
@ -439,8 +478,8 @@ int ren_render_text(const char *str, int x, int y, int w, int h, int size)
REN_RET(-1, REN_TEXTURE); REN_RET(-1, REN_TEXTURE);
} }
c = *g; c = *g;
printf("g: u=%d v=%d w=%d h=%d a=%d x=%d y=%d\n", c.u, c.v, c.w, c.h, c.a, c.x, c.y); //printf("g: u=%d v=%d w=%d h=%d a=%d x=%d y=%d\n", c.u, c.v, c.w, c.h, c.a, c.x, c.y);
//printf("v: x=%d y=%d u=%d v=%d\n", v.pos.x, v.pos.y, v.uv.u, v.uv.v);
// x1,y1 // x1,y1
v = (struct v_text){ v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y+c.h }, .pos = { .x = gx+c.x, .y = gy+c.y+c.h },
@ -449,37 +488,51 @@ int ren_render_text(const char *str, int x, int y, int w, int h, int size)
vtstack_push(&ren.font_stack, &v); vtstack_push(&ren.font_stack, &v);
// x2,y2 // x2,y2
v = (struct v_text){ v = (struct v_text){
.pos = { .x = gx+c.x+c.w, .y = gy+c.y+c.h }, .pos = { .x = gx+c.x+c.w, .y = gy+c.y+c.h },
.uv = { .u = c.u+c.w, .v = c.v+c.h }, .uv = { .u = c.u+c.w, .v = c.v+c.h },
}; };
vtstack_push(&ren.font_stack, &v); vtstack_push(&ren.font_stack, &v);
// x3,y3 // x3,y3
v = (struct v_text){ v = (struct v_text){
.pos = { .x = gx+c.x+c.w, .y = gy+c.y }, .pos = { .x = gx+c.x+c.w, .y = gy+c.y },
.uv = { .u = c.u+c.w, .v = c.v }, .uv = { .u = c.u+c.w, .v = c.v },
}; };
vtstack_push(&ren.font_stack, &v); vtstack_push(&ren.font_stack, &v);
// x1,y1
v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y+c.h },
.uv = { .u = c.u, .v = c.v+c.h },
};
vtstack_push(&ren.font_stack, &v); vtstack_push(&ren.font_stack, &v);
// x4,y4 // x3,y3
v = (struct v_text){ v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y }, .pos = { .x = gx+c.x+c.w, .y = gy+c.y },
.uv = { .u = c.u, .v = c.v }, .uv = { .u = c.u+c.w, .v = c.v },
}; };
vtstack_push(&ren.font_stack, &v); vtstack_push(&ren.font_stack, &v);
// x1,y1 // x4,y4
v = (struct v_text){ v = (struct v_text){
.pos = { .x = gx+c.x, .y = gy+c.y+c.h }, .pos = { .x = gx+c.x, .y = gy+c.y },
.uv = { .u = c.u, .v = c.v+c.h }, .uv = { .u = c.u, .v = c.v },
}; };
vtstack_push(&ren.font_stack, &v); vtstack_push(&ren.font_stack, &v);
// TODO: possible kerning needs to be applied here // TODO: possible kerning needs to be applied here
// FIXME: advance is too large // FIXME: advance is too large
//gx += c.w + c.a; //gx += c.w + c.a;
gx += c.w + c.x + 1; //gx += c.w + c.x + 1;
if (cp == '\n') gx += c.x + c.a;
gy += ren.font->glyph_max_h; switch (cp) {
case '\r':
gx = x;
break;
case '\n':
// TODO: encode and/or store line height // TODO: encode and/or store line height
gy = ren.font->glyph_max_h;
gx = x;
break;
default: break;
}
} }
// FIXME: here we are doing one draw call for string of text which is // FIXME: here we are doing one draw call for string of text which is

Binary file not shown.
Loading…
Cancel
Save