commit f13c2e298a2905837b4ced9307e80b7be7d738f2
parent caf50bb2ab0d31758d59e590f73149ce479fbe96
Author: Brian Swetland <swetland@frotz.net>
Date: Sat, 22 Jun 2013 06:48:24 -0700
texturefont: renderer for fonts generated by mkfont tool
Diffstat:
4 files changed, 272 insertions(+), 0 deletions(-)
diff --git a/common/assets/texturefont.glsl b/common/assets/texturefont.glsl
@@ -0,0 +1,74 @@
+#version 150
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(std140) uniform udata0 {
+ mat4 MVP;
+ float dim;
+};
+
+-- vs
+
+layout(location = 0) in ivec4 posn;
+layout(location = 1) in ivec2 texc;
+layout(location = 2) in vec4 color;
+
+out vec2 size;
+out vec2 tex;
+out vec4 vcolor;
+
+void main() {
+ gl_Position = vec4(posn.x, posn.y, 0, 1);
+ size = posn.zw;
+ tex = texc;
+ vcolor = color;
+}
+
+-- gs
+
+layout (points) in;
+layout (triangle_strip, max_vertices=4) out;
+
+in vec2 size[1];
+in vec2 tex[1];
+in vec4 vcolor[1];
+
+out vec2 s0tc;
+out vec4 color;
+
+void main() {
+ vec4 p = gl_in[0].gl_Position;
+
+ gl_Position = MVP * vec4(p.x, p.y - size[0].y, 0.0, 1.0);
+ s0tc = tex[0] / dim;
+ color = vcolor[0];
+ EmitVertex();
+
+ gl_Position = MVP * vec4(p.x + size[0].x, p.y - size[0].y, 0.0, 1.0);
+ s0tc = (tex[0] + vec2(size[0].x,0)) / dim;
+ color = vcolor[0];
+ EmitVertex();
+
+ gl_Position = MVP * vec4(p.x, p.y, 0.0, 1.0);
+ s0tc = (tex[0] + vec2(0,size[0].y)) / dim;
+ color = vcolor[0];
+ EmitVertex();
+
+ gl_Position = MVP * vec4(p.x + size[0].x, p.y, 0.0, 1.0);
+ s0tc = (tex[0] + size[0]) / dim;
+ color = vcolor[0];
+ EmitVertex();
+
+ EndPrimitive();
+}
+
+-- fs
+
+uniform sampler2D s0glyphs;
+
+in vec2 s0tc;
+in vec4 color;
+
+void main() {
+ vec4 c = texture2D(s0glyphs, s0tc);
+ gl_FragColor = vec4(color.r, color.g, color.b, c.r);
+}
diff --git a/common/module.mk b/common/module.mk
@@ -12,6 +12,7 @@ M_OBJS += matrix.o
M_OBJS += savepng.o
M_OBJS += simplexnoise.o
M_OBJS += textgrid.o
+M_OBJS += texturefont.o
M_LIBS := common
include build/lib.mk
diff --git a/common/texturefont.cc b/common/texturefont.cc
@@ -0,0 +1,150 @@
+/* Copyright 2013 Brian Swetland <swetland@frotz.net>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include <util.h>
+#include <matrix.h>
+#include <app.h>
+#include <texturefont.h>
+
+// idx, src, dst, count, offset, stride, divisor
+static VertexAttrDesc layout[] = {
+ { 0, SRC_INT16, DST_INTEGER, 4, 0, 16, 0 },
+ { 1, SRC_UINT16, DST_INTEGER, 2, 8, 16, 0 },
+ { 2, SRC_UINT8, DST_NORMALIZED, 4, 12, 16, 0 },
+};
+
+int TextureFont::init(App *app, const char *fontname) {
+ VertexBuffer *vdata[] = {
+ &vtx, &vtx, &vtx,
+ };
+ char tmp[256];
+ unsigned sz;
+
+ header = NULL;
+ max = 128;
+ count = 0;
+ data = (CharData *) malloc(sizeof(CharData) * max);
+ if (!data)
+ goto fail;
+ next = data;
+
+ sprintf(tmp, "%s.font.png", fontname);
+ if (glyphs.load(tmp, 0))
+ goto fail;
+
+ sprintf(tmp, "%s.font.dat", fontname);
+ header = (FontInfo*) load_file(tmp, &sz);
+ info = header->info;
+ if (sz < sizeof(FontInfo)) {
+ error("invalid font header");
+ goto fail;
+ }
+ if (header->magic != TEXTUREFONT_MAGIC) {
+ error("invalid font magic");
+ goto fail;
+ }
+ if (sz < (sizeof(FontInfo) + sizeof(CharInfo) * header->count)) {
+ error("missing font data");
+ goto fail;
+ }
+ first = header->first;
+ last = first + header->count - 1;
+
+ if (pgm.load("texturefont.vs", "texturefont.gs", "texturefont.fs"))
+ goto fail;
+
+ u.mvp.setOrtho(0, app->getWidth() - 1, app->getHeight() - 1, 0, -1, 1);
+ u.dim = glyphs.width;
+ vtx.load(data, sizeof(CharData) * max);
+ ubuf.load(&u, sizeof(u));
+
+ attr.init(layout, vdata, sizeof(layout) / sizeof(layout[0]));
+
+ dirty = 0;
+
+ color = RGBA(255,255,255,255);
+ return 0;
+fail:
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ if (header) {
+ free(header);
+ header = NULL;
+ }
+}
+
+void TextureFont::clear(void) {
+ next = data;
+ count = 0;
+}
+
+void TextureFont::setColor(unsigned rgba) {
+ color = rgba;
+}
+
+void TextureFont::render(App *app) {
+ if (count == 0)
+ return;
+
+ if (dirty) {
+ vtx.load(data, sizeof(CharData) * count);
+ dirty = 0;
+ }
+
+ pgm.use();
+ ubuf.use(0);
+ attr.use();
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDrawArrays(GL_POINTS, 0, count);
+ glDisable(GL_BLEND);
+}
+
+void TextureFont::puts(int x, int y, const char *s) {
+ while (count < max) {
+ unsigned n = *s++;
+ if (n == 0)
+ break;
+ if ((n < first) || (n > last))
+ continue;
+ n -= first;
+ data[count].x = x + info[n].dx;
+ data[count].y = y - info[n].dy;
+ data[count].w = info[n].w;
+ data[count].h = info[n].h;
+ data[count].s = info[n].x;
+ data[count].t = info[n].y;
+ data[count].rgba = color;
+ count++;
+ x += info[n].advance;
+ }
+ dirty = 1;
+}
+
+void TextureFont::printf(int x, int y, const char *fmt, ...) {
+ char buf[128];
+ int len;
+ va_list ap;
+ va_start(ap, fmt);
+ len = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ buf[127] = 0;
+ if (len > 127) len = 127;
+ puts(x, y, buf);
+}
diff --git a/common/texturefont.h b/common/texturefont.h
@@ -16,6 +16,9 @@
#ifndef _TEXTUREFONT_H_
#define _TEXTUREFONT_H_
+#include <app.h>
+#include <matrix.h>
+
struct CharInfo {
// location in texture
u16 x;
@@ -40,4 +43,48 @@ struct FontInfo {
#define TEXTUREFONT_MAGIC 0x746E6F46
+struct CharData {
+ u16 x, y, w, h;
+ u16 s, t;
+ u32 rgba;
+};
+
+class TextureFont {
+public:
+ int init(App *app, const char *fontname);
+ void render(App *app);
+ void clear(void);
+ void printf(int x, int y, const char *fmt, ...);
+ void puts(int x, int y, const char *s);
+ void setColor(unsigned rgba);
+private:
+ FontInfo *header;
+ CharInfo *info;
+ unsigned first;
+ unsigned last;
+
+ struct {
+ mat4 mvp;
+ float dim;
+ } u;
+
+ UniformBuffer ubuf;
+ VertexBuffer vtx;
+ VertexBuffer cbuf;
+ PixelShader ps;
+ GeometryShader gs;
+ VertexShader vs;
+ Program pgm;
+ Texture2D glyphs;
+ VertexAttributes attr;
+
+ CharData *data;
+ CharData *next;
+ unsigned count;
+ unsigned max;
+
+ unsigned color;
+ int dirty;
+};
+
#endif