summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdebug/debugbin396728 -> 0 bytes
-rw-r--r--libs/common.h13
-rw-r--r--libs/pwyazh/v2f.h7
-rw-r--r--libs/pwyazh/v3f.h7
-rw-r--r--text_rendering/bounds.frag8
-rw-r--r--text_rendering/bounds.vert12
-rwxr-xr-xtext_rendering/build.sh7
-rw-r--r--text_rendering/glyph.frag16
-rw-r--r--text_rendering/glyph.vert18
-rw-r--r--text_rendering/ibmvga8x16.ttfbin0 -> 69760 bytes
-rw-r--r--text_rendering/text_rendering.c199
11 files changed, 282 insertions, 5 deletions
diff --git a/debug/debug b/debug/debug
deleted file mode 100755
index d516f24..0000000
--- a/debug/debug
+++ /dev/null
Binary files differ
diff --git a/libs/common.h b/libs/common.h
index 08e753a..a7f8985 100644
--- a/libs/common.h
+++ b/libs/common.h
@@ -454,16 +454,16 @@ typedef struct {
#define MAX_SHADERS 8
shader_t shaders[MAX_SHADERS] = {0};
-void add_shader(const char *vert_filename, const char *frag_filename, const char *geom_filename)
+U32 add_shader(const char *vert_filename, const char *frag_filename, const char *geom_filename)
{
if (!vert_filename) {
info("vertex shader filename not specified");
- return;
+ return 0;
}
const char *dot = strrchr(vert_filename, '.');
if (!dot) {
info("shader \"%s\" was not loaded .vert or .vs expected for vertex shader", vert_filename);
- return;
+ return 0;
}
U64 len = dot - vert_filename;
char *name = malloc(len + 1);
@@ -476,10 +476,11 @@ void add_shader(const char *vert_filename, const char *frag_filename, const char
if (!shaders[i].id) die("failed to load shader \"%s\"", name);
shaders[i].name = name;
info("shader \"%s\" loaded successfully", name);
- return;
+ return shaders[i].id;
}
}
info("max shaders reached, can't load \"%s\"", name);
+ return 0;
}
void remove_shader(const char *name)
@@ -689,7 +690,9 @@ void gl_debug_output(GLenum source, GLenum type, GLuint id, GLenum severity, GLs
/* ignore these non-significant error codes */
if(id == 131169 || id == 131185 || id == 131218 || id == 131204)
return;
- info("debug message (%d): %s", id, message);
+ if (userParam)
+ info("user parameters doesn't supported");
+ info("debug message (%d length: %d): %s", id, length, message);
switch (source) {
case GL_DEBUG_SOURCE_API:
info("source: api");
diff --git a/libs/pwyazh/v2f.h b/libs/pwyazh/v2f.h
index bc09b45..67f9bd2 100644
--- a/libs/pwyazh/v2f.h
+++ b/libs/pwyazh/v2f.h
@@ -9,6 +9,13 @@ v2f(F32 x, F32 y)
}
V2F
+v2fa(F32 x)
+{
+ V2F result = { x, x };
+ return(result);
+}
+
+V2F
v2f_zero()
{
V2F result = { 0.0f, 0.0f };
diff --git a/libs/pwyazh/v3f.h b/libs/pwyazh/v3f.h
index f1b4ff7..c5a5c1b 100644
--- a/libs/pwyazh/v3f.h
+++ b/libs/pwyazh/v3f.h
@@ -9,6 +9,13 @@ v3f(F32 x, F32 y, F32 z)
}
V3F
+v3fa(F32 x)
+{
+ V3F result = { x, x, x };
+ return(result);
+}
+
+V3F
v3f_from_v4f(V4F a)
{
V3F result = { a.x, a.y, a.z };
diff --git a/text_rendering/bounds.frag b/text_rendering/bounds.frag
new file mode 100644
index 0000000..34646c6
--- /dev/null
+++ b/text_rendering/bounds.frag
@@ -0,0 +1,8 @@
+#version 330 core
+
+out vec4 frag_color;
+
+void main()
+{
+ frag_color = vec4(1.0);
+}
diff --git a/text_rendering/bounds.vert b/text_rendering/bounds.vert
new file mode 100644
index 0000000..8c115a5
--- /dev/null
+++ b/text_rendering/bounds.vert
@@ -0,0 +1,12 @@
+#version 330 core
+
+layout(location = 0) in vec4 vertex;
+
+uniform mat4 projection;
+
+void main()
+{
+ gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
+}
+
+
diff --git a/text_rendering/build.sh b/text_rendering/build.sh
new file mode 100755
index 0000000..bfca9cc
--- /dev/null
+++ b/text_rendering/build.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+include="-I../libs -I../libs/pwyazh -I/usr/include/freetype2"
+cflags="-g -Wall -Wextra $include"
+libs='-lm -lGL -lGLEW -lglfw -lfreetype'
+target='text_rendering'
+set -x
+gcc -o $target $cflags $target.c $libs
diff --git a/text_rendering/glyph.frag b/text_rendering/glyph.frag
new file mode 100644
index 0000000..a6fae4b
--- /dev/null
+++ b/text_rendering/glyph.frag
@@ -0,0 +1,16 @@
+#version 330 core
+
+in vert_t {
+ vec2 tex_coords;
+} vert;
+
+out vec4 frag_color;
+
+uniform sampler2D glyph;
+uniform vec3 text_color;
+
+void main()
+{
+ vec4 glyph_color = vec4(1.0, 1.0, 1.0, texture(glyph, vert.tex_coords).r);
+ frag_color = vec4(text_color, 1.0) * glyph_color;
+}
diff --git a/text_rendering/glyph.vert b/text_rendering/glyph.vert
new file mode 100644
index 0000000..ebee1b5
--- /dev/null
+++ b/text_rendering/glyph.vert
@@ -0,0 +1,18 @@
+#version 330 core
+
+/* combine position and texture coordinates into vec4 */
+layout(location = 0) in vec4 vertex;
+
+out vert_t {
+ vec2 tex_coords;
+} vert;
+
+uniform mat4 projection;
+
+void main()
+{
+ gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
+ vert.tex_coords = vertex.zw;
+}
+
+
diff --git a/text_rendering/ibmvga8x16.ttf b/text_rendering/ibmvga8x16.ttf
new file mode 100644
index 0000000..72231a6
--- /dev/null
+++ b/text_rendering/ibmvga8x16.ttf
Binary files differ
diff --git a/text_rendering/text_rendering.c b/text_rendering/text_rendering.c
new file mode 100644
index 0000000..398b202
--- /dev/null
+++ b/text_rendering/text_rendering.c
@@ -0,0 +1,199 @@
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "common.h"
+
+typedef struct {
+ U32 texture_id;
+ V2F size;
+ V2F bearing;
+ U32 advance;
+} char_t;
+
+char_t chars[128];
+static U32 vao, vbo;
+
+V2F get_text_size(const char *text, F32 scale)
+{
+ V2F size = {0};
+ for (const char *c = text; *c; c++) {
+ char_t ch = chars[(U8)*c];
+ F32 h = ch.size.y * scale;
+ if (h > size.y)
+ size.y = h;
+ size.x += (ch.advance >> 6) * scale;
+ }
+ return size;
+}
+
+void render_text(const char *text, U32 shader, V2F pos, F32 scale, V3F color)
+{
+ glUseProgram(shader);
+ shader_set_3fv(shader, "text_color", color);
+ glActiveTexture(GL_TEXTURE0);
+ glBindVertexArray(vao);
+ for (const char *c = text; *c; c++) {
+ char_t ch = chars[(U8)*c];
+ F32 x = pos.x + ch.bearing.x * scale;
+ F32 y = pos.y - (ch.size.y - ch.bearing.y) * scale;
+ F32 w = ch.size.x * scale;
+ F32 h = ch.size.y * scale;
+ F32 vertices[] = {
+ x, y + h, 0.0f, 0.0f,
+ x, y, 0.0f, 1.0f,
+ x + w, y, 1.0f, 1.0f,
+
+ x, y + h, 0.0f, 0.0f,
+ x + w, y, 1.0f, 1.0f,
+ x + w, y + h, 1.0f, 0.0f,
+ };
+ glBindTexture(GL_TEXTURE_2D, ch.texture_id);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ pos.x += (ch.advance >> 6) * scale;
+ }
+ glBindVertexArray(0);
+ glUseProgram(0);
+}
+
+void render_bounds(const char *text, U32 shader, V2F pos, F32 scale)
+{
+ glUseProgram(shader);
+ glBindVertexArray(vao);
+ V2F size = get_text_size(text, scale);
+ F32 x = pos.x;
+ F32 y = pos.y;
+ F32 w = size.x;
+ F32 h = size.y;
+ F32 vertices[] = {
+ x, y + h, 0.0f, 0.0f,
+ x, y, 0.0f, 1.0f,
+ x + w, y, 1.0f, 1.0f,
+
+ x, y + h, 0.0f, 0.0f,
+ x + w, y, 1.0f, 1.0f,
+ x + w, y + h, 1.0f, 0.0f,
+ };
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glBindVertexArray(0);
+ glUseProgram(0);
+}
+
+int main(void)
+{
+ state_t state = init_state(1600, 800, 1);
+ init_glfw(&state);
+ init_gl();
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ FT_Library ft;
+ if (FT_Init_FreeType(&ft))
+ die("failed to initialize freetype");
+ FT_Face face;
+ const char *font_name = "ibmvga8x16.ttf";
+ if (FT_New_Face(ft, font_name, 0, &face))
+ die("failed to load %s", font_name);
+ FT_Set_Pixel_Sizes(face, 0, 48);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ for (U32 c = 0; c < 128; c++) {
+ if (FT_Load_Char(face, c, FT_LOAD_RENDER))
+ die("failed to load X character");
+ U32 texture;
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RED,
+ face->glyph->bitmap.width,
+ face->glyph->bitmap.rows,
+ 0, GL_RED, GL_UNSIGNED_BYTE,
+ face->glyph->bitmap.buffer);
+ 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_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ chars[c] = (char_t){
+ texture,
+ {face->glyph->bitmap.width, face->glyph->bitmap.rows},
+ {face->glyph->bitmap_left, face->glyph->bitmap_top},
+ face->glyph->advance.x
+ };
+
+ }
+ FT_Done_Face(face);
+ FT_Done_FreeType(ft);
+
+ U32 shader = add_shader("glyph.vert", "glyph.frag", 0);
+ MAT4 projection = ortho(0.0f, state.width, 0.0f, state.height, 0.0f, 1.0f);
+ glUseProgram(shader);
+ shader_set_mat4fv(shader, "projection", projection);
+ glUseProgram(0);
+
+ U32 bounds_shader = add_shader("bounds.vert", "bounds.frag", 0);
+ glUseProgram(bounds_shader);
+ shader_set_mat4fv(bounds_shader, "projection", projection);
+ glUseProgram(0);
+
+ glGenVertexArrays(1, &vao);
+ glGenBuffers(1, &vbo);
+ glBindVertexArray(vao);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(F32) * 6 * 4, 0, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(F32), 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ glClearColor(0.16f, 0.16f, 0.16f, 1.0f);
+ F32 time = 0.0f;
+
+ V2F pos = {state.width / 2.0f, state.height / 2.0f};
+ V2F vel = {0.5f, 0.5f};
+
+ S32 show_bounds = 0;
+ const char *text = "foo, bar, nope";
+ F32 scale = 1.0f;
+ V2F size = get_text_size(text, scale);
+
+ while (!glfwWindowShouldClose(state.window)) {
+ handle_glfw_events(state.window, &state.input);
+ F32 dt = lock_framerate(60);
+
+ /* update */
+ F32 sin_value = 0.25f * sinf(time) + 0.75f;
+ F32 cos_value = 0.25f * cosf(time) + 0.75f;
+ V3F color = v3f(sin_value, cos_value, sin_value);
+ F32 speed = 256.0f;
+ V2F new_pos = v2f_add(pos, v2f_scalef(vel, speed * dt));
+ if (new_pos.x < 0.0f || new_pos.x + size.x > state.width)
+ vel.x = -vel.x;
+ if (new_pos.y < 0.0f || new_pos.y + size.y > state.height)
+ vel.y = -vel.y;
+ pos = new_pos;
+
+ if (key_first_press(state.input.jump))
+ show_bounds = !show_bounds;
+
+ time += dt;
+
+ /* render */
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ render_text(text, shader, pos, scale, color);
+ if (show_bounds)
+ render_bounds(text, bounds_shader, pos, scale);
+
+ glfwSwapBuffers(state.window);
+ }
+
+ return 0;
+}