graphics

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Acommon/assets/texturefont.glsl | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcommon/module.mk | 1+
Acommon/texturefont.cc | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcommon/texturefont.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
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