Mercurial > projects > mde
comparison mde/resource/FontTexture.d @ 57:9e1f05fbbcef
Coloured and alpha-blended text is now supported.
TextWidgets get text colour from argument.
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Sat, 14 Jun 2008 13:09:03 +0100 |
parents | f000d6cd0f74 |
children | 7cab2af4ba21 |
comparison
equal
deleted
inserted
replaced
56:f9f5e04f20b2 | 57:9e1f05fbbcef |
---|---|
22 * coordinates, and OpenGL's model/world coordinates (for rendering). The freetype and texture | 22 * coordinates, and OpenGL's model/world coordinates (for rendering). The freetype and texture |
23 * coords are cartesian (i.e. y increases upwards), although largely this is too abstract to | 23 * coords are cartesian (i.e. y increases upwards), although largely this is too abstract to |
24 * matter. However, for the model/world coords, y increases downwards. */ | 24 * matter. However, for the model/world coords, y increases downwards. */ |
25 module mde.resource.FontTexture; | 25 module mde.resource.FontTexture; |
26 | 26 |
27 import mde.types.basic; // Colour | |
27 import mde.Options; | 28 import mde.Options; |
28 import mde.resource.exception; | 29 import mde.resource.exception; |
29 | 30 |
30 import derelict.freetype.ft; | 31 import derelict.freetype.ft; |
31 import derelict.opengl.gl; | 32 import derelict.opengl.gl; |
158 // Now increment i and continue with the next line if there is one. | 159 // Now increment i and continue with the next line if there is one. |
159 y += lineSep - yMax; | 160 y += lineSep - yMax; |
160 } | 161 } |
161 } | 162 } |
162 | 163 |
163 /** Render a block of text using a cache. Updates the cache if necessary. */ | 164 /** Render a block of text using a cache. Updates the cache if necessary. |
164 void drawTextCache (FT_Face face, char[] str, ref TextBlock cache, int x, int y) { | 165 * |
166 * Params: | |
167 * face = Current typeface pointer; must be passed from font.d (only needed if the cache is | |
168 * invalid) | |
169 * str = Text to render (only needed if the cache is invalid) | |
170 * cache = Cache used to speed up CPU-side rendering code | |
171 * x = Smaller x-coordinate of position | |
172 * y = Smaller y-coordinate of position | |
173 * col = Text colour (note: currently limited to black or white) */ | |
174 void drawCache (FT_Face face, char[] str, ref TextBlock cache, int x, int y, Colour col ) { | |
165 updateCache (face, str, cache); // update if necessary | 175 updateCache (face, str, cache); // update if necessary |
166 debug scope (failure) | 176 debug scope (failure) |
167 logger.error ("drawTextCache failed"); | 177 logger.error ("drawTextCache failed"); |
168 | 178 |
179 // opaque (GL_DECAL would be equivalent) | |
180 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | |
181 | |
182 drawCacheImpl (cache, x, y, col); | |
183 } | |
184 /** A variation of drawCache, for transparent text. | |
185 * | |
186 * Instead of passing the alpha value(s) as arguments, set the openGL colour prior to calling: | |
187 * --- | |
188 * glColor3f (.5f, .5f, .5f); // set alpha to half | |
189 * drawCacheA (face, ...); | |
190 * | |
191 * glColor3ub (0, 255, 127); // alpha 0 for red, 1 for green, half for blue | |
192 * drawCacheA (face, ...); | |
193 * --- | |
194 * | |
195 * The overhead of the transparency is minimal. */ | |
196 void drawCacheA (FT_Face face, char[] str, ref TextBlock cache, int x, int y, Colour col/+ = Colour.WHITE+/) { | |
197 updateCache (face, str, cache); // update if necessary | |
198 debug scope (failure) | |
199 logger.error ("drawTextCache failed"); | |
200 | |
201 // transparency alpha | |
202 // alpha is current colour, per component | |
203 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | |
204 | |
205 drawCacheImpl (cache, x, y, col); | |
206 } | |
207 | |
208 private void drawCacheImpl (ref TextBlock cache, int x, int y, Colour col) { | |
209 if (DerelictGL.availableVersion() >= GLVersion.Version14) { | |
210 glBlendFunc (GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR); | |
211 glBlendColor(col.r, col.g, col.b, 1f); // text colour | |
212 } else | |
213 glBlendFunc (col.nearestGLConst, GL_ONE_MINUS_SRC_COLOR); | |
214 | |
169 glEnable (GL_TEXTURE_2D); | 215 glEnable (GL_TEXTURE_2D); |
170 glEnable(GL_BLEND); | 216 glEnable(GL_BLEND); |
171 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_COLOR); | |
172 | 217 |
173 foreach (chr; cache.chars) { | 218 foreach (chr; cache.chars) { |
174 GlyphAttribs* ga = chr.ga; | 219 GlyphAttribs* ga = chr.ga; |
175 | 220 |
176 glBindTexture(GL_TEXTURE_2D, ga.texID); | 221 glBindTexture(GL_TEXTURE_2D, ga.texID); |
279 cachedGlyphs[chr] = ga; | 324 cachedGlyphs[chr] = ga; |
280 } | 325 } |
281 | 326 |
282 void drawTexture () { // temp func | 327 void drawTexture () { // temp func |
283 if (tex.length == 0) return; | 328 if (tex.length == 0) return; |
329 glEnable (GL_TEXTURE_2D); | |
284 glBindTexture(GL_TEXTURE_2D, tex[0].texID); | 330 glBindTexture(GL_TEXTURE_2D, tex[0].texID); |
285 glEnable (GL_TEXTURE_2D); | |
286 glEnable(GL_BLEND); | 331 glEnable(GL_BLEND); |
287 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_COLOR); | 332 glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_COLOR); |
333 float[4] Cc = [ 1.0f, 1f, 1f, 1f ]; | |
334 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, Cc.ptr); | |
335 glColor3f (1f, 0f, 0f); | |
288 | 336 |
289 glBegin (GL_QUADS); | 337 glBegin (GL_QUADS); |
290 glTexCoord2f (0f, 0f); glVertex2i (0, 0); | 338 glTexCoord2f (0f, 0f); glVertex2i (0, 0); |
291 glTexCoord2f (1f, 0f); glVertex2i (dimW, 0); | 339 glTexCoord2f (1f, 0f); glVertex2i (dimW, 0); |
292 glTexCoord2f (1f, 1f); glVertex2i (dimW, dimH); | 340 glTexCoord2f (1f, 1f); glVertex2i (dimW, dimH); |
310 struct LinePacker | 358 struct LinePacker |
311 { | 359 { |
312 // create a new texture | 360 // create a new texture |
313 static LinePacker create () { | 361 static LinePacker create () { |
314 LinePacker p; | 362 LinePacker p; |
315 //FIXME: check for error? | 363 //FIXME: why do I get a blank texture when binding to non-0? |
316 //glGenTextures (1, &(p.texID)); | 364 //glGenTextures (1, &(p.texID)); |
317 p.texID = 0; | 365 p.texID = 0; |
318 //FIXME: why do I get a blank texture when using bind? | |
319 glBindTexture(GL_TEXTURE_2D, p.texID); | |
320 | 366 |
321 // add a pretty background to the texture | 367 // add a pretty background to the texture |
322 static if (false) { | 368 static if (true) { |
323 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | 369 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
324 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); | 370 glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); |
325 ubyte[3][dimH][dimW] testTex; | 371 ubyte[3][dimH][dimW] testTex; |
326 for (size_t i = 0; i < dimW; ++i) | 372 for (size_t i = 0; i < dimW; ++i) |
327 for (size_t j = 0; j < dimH; ++j) | 373 for (size_t j = 0; j < dimH; ++j) |
333 void* ptr = testTex.ptr; | 379 void* ptr = testTex.ptr; |
334 } else | 380 } else |
335 const void* ptr = null; | 381 const void* ptr = null; |
336 | 382 |
337 // Create a texture without initialising values. | 383 // Create a texture without initialising values. |
338 glTexImage2D(GL_TEXTURE_2D, 0, 3, | 384 glBindTexture(GL_TEXTURE_2D, p.texID); |
385 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, | |
339 dimW, dimH, 0, | 386 dimW, dimH, 0, |
340 GL_RGB, GL_UNSIGNED_BYTE, ptr); | 387 GL_RGB, GL_UNSIGNED_BYTE, ptr); |
341 return p; | 388 return p; |
342 } | 389 } |
343 | 390 |