ref: 8aad8a662851860ee6aa157ccaf45283fa261cec
parent: e2054918a606d89c47027c37a8b3a6c88d6203f8
author: Clownacy <Clownacy@users.noreply.github.com>
date: Tue Jul 23 16:05:38 EDT 2019
Font refactor part 4: Thy Flesh Co- I mean, OpenGL Hard mode. Wound up debugging a weird issue for about half an hour. Turns out you don't need to reset the matrix when you switch framebuffer target? I don't really know how that works. Anyway, yay font rendering is in the OpenGL backend now.
--- a/src/Backends/Rendering/OpenGL2.cpp
+++ b/src/Backends/Rendering/OpenGL2.cpp
@@ -18,6 +18,13 @@
unsigned char *pixels;
} Backend_Surface;
+typedef struct Backend_Glyph
+{
+ GLuint texture_id;
+ unsigned int width;
+ unsigned int height;
+} Backend_Glyph;
+
static SDL_Window *window;
static SDL_GLContext context;
static GLuint colour_key_program_id;
@@ -88,6 +95,8 @@
// glLoadIdentity();
glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
@@ -228,14 +237,7 @@
// Point our framebuffer to the destination texture
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, destination_surface->texture_id, 0);
- // The matrix needs resetting to fit the dimensions of the destination texture
- glPushMatrix();
- glLoadIdentity();
- glOrtho(0.0, destination_surface->width, 0.0, destination_surface->height, 1.0, -1.0);
-
BlitCommon(source_surface, rect, x, y, colour_key);
-
- glPopMatrix();
}
void Backend_BlitToScreen(Backend_Surface *source_surface, const RECT *rect, long x, long y, BOOL colour_key)
@@ -268,14 +270,7 @@
// Point our framebuffer to the destination texture
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, surface->texture_id, 0);
- // The matrix needs resetting to fit the dimensions of the destination texture
- glPushMatrix();
- glLoadIdentity();
- glOrtho(0.0, surface->width, 0.0, surface->height, 1.0, -1.0);
-
ColourFillCommon(rect, red, green, blue);
-
- glPopMatrix();
}
void Backend_ColourFillToScreen(const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
@@ -291,24 +286,116 @@
// Point our framebuffer to the destination texture
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, surface->texture_id, 0);
- // The matrix needs resetting to fit the dimensions of the destination texture
- glPushMatrix();
- glLoadIdentity();
- glOrtho(0.0, surface->width, 0.0, surface->height, 1.0, -1.0);
-
BlitCommon(&framebuffer_surface, rect, rect->left, rect->top, FALSE);
+}
- glPopMatrix();
+BOOL Backend_SupportsSubpixelGlyph(void)
+{
+ return FALSE; // Per-component alpha is available as an extension, but I haven't looked into it yet
}
-void Backend_DrawText(Backend_Surface *surface, FontObject *font, int x, int y, const char *text, unsigned long colour)
+Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, unsigned short total_greys, unsigned char pixel_mode)
{
- // Soon
+ Backend_Glyph *glyph = (Backend_Glyph*)malloc(sizeof(Backend_Glyph));
+
+ if (glyph == NULL)
+ return NULL;
+
+ unsigned char *buffer = (unsigned char*)malloc(width * height * 4);
+
+ switch (pixel_mode)
+ {
+ // FONT_PIXEL_MODE_LCD is unsupported
+
+ case FONT_PIXEL_MODE_GRAY:
+ for (unsigned int y = 0; y < height; ++y)
+ {
+ const unsigned char *source_pointer = pixels + y * pitch;
+ unsigned char *destination_pointer = buffer + y * width * 4;
+
+ for (unsigned int x = 0; x < width; ++x)
+ {
+ *destination_pointer++ = 0xFF;
+ *destination_pointer++ = 0xFF;
+ *destination_pointer++ = 0xFF;
+ *destination_pointer++ = (unsigned char)(pow((double)*source_pointer++ / (total_greys - 1), 1.0 / 1.8) * 255.0);
+ }
+ }
+
+ break;
+
+ case FONT_PIXEL_MODE_MONO:
+ for (unsigned int y = 0; y < height; ++y)
+ {
+ const unsigned char *source_pointer = pixels + y * pitch;
+ unsigned char *destination_pointer = buffer + y * width * 4;
+
+ for (unsigned int x = 0; x < width; ++x)
+ {
+ *destination_pointer++ = 0xFF;
+ *destination_pointer++ = 0xFF;
+ *destination_pointer++ = 0xFF;
+ *destination_pointer++ = *source_pointer++ ? 0xFF : 0;
+ }
+ }
+
+ break;
+ }
+
+ glGenTextures(1, &glyph->texture_id);
+ glBindTexture(GL_TEXTURE_2D, glyph->texture_id);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glyph->width = width;
+ glyph->height = height;
+
+ free(buffer);
+
+ return glyph;
}
-void Backend_DrawTextToScreen(FontObject *font, int x, int y, const char *text, unsigned long colour)
+void Backend_UnloadGlyph(Backend_Glyph *glyph)
{
- // Soon
+ glDeleteTextures(1, &glyph->texture_id);
+ free(glyph);
+}
+
+static void DrawGlyphCommon(Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
+{
+ // Disable colour-keying
+ glUseProgram(0);
+
+ glBindTexture(GL_TEXTURE_2D, glyph->texture_id);
+
+ glBegin(GL_QUADS);
+ glColor3f(colours[0] / 255.0f, colours[1] / 255.0f, colours[2] / 255.0f);
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex2f((GLfloat)x, (GLfloat)y);
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex2f((GLfloat)x + glyph->width, (GLfloat)y);
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex2f((GLfloat)x + glyph->width, (GLfloat)y + glyph->height);
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex2f((GLfloat)x, (GLfloat)y + glyph->height);
+ glEnd();
+}
+
+void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
+{
+ // Point our framebuffer to the destination texture
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, surface->texture_id, 0);
+
+ DrawGlyphCommon(glyph, x, y, colours);
+}
+
+void Backend_DrawGlyphToScreen(Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
+{
+ // Point our framebuffer to the screen texture
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, framebuffer_surface.texture_id, 0);
+
+ DrawGlyphCommon(glyph, x, y, colours);
}
void Backend_HandleDeviceLoss(void)