debugtext.cc (6417B)
1 /* Copyright 2013 Brian Swetland <swetland@frotz.net> 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <stdarg.h> 19 #include <string.h> 20 #ifndef _WIN32 21 #include <unistd.h> 22 #endif 23 24 #include "opengl.h" 25 #include "util.h" 26 #include "matrix.h" 27 28 #include "debugtext.h" 29 30 struct DebugTextCell { 31 unsigned char x; 32 unsigned char y; 33 unsigned char z; 34 unsigned char w; 35 unsigned char u; 36 unsigned char v; 37 unsigned char i; 38 unsigned char j; 39 }; 40 41 static void dtc_init(DebugTextCell *data, int w, int h) { 42 int x, y; 43 DebugTextCell *p = data; 44 memset(p, 0, sizeof(DebugTextCell) * w * h * 6); 45 y = 1; 46 for (y = h; y > 0; y--) { 47 for (x = 0; x < w; x++) { 48 p->x = x+0; p->y = y+0; 49 p->u = 0; p->v = 0; p->i = x; p->j = h-y; p++; 50 p->x = x+0; p->y = y-1; 51 p->u = 0; p->v = 1; p->i = x; p->j = h-y; p++; 52 p->x = x+1; p->y = y-1; 53 p->u = 1; p->v = 1; p->i = x; p->j = h-y; p++; 54 p->x = x+1; p->y = y-1; 55 p->u = 1; p->v = 1; p->i = x; p->j = h-y; p++; 56 p->x = x+1; p->y = y+0; 57 p->u = 1; p->v = 0; p->i = x; p->j = h-y; p++; 58 p->x = x+0; p->y = y+0; 59 p->u = 0; p->v = 0; p->i = x; p->j = h-y; p++; 60 } 61 } 62 } 63 64 static const char *vsrc = 65 "uniform mat4 uMVP;" 66 "uniform sampler2D uTexture1;" 67 "attribute vec4 aVertex;" 68 "attribute vec4 aTexCoord;" 69 "" 70 "varying vec4 vTexCoord;" 71 "const float cbw = 32.0;" 72 "const float cbh = 32.0;" 73 "" 74 "void main() {" 75 " gl_Position = uMVP * vec4(aVertex.xy,0.0,1.0);" 76 " vTexCoord = aTexCoord;" 77 "}"; 78 79 static const char *fsrc = 80 "uniform sampler2D uTexture0;" 81 "uniform sampler2D uTexture1;" 82 "" 83 "varying vec4 vTexCoord; /* u, v, cx, cy */" 84 "" 85 "/* width and height of the character buffer */" 86 "const float cbw = 32.0;" 87 "const float cbh = 32.0;" 88 "" 89 "/* cell count (h & v) for character map */" 90 "const float cc = 16.0;" 91 "" 92 "void main() {" 93 " vec2 base, offset;" 94 " float ch;" 95 "" 96 " /* look up characer in cbw x cbh character buffer texture */" 97 " ch = texture2D(uTexture1, vec2(vTexCoord.z / cbw, vTexCoord.w / cbh)).a" 98 " * 255.0 + 0.001953125;" 99 "" 100 " /* base texcoord of ch (0..255) in cc x cc character map texture */" 101 " base = vec2(fract(ch / cc), -floor(ch / cc) / cc);" 102 "" 103 " /* scale offset texcoord */" 104 " offset = vTexCoord.xy / cc;" 105 "" 106 " gl_FragColor = texture2D(uTexture0, base + offset * vec2(1.0,-1.0));" 107 "}"; 108 109 int DebugText::init(unsigned w, unsigned h) { 110 cbw = w; 111 cbh = h; 112 cx = 0; 113 cy = 0; 114 dirty = 0; 115 116 data = (DebugTextCell*) malloc(sizeof(DebugTextCell) * w * h * 6); 117 cbdata = (unsigned char*) malloc(sizeof(unsigned char) * w * h); 118 119 dtc_init(data, w, h); 120 121 if (!(fontdata = load_png_rgba("font-vincent-8x8.png", &fdw, &fdh, 1))) 122 return -1; 123 124 if (pgm.compileStr(vsrc, fsrc)) 125 return -1; 126 127 aVertex = pgm.getAttribID("aVertex"); 128 aTexCoord = pgm.getAttribID("aTexCoord"); 129 uMVP = pgm.getUniformID("uMVP"); 130 uTex0 = pgm.getUniformID("uTexture0"); 131 uTex1 = pgm.getUniformID("uTexture1"); 132 133 glGenTextures(1, &tex0); 134 glGenTextures(1, &tex1); 135 136 glBindTexture(GL_TEXTURE_2D, tex0); 137 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fdw, fdh, 0, GL_RGBA, 138 GL_UNSIGNED_BYTE, fontdata); 139 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 141 142 memset(cbdata, 0, cbw * cbh); 143 144 glBindTexture(GL_TEXTURE_2D, tex1); 145 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, cbw, cbh, 0, GL_ALPHA, 146 GL_UNSIGNED_BYTE, cbdata); 147 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 149 150 glGenBuffers(1, &vbo); 151 glBindBuffer(GL_ARRAY_BUFFER, vbo); 152 glBufferData(GL_ARRAY_BUFFER, sizeof(DebugTextCell) * cbw * cbh * 6, 153 data, GL_STATIC_DRAW); 154 155 return 0; 156 } 157 158 int DebugText::render(void) { 159 mat4 MVP; 160 MVP.setOrtho(0.0, cbw, 0.0, cbh, 1.0, -1.0); 161 162 pgm.use(); 163 164 glActiveTexture(GL_TEXTURE0); 165 glBindTexture(GL_TEXTURE_2D, tex0); 166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 168 169 glActiveTexture(GL_TEXTURE1); 170 glBindTexture(GL_TEXTURE_2D, tex1); 171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 173 174 if (dirty) { 175 dirty = 0; 176 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, cbw, cbh, 0, GL_ALPHA, 177 GL_UNSIGNED_BYTE, cbdata); 178 } 179 180 glUniformMatrix4fv(uMVP, 1, GL_FALSE, MVP); 181 glUniform1i(uTex0, 0); 182 glUniform1i(uTex1, 1); 183 184 glEnable(GL_BLEND); 185 glDisable(GL_DEPTH_TEST); 186 187 glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA); 188 189 glBindBuffer(GL_ARRAY_BUFFER, vbo); 190 191 glVertexAttribPointer(aVertex, 4, GL_UNSIGNED_BYTE, GL_FALSE, 8, (void*) 0); 192 glVertexAttribPointer(aTexCoord, 4, GL_UNSIGNED_BYTE, GL_FALSE, 8, (void*) 4); 193 194 glEnableVertexAttribArray(aVertex); 195 glEnableVertexAttribArray(aTexCoord); 196 197 glDrawArrays(GL_TRIANGLES, 0, cbw * cbh * 6); 198 glDisableVertexAttribArray(aVertex); 199 glDisableVertexAttribArray(aTexCoord); 200 201 return 0; 202 } 203 204 void DebugText::putch(unsigned c) { 205 switch (c) { 206 case 10: 207 cx = 0; 208 if (cy < cbh - 1) 209 cy++; 210 return; 211 case 13: 212 return; 213 case 9: 214 c = ' '; 215 break; 216 } 217 cbdata[cx + cy * cbw] = c; 218 219 if (++cx == cbw) { 220 cx = 0; 221 if (++cy == cbh) { 222 cy = cbh - 1; 223 } 224 } 225 226 dirty = 1; 227 } 228 229 void DebugText::puts(const char *s) { 230 while (*s) 231 putch(*s++); 232 } 233 234 void DebugText::clear(void) { 235 memset(cbdata, 0, cbw * cbh); 236 cx = 0; 237 cy = 0; 238 dirty = 1; 239 } 240 241 void DebugText::printf(const char *fmt, ...) { 242 va_list ap; 243 char tmp[128]; 244 245 va_start(ap, fmt); 246 vsnprintf(tmp, sizeof(tmp), fmt, ap); 247 va_end(ap); 248 249 puts(tmp); 250 } 251 252 #if 0 253 DebugText DT; 254 255 int scene_init(struct ctxt *c) { 256 glViewport(0, 0, c->width, c->height); 257 glClearColor(0, 0, 180, 255); 258 glClearDepth(1.0f); 259 DT.init(32, 32); 260 return 0; 261 } 262 263 int fr = 0; 264 265 int scene_draw(struct ctxt *c) { 266 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 267 DT.printf("Frame #%d\n", fr++); 268 DT.render(); 269 return 0; 270 } 271 #endif