Text rendering working again

master
Joey Pollack 3 years ago
parent f88c8a8918
commit dfa237d2be

@ -7,6 +7,7 @@
******************************************************************************/ ******************************************************************************/
#include "text_renderer.h" #include "text_renderer.h"
#include "renderer2D.h"
#include <utils/logger.h> #include <utils/logger.h>
#include "texture.h" #include "texture.h"
@ -99,6 +100,8 @@ namespace lunarium
u32 max_width = 0; u32 max_width = 0;
u32 max_height = 0; u32 max_height = 0;
u32 running_width = 0;
for (u8 c = 0; c < 128; c++) for (u8 c = 0; c < 128; c++)
{ {
// Load character glyph // Load character glyph
@ -115,7 +118,7 @@ namespace lunarium
Character character = Character Character character = Character
{ {
c, pixel_data, 0, 0, Sizeu { width, height }, c, pixel_data, 0, 0, Sizei { (i32)width, (i32)height },
glm::vec2((float)face->glyph->bitmap_left, (float)face->glyph->bitmap_top), // bearing glm::vec2((float)face->glyph->bitmap_left, (float)face->glyph->bitmap_top), // bearing
(int)face->glyph->bitmap.rows - face->glyph->bitmap_top, // downshift (int)face->glyph->bitmap.rows - face->glyph->bitmap_top, // downshift
(unsigned int)face->glyph->advance.x // advance (unsigned int)face->glyph->advance.x // advance
@ -147,6 +150,13 @@ namespace lunarium
} }
} }
// Set the character's texture offsets to the max values
for (int i = 0; i < mFonts.back().CharSet.size(); i++)
{
mFonts.back().CharSet[i].TextureDataWidthOffset = max_width * i;
mFonts.back().CharSet[i].TextureDataHeightOffset = 0; // TEXTURE IS ONE ROW SO THIS IS ALWAYS ZERO
}
// Put the font texture together // Put the font texture together
u32 single_row_width = f.CharSet.size() * max_width; u32 single_row_width = f.CharSet.size() * max_width;
if (single_row_width > Texture::GetMaxSize()) if (single_row_width > Texture::GetMaxSize())
@ -190,9 +200,85 @@ namespace lunarium
return fontIdx; return fontIdx;
} }
void TextRenderer::DrawString(Renderer2D& r, u32 font_id, const char* str, Rectangle bounding_box, Color c, float scale) void TextRenderer::DrawString(Renderer2D& r, u32 font_id, const char* str, Rectangle bounding_box, Color color, float scale)
{
if (font_id < 0 || font_id >= mFonts.size())
{
Logger::Error(LogCategory::GRAPHICS, "Invalid font ID specified for DrawString: %d", font_id);
return;
}
float lineSize = (mFonts[font_id].MaxHeight + mFonts[font_id].MaxDownShift) * scale;
float curX = bounding_box.left(); //topLeft.x;
float curY = bounding_box.top(); //topLeft.y;
// Iterate through all characters
int len = (int)strlen(str);
for (int c = 0; c < len; c++)
{
// if the last character was a space then we must
// be starting a new word
if (c > 0 && ' ' == str[c - 1])
{
// check the total advance of this word to see if
// it would go beyond the right boundry
float totalAdvance = 0;
for (int i = c; str[i] != ' ' && str[i] != '\0'; i++)
{
Character ch = mFonts[font_id].CharSet[str[c]];
totalAdvance += (ch.Advance >> 6) * scale;
}
if (curX + totalAdvance > bounding_box.right())
{
curX = bounding_box.left();
curY += lineSize;
}
if (curY + lineSize > bounding_box.bottom())
{ {
break;
}
}
Character ch = mFonts[font_id].CharSet[str[c]];
float xpos = curX + ch.Bearing.x * scale;
float ypos = curY + (mFonts[font_id].MaxHeight - ch.Size.Height) * scale;
// Apply a down offset if the char should go below the baseline
ypos += (ch.DownShift * scale);
// NOTE: The following code does not work because it assumes that positive y is the upward direction
//
//GLfloat test_ypos = curY + (ch.Size.Height - ch.Bearing.Y) * scale;
//
float w = ch.Size.Width * scale;
float h = ch.Size.Height * scale;
// Update VBO for each character
// float vertices[6][4] = {
// { xpos, ypos + h, 0.0, 1.0 },
// { xpos + w, ypos, 1.0, 0.0 },
// { xpos, ypos, 0.0, 0.0 },
// { xpos, ypos + h, 0.0, 1.0 },
// { xpos + w, ypos + h, 1.0, 1.0 },
// { xpos + w, ypos, 1.0, 0.0 }
// };
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
curX += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64)
// DrawQuad
float offset_x = ch.TextureDataWidthOffset;
float offset_y = ch.TextureDataHeightOffset;
Rectangle tex_region = Rectangle::MakeFromTopLeft(offset_x, offset_y, ch.Size.Width, ch.Size.Height);
r.DrawQuad(Rectangle::MakeFromTopLeft(xpos, ypos, w, h), color, mFonts[font_id].FontTexture, 0.0f, tex_region);
}
} }

@ -53,7 +53,7 @@ namespace lunarium
u8* PixelDataBuffer; // Temporary storage for the character's pixel data - this should be cleanup after the font texture is created u8* PixelDataBuffer; // Temporary storage for the character's pixel data - this should be cleanup after the font texture is created
u32 TextureDataWidthOffset; // how far into the row does this chars texture data begin u32 TextureDataWidthOffset; // how far into the row does this chars texture data begin
u32 TextureDataHeightOffset; // how far into the col does this chars texture data begin u32 TextureDataHeightOffset; // how far into the col does this chars texture data begin
Sizeu Size; // Size of glyph Sizei Size; // Size of glyph
glm::vec2 Bearing; // Offset from baseline to left/top of glyph glm::vec2 Bearing; // Offset from baseline to left/top of glyph
int DownShift; // Size/Amount of glyph below the baseline int DownShift; // Size/Amount of glyph below the baseline
unsigned int Advance; // Offset to advance to next glyph unsigned int Advance; // Offset to advance to next glyph
@ -65,7 +65,7 @@ namespace lunarium
std::string Name; std::string Name;
// The tallest character that does not go below the base line // The tallest character that does not go below the base line
// This is also the distance from the string Y position to the baseline // This is also the distance from the string Y position to the baseline
u32 MaxHeight; i32 MaxHeight;
// This is the max distance a char will go below the baseline // This is the max distance a char will go below the baseline
u32 MaxDownShift; u32 MaxDownShift;

@ -27,7 +27,7 @@
namespace lunarium namespace lunarium
{ {
SimpleRenderScene::SimpleRenderScene(uint32_t logCat) SimpleRenderScene::SimpleRenderScene(uint32_t logCat)
: BaseScene(logCat), mTestMode(TestMode::String), mFrameTime(0.0), mNumFrames(0) : BaseScene(logCat), mTestMode(TestMode::Basic), mFrameTime(0.0), mNumFrames(0), mpTestImageLoad3(nullptr)
{ {
srand((u32)time(0)); srand((u32)time(0));
} }
@ -65,9 +65,10 @@ namespace lunarium
mSrcWidth = w; mSrcWidth = w;
mSrcHeight = h; mSrcHeight = h;
//delete[] buffer; delete[] buffer;
stbi_set_flip_vertically_on_load(0); stbi_set_flip_vertically_on_load(0);
buffer = stbi_load("debug_texture.jpeg", &w, &h, &n, 0); buffer = stbi_load("debug_texture.jpeg", &w, &h, &n, 0);
//buffer = stbi_load("lunarium_text_test.png", &w, &h, &n, 0);
format = TextureFormat::RGBA; format = TextureFormat::RGBA;
if (n == 3) if (n == 3)
@ -80,7 +81,23 @@ namespace lunarium
} }
mpTestImageLoad2 = Texture::Create(buffer, w, h, format); mpTestImageLoad2 = Texture::Create(buffer, w, h, format);
//delete[] buffer; delete[] buffer;
stbi_set_flip_vertically_on_load(0);
buffer = stbi_load("lunarium_text_test.png", &w, &h, &n, 0);
format = TextureFormat::RGBA;
if (n == 3)
{
format = TextureFormat::RGB;
}
else if (n == 1)
{
format = TextureFormat::RED;
}
mpTestImageLoad3 = Texture::Create(buffer, w, h, format);
delete[] buffer;
mQuads = new Rectangle[NUM_QUADS]; mQuads = new Rectangle[NUM_QUADS];
for (int i = 0; i < NUM_QUADS; i++) for (int i = 0; i < NUM_QUADS; i++)
@ -181,10 +198,16 @@ namespace lunarium
mTestMode = TestMode::Stress; mTestMode = TestMode::Stress;
else if (mTestMode == TestMode::Stress) else if (mTestMode == TestMode::Stress)
{
mSubTex = Rectangle::MakeFromTopLeft(2858, 0, 32, 32);
mTestMode = TestMode::String; mTestMode = TestMode::String;
}
else if (mTestMode == TestMode::String) else if (mTestMode == TestMode::String)
{
mTestMode = TestMode::Basic; mTestMode = TestMode::Basic;
mSubTex = Rectangle::MakeFromTopLeft(0, 0, 256, 256);
}
} }
if (Core::Input().IsKeyPressed(KeyCode::Q)) if (Core::Input().IsKeyPressed(KeyCode::Q))
@ -331,9 +354,13 @@ namespace lunarium
void SimpleRenderScene::RenderStringTest(Renderer2D& g) void SimpleRenderScene::RenderStringTest(Renderer2D& g)
{ {
Texture* dt = g.GetTextDebugTexture(); Texture* dt = g.GetTextDebugTexture();
g.DrawQuad(Rectangle(mTextDebugPosX, 400, dt->GetWidth() , dt->GetHeight() ), Color::Blue(), dt); g.DrawQuad(Rectangle(mTextDebugPosX, 300, dt->GetWidth() , dt->GetHeight() ), Color::Blue(), dt);
g.DrawQuad(Rectangle(200, 100, 32, 32), Color(0.25f, 0.75f, 0.6f, 1.0f), mpTestImageLoad3, 0.0f, mSubTex);
g.DrawString("A", Rectangle(200, 170, 32, 32), Color(0.25f, 0.75f, 0.6f, 1.0f));
//g.DrawString("This is a test string!", Rectangle(100, 400, 200, 50), Color::Green()); g.DrawString("This is a test string!", Rectangle::MakeFromTopLeft(100, 500, 500, 50), Color::Green());
g.DrawString("This is a very long string that should end up on more than one line when printed out test string!", Rectangle::MakeFromTopLeft(300, 50, 400, 500), Color::Red());
} }

@ -43,6 +43,7 @@ namespace lunarium
Texture* mpRenderedImage; Texture* mpRenderedImage;
Texture* mpTestImageLoad; Texture* mpTestImageLoad;
Texture* mpTestImageLoad2; Texture* mpTestImageLoad2;
Texture* mpTestImageLoad3;
FrameBuffer* mFrameBufferOne; FrameBuffer* mFrameBufferOne;
FrameBuffer* mFrameBufferTwo; FrameBuffer* mFrameBufferTwo;
float angle; float angle;
@ -60,12 +61,14 @@ namespace lunarium
TestMode mTestMode; TestMode mTestMode;
// STRESS TEST MODE
int mNumQuadsToRender = 500; int mNumQuadsToRender = 500;
bool mUseTextures = false; bool mUseTextures = false;
const int NUM_QUADS = 50000; const int NUM_QUADS = 50000;
Color* mQuadColors; Color* mQuadColors;
Rectangle* mQuads; Rectangle* mQuads;
Texture** mQuadTexures; Texture** mQuadTexures;
//
struct GridTestObj struct GridTestObj
{ {

Loading…
Cancel
Save