graphics

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

commit 8a5148e5771b02df1e2759a3ee5072148b7622fb
parent 7e8d64c03ab7597ce8b8805d7e39af2bd4273b59
Author: Brian Swetland <swetland@frotz.net>
Date:   Thu,  5 Sep 2013 20:04:16 -0700

texturefont: stop using geometry shaders

Diffstat:
Mcommon/assets/texturefont.glsl | 86++++++++++++++++++++++---------------------------------------------------------
Mcommon/texturefont.cc | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Mcommon/texturefont.h | 17++++++++---------
3 files changed, 124 insertions(+), 94 deletions(-)

diff --git a/common/assets/texturefont.glsl b/common/assets/texturefont.glsl @@ -1,77 +1,39 @@ -#version 150 -#extension GL_ARB_separate_shader_objects : enable +#version 140 +#extension GL_ARB_explicit_attrib_location : enable -layout(std140) uniform udata0 { - mat4 MVP; - vec2 adj; - float dim; +uniform samplerBuffer sampler0; // character data +uniform sampler2D sampler1; // glyph texture + +layout(std140) uniform block3 { + mat4 xMVP; }; -- 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; +layout(location = 0) in ivec4 aData; // X, Y, ID, RGBA -in vec2 size[1]; -in vec2 tex[1]; -in vec4 vcolor[1]; - -out vec2 s0tc; -out vec4 color; +out vec2 vTexCoord; +out vec4 vColor; void main() { - vec4 p = gl_in[0].gl_Position; - vec2 sz = size[0]; - vec2 tsz = sz - vec2(1.0,1.0); - - gl_Position = MVP * vec4(p.x, p.y - sz.y, 0.0, 1.0); - s0tc = tex[0] / dim + adj; - color = vcolor[0]; - EmitVertex(); - - gl_Position = MVP * vec4(p.x + sz.x, p.y - sz.y, 0.0, 1.0); - s0tc = (tex[0] + vec2(tsz.x,0)) / dim + adj; - color = vcolor[0]; - EmitVertex(); - - gl_Position = MVP * vec4(p.x, p.y, 0.0, 1.0); - s0tc = (tex[0] + vec2(0,tsz.y)) / dim + adj; - color = vcolor[0]; - EmitVertex(); - - gl_Position = MVP * vec4(p.x + sz.x, p.y, 0.0, 1.0); - s0tc = (tex[0] + tsz) / dim + adj; - color = vcolor[0]; - EmitVertex(); - - EndPrimitive(); + vec4 cdata = texelFetch(sampler0, aData.z + gl_VertexID); + vec4 pos = vec4(aData.x + cdata.x, aData.y + cdata.y, 0.0, 1.0); + vColor = vec4( + float(aData.w & 0xFF) / 255.0, + float((aData.w >> 8) & 0xFF) / 255.0, + float((aData.w >> 16) & 0xFF) / 255.0, + 1.0 + ); + vTexCoord = vec2(cdata.zw); + gl_Position = xMVP * pos; } -- fs -uniform sampler2D s0glyphs; - -in vec2 s0tc; -in vec4 color; +in vec2 vTexCoord; +in vec4 vColor; void main() { - vec4 c = texture2D(s0glyphs, s0tc); - gl_FragColor = vec4(color.r, color.g, color.b, c.r); + vec4 c = texture2D(sampler1, vTexCoord); + gl_FragColor = vec4(vColor.rgb, c.r); } diff --git a/common/texturefont.cc b/common/texturefont.cc @@ -20,20 +20,26 @@ #include "app.h" #include "texturefont.h" +/* performance experiments to try sometime: + * - pass color via vtx attr instead of unpacking in shader + * - pass character vertex table via uniform instead of texturebuffer + * - instead of DrawArraysInstanced: + * - call DrawElements with a fixed 1,1,1,1,1,1,2,2,2,2,2,2,3,... index buffer + * - call DrawArrays with unpacked vtx array (6 per character) + * - explore different vtx formats (int vs float vs short, etc) +*/ + // 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 }, + { 0, SRC_INT32, DST_INTEGER, 4, 0, 16, 6 }, }; int TextureFont::init(App *app, const char *fontname) { - VertexBuffer *vdata[] = { - &vtx, &vtx, &vtx, - }; + VertexBuffer *vdata[] = { &vtx }; char tmp[256]; + float *cdata, *cp; + float dim, adj; unsigned sz; - header = NULL; max = 128; count = 0; @@ -64,21 +70,62 @@ int TextureFont::init(App *app, const char *fontname) { first = header->first; last = first + header->count - 1; - if (pgm.load("texturefont.vs", "texturefont.gs", "texturefont.fs")) + if (pgm.load("texturefont.vs", "texturefont.fs")) goto fail; - u.mvp.setOrtho(0, app->getWidth(), app->getHeight(), 0, -1, 1); - u.dim = glyphs.width; - u.adj[0] = 0.5 / float(glyphs.width); - u.adj[1] = 0.5 / float(glyphs.width); + cp = cdata = (float*) malloc(sizeof(float) * 4 * 6 * header->count); + + /* to adjust int coords to texture coords */ + dim = glyphs.width; + adj = 0.5 / float(glyphs.width); + + /* generate a 2d+uv quad for each character */ + for (unsigned n = 0; n < header->count; n++) { + *cp++ = 0; + *cp++ = -info[n].h; + *cp++ = float(info[n].x) / dim + adj; + *cp++ = float(info[n].y) / dim + adj; + + *cp++ = info[n].w; + *cp++ = -info[n].h; + *cp++ = float(info[n].x + info[n].w - 1) / dim + adj; + *cp++ = float(info[n].y) / dim + adj; + + *cp++ = 0; + *cp++ = 0; + *cp++ = float(info[n].x) / dim + adj; + *cp++ = float(info[n].y + info[n].h - 1) / dim + adj; + + *cp++ = info[n].w; + *cp++ = 0; + *cp++ = float(info[n].x + info[n].w - 1) / dim + adj; + *cp++ = float(info[n].y + info[n].h - 1) / dim + adj; + + *cp++ = 0; + *cp++ = 0; + *cp++ = float(info[n].x) / dim + adj; + *cp++ = float(info[n].y + info[n].h - 1) / dim + adj; + + *cp++ = info[n].w; + *cp++ = -info[n].h; + *cp++ = float(info[n].x + info[n].w - 1) / dim + adj; + *cp++ = float(info[n].y) / dim + adj; + } + cbuf.load(cdata, sizeof(float) * 4 * 6 * header->count); vtx.load(data, sizeof(CharData) * max); - ubuf.load(&u, sizeof(u)); - attr.init(layout, vdata, sizeof(layout) / sizeof(layout[0])); + mvp.setOrtho(0, app->getWidth(), app->getHeight(), 0, -1, 1); + ubuf.load(&mvp, sizeof(mvp)); + attr.init(layout, vdata, sizeof(layout) / sizeof(layout[0])); dirty = 0; - color = RGBA(255,255,255,255); + glGenTextures(1, &tbid); + glActiveTexture(GL_TEXTURE0 + 15); + glBindTexture(GL_TEXTURE_BUFFER, tbid); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, cbuf.id); + + color = RGBA(255,255,255,0); return 0; fail: if (data) { @@ -112,15 +159,40 @@ void TextureFont::render(App *app) { } pgm.use(); - ubuf.use(0); + ubuf.use(3); attr.use(); - glyphs.use(0); + glyphs.use(1); + glActiveTexture(GL_TEXTURE0 + 0); + glBindTexture(GL_TEXTURE_BUFFER, tbid); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, cbuf.id); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDrawArrays(GL_POINTS, 0, count); + glDrawArraysInstanced(GL_TRIANGLES, 0, 6, count * 6); glDisable(GL_BLEND); } +void TextureFont::measure(const char *s, unsigned *width, unsigned *height) { + unsigned w = 0; + unsigned h = 0; + while (*s) { + unsigned n = *s++; + if (n == 0) + break; + if ((n < first) || (n > last)) + continue; + n -= first; + unsigned ch = info[n].h; + unsigned cw = info[n].w; + if (ch > h) + h = ch; + w += cw; + if (*s) + w += info[n].advance; + } + *width = w; + *height = h; +} + void TextureFont::puts(int x, int y, const char *s) { while (count < max) { unsigned n = *s++; @@ -131,11 +203,8 @@ void TextureFont::puts(int x, int y, const char *s) { 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; + data[count].id = n * 6; + data[count].rgba = color & 0xFFFFFF; // strip alpha count++; x += info[n].advance; } diff --git a/common/texturefont.h b/common/texturefont.h @@ -44,9 +44,10 @@ struct FontInfo { #define TEXTUREFONT_MAGIC 0x746E6F46 struct CharData { - u16 x, y, w, h; - u16 s, t; - u32 rgba; + int x; + int y; + int id; + int rgba; }; class TextureFont { @@ -57,18 +58,14 @@ public: void printf(int x, int y, const char *fmt, ...); void puts(int x, int y, const char *s); void setColor(unsigned rgba); + void measure(const char *s, unsigned *width, unsigned *height); private: FontInfo *header; CharInfo *info; unsigned first; unsigned last; - struct { - mat4 mvp; - float adj[2]; - float dim; - } u; - + mat4 mvp; UniformBuffer ubuf; VertexBuffer vtx; VertexBuffer cbuf; @@ -79,6 +76,8 @@ private: Texture2D glyphs; VertexAttributes attr; + unsigned tbid; + CharData *data; CharData *next; unsigned count;