initial release of new RasterFont without color support
this new design will once create a texture for all chars. while rendering a string, a list of polygons (position on screen + texture) for this string is generated on the fly and print at once by glDrawArrays. atm, there is no support for colors, so everything will display white. Signed-off-by: Ryan Houdek <Sonicadvance1@gmail.com>
This commit is contained in:
parent
c207422987
commit
75dd48247f
|
@ -22,7 +22,13 @@
|
||||||
#include "RasterFont.h"
|
#include "RasterFont.h"
|
||||||
// globals
|
// globals
|
||||||
|
|
||||||
const GLubyte rasters[][13] = {
|
|
||||||
|
static const u32 char_width = 8;
|
||||||
|
static const u32 char_height = 13;
|
||||||
|
static const u32 char_offset = 32;
|
||||||
|
static const u32 char_count = 95;
|
||||||
|
|
||||||
|
const u8 rasters[char_count][char_height] = {
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
|
||||||
|
@ -122,102 +128,122 @@ const GLubyte rasters[][13] = {
|
||||||
|
|
||||||
RasterFont::RasterFont()
|
RasterFont::RasterFont()
|
||||||
{
|
{
|
||||||
// set GL modes
|
// generate the texture
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glEnable(GL_TEXTURE_RECTANGLE);
|
||||||
// create the raster font
|
glGenTextures(1, &texture);
|
||||||
fontOffset = glGenLists(128);
|
glBindTexture(GL_TEXTURE_RECTANGLE, texture);
|
||||||
for (int i = 32; i < 127; i++) {
|
u32* texture_data = new u32[char_width*char_count*char_height];
|
||||||
glNewList(i + fontOffset, GL_COMPILE);
|
for(u32 y=0; y<char_height; y++) {
|
||||||
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
|
for(u32 c=0; c<char_count; c++) {
|
||||||
glEndList();
|
for(u32 x=0; x<char_width; x++) {
|
||||||
|
bool pixel = rasters[c][y] & (1<<(char_width-x-1));
|
||||||
|
texture_data[char_width*char_count*y+char_width*c+x] = pixel ? -1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, char_width*char_count, char_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
|
||||||
temp_buffer = new char[TEMP_BUFFER_SIZE];
|
delete [] texture_data;
|
||||||
|
|
||||||
|
// generate VBO & VAO
|
||||||
|
glGenBuffers(1, &VBO);
|
||||||
|
glGenVertexArrays(1, &VAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
|
glBindVertexArray(VAO);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glVertexPointer(2, GL_FLOAT, sizeof(GLfloat)*4, NULL);
|
||||||
|
glEnable(GL_TEXTURE_RECTANGLE);
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
|
||||||
}
|
}
|
||||||
|
|
||||||
RasterFont::~RasterFont()
|
RasterFont::~RasterFont()
|
||||||
{
|
{
|
||||||
glDeleteLists(fontOffset, 128);
|
glDeleteTextures(1, &texture);
|
||||||
delete [] temp_buffer;
|
glDeleteBuffers(1, &VBO);
|
||||||
|
glDeleteVertexArrays(1, &VAO);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterFont::printString(const char *s, double x, double y, double z)
|
void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight, u32 color)
|
||||||
{
|
{
|
||||||
int length = (int)strlen(s);
|
if(!(color & 0xffffff)) return; // color are not supported atm, so do not draw black shadows
|
||||||
|
|
||||||
|
int length = (int)strlen(text);
|
||||||
if (!length)
|
if (!length)
|
||||||
return;
|
return; // nothing to do
|
||||||
if (length >= TEMP_BUFFER_SIZE)
|
|
||||||
length = TEMP_BUFFER_SIZE - 1;
|
glBindVertexArray(VAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||||
// Sanitize string to avoid GL errors.
|
glBufferData(GL_ARRAY_BUFFER, length*4*6*sizeof(GLfloat), NULL, GL_STREAM_DRAW);
|
||||||
char *s2 = temp_buffer;
|
GLfloat *vertices = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||||
memcpy(s2, s, length);
|
|
||||||
s2[length] = 0;
|
int usage = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
GLfloat delta_x = 2*char_width/GLfloat(bbWidth);
|
||||||
if (s2[i] < 32 || s2[i] > 126)
|
GLfloat delta_y = 2*char_height/GLfloat(bbHeight);
|
||||||
s2[i] = '!';
|
GLfloat border_x = 1*2/GLfloat(bbWidth);
|
||||||
}
|
GLfloat border_y = 2*2/GLfloat(bbHeight);
|
||||||
|
|
||||||
// go to the right spot
|
GLfloat x = start_x;
|
||||||
glRasterPos3d(x, y, z);
|
GLfloat y = start_y;
|
||||||
GL_REPORT_ERRORD();
|
|
||||||
|
for(int i=0; i<length; i++) {
|
||||||
glPushAttrib (GL_LIST_BIT);
|
u8 c = text[i];
|
||||||
glListBase(fontOffset);
|
|
||||||
glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
|
if(c == '\n') {
|
||||||
GL_REPORT_ERRORD();
|
|
||||||
glPopAttrib();
|
|
||||||
GL_REPORT_ERRORD();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
|
|
||||||
{
|
|
||||||
int length = (int)strlen(s);
|
|
||||||
int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
|
|
||||||
printString(s, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
|
|
||||||
{
|
|
||||||
double x = start_x;
|
|
||||||
double y = start_y;
|
|
||||||
char temp[1024];
|
|
||||||
char *t = temp;
|
|
||||||
while (*text)
|
|
||||||
{
|
|
||||||
if (*text == '\n')
|
|
||||||
{
|
|
||||||
*t = 0;
|
|
||||||
printString(temp, x, y, z);
|
|
||||||
y -= char_height * 2.0f / bbHeight;
|
|
||||||
x = start_x;
|
x = start_x;
|
||||||
t = temp;
|
y -= delta_y + border_y;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (*text == '\r')
|
|
||||||
{
|
// do not print spaces, they can be skipped easyly
|
||||||
t = temp;
|
if(c == ' ') {
|
||||||
|
x += delta_x + border_x;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (*text == '\t')
|
|
||||||
{
|
if(c < char_offset || c >= char_count+char_offset) continue;
|
||||||
//todo: add tabs every something like 4*char_width
|
|
||||||
*t = 0;
|
vertices[usage++] = x;
|
||||||
int cpos = (int)strlen(temp);
|
vertices[usage++] = y;
|
||||||
int newpos = (cpos + 4) & (~3);
|
vertices[usage++] = (c-char_offset)*char_width;
|
||||||
printString(temp, x, y, z);
|
vertices[usage++] = 0;
|
||||||
x = start_x + (char_width*newpos) * 2.0f / bbWidth;
|
|
||||||
t = temp;
|
vertices[usage++] = x+delta_x;
|
||||||
*t++ = ' ';
|
vertices[usage++] = y;
|
||||||
}
|
vertices[usage++] = (c-char_offset+1)*char_width;
|
||||||
else
|
vertices[usage++] = 0;
|
||||||
*t++ = *text;
|
|
||||||
|
vertices[usage++] = x+delta_x;
|
||||||
text++;
|
vertices[usage++] = y+delta_y;
|
||||||
|
vertices[usage++] = (c-char_offset+1)*char_width;
|
||||||
|
vertices[usage++] = char_height;
|
||||||
|
|
||||||
|
vertices[usage++] = x;
|
||||||
|
vertices[usage++] = y;
|
||||||
|
vertices[usage++] = (c-char_offset)*char_width;
|
||||||
|
vertices[usage++] = 0;
|
||||||
|
|
||||||
|
vertices[usage++] = x+delta_x;
|
||||||
|
vertices[usage++] = y+delta_y;
|
||||||
|
vertices[usage++] = (c-char_offset+1)*char_width;
|
||||||
|
vertices[usage++] = char_height;
|
||||||
|
|
||||||
|
vertices[usage++] = x;
|
||||||
|
vertices[usage++] = y+delta_y;
|
||||||
|
vertices[usage++] = (c-char_offset)*char_width;
|
||||||
|
vertices[usage++] = char_height;
|
||||||
|
|
||||||
|
x += delta_x + border_x;
|
||||||
}
|
}
|
||||||
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
// no printable char, so also nothing to do
|
||||||
|
if(!usage) return;
|
||||||
|
|
||||||
// ????
|
glEnable(GL_BLEND);
|
||||||
if (t != text)
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||||
{
|
glActiveTexture(GL_TEXTURE0);
|
||||||
*t = 0;
|
glBindTexture(GL_TEXTURE_RECTANGLE, texture);
|
||||||
printString(temp, x, y, z);
|
glEnable(GL_TEXTURE_RECTANGLE);
|
||||||
}
|
glDrawArrays(GL_TRIANGLES, 0, usage/4);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,20 +23,13 @@ public:
|
||||||
RasterFont();
|
RasterFont();
|
||||||
~RasterFont(void);
|
~RasterFont(void);
|
||||||
static int debug;
|
static int debug;
|
||||||
|
|
||||||
// some useful constants
|
|
||||||
enum {char_width = 10};
|
|
||||||
enum {char_height = 15};
|
|
||||||
|
|
||||||
// and the happy helper functions
|
|
||||||
void printString(const char *s, double x, double y, double z=0.0);
|
|
||||||
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
|
|
||||||
|
|
||||||
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
|
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight, u32 color);
|
||||||
private:
|
private:
|
||||||
int fontOffset;
|
|
||||||
char *temp_buffer;
|
u32 VBO;
|
||||||
enum {TEMP_BUFFER_SIZE = 64 * 1024};
|
u32 VAO;
|
||||||
|
u32 texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _RASTERFONT_H_
|
#endif // _RASTERFONT_H_
|
||||||
|
|
|
@ -722,14 +722,11 @@ void Renderer::RenderText(const char *text, int left, int top, u32 color)
|
||||||
{
|
{
|
||||||
const int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
|
const int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
|
||||||
const int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
|
const int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
|
||||||
|
|
||||||
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
|
|
||||||
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
|
|
||||||
|
|
||||||
s_pfont->printMultilineText(text,
|
s_pfont->printMultilineText(text,
|
||||||
left * 2.0f / (float)nBackbufferWidth - 1,
|
left * 2.0f / (float)nBackbufferWidth - 1,
|
||||||
1 - top * 2.0f / (float)nBackbufferHeight,
|
1 - top * 2.0f / (float)nBackbufferHeight,
|
||||||
0, nBackbufferWidth, nBackbufferHeight);
|
0, nBackbufferWidth, nBackbufferHeight, color);
|
||||||
|
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,12 +101,11 @@ void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color)
|
||||||
{
|
{
|
||||||
int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
|
int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
|
||||||
int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
|
int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
|
||||||
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
|
|
||||||
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
|
|
||||||
s_pfont->printMultilineText(pstr,
|
s_pfont->printMultilineText(pstr,
|
||||||
left * 2.0f / (float)nBackbufferWidth - 1,
|
left * 2.0f / (float)nBackbufferWidth - 1,
|
||||||
1 - top * 2.0f / (float)nBackbufferHeight,
|
1 - top * 2.0f / (float)nBackbufferHeight,
|
||||||
0, nBackbufferWidth, nBackbufferHeight);
|
0, nBackbufferWidth, nBackbufferHeight, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWRenderer::DrawDebugText()
|
void SWRenderer::DrawDebugText()
|
||||||
|
|
Loading…
Reference in New Issue