struct Character {
GLuint TextureID;
Vector2 Size;
Vector2 Bearing;
GLuint Advance; //Offset to advance to next glyph
};
//Init character
TTF_Init();
font = TTF_OpenFont("../../Assets/consola.ttf", 24);
SDL_Color color = { 255, 0, 0 };
SDL_Surface *face = NULL;
//14 is a magic number...
for (GLubyte c = 14; c < 128; c++)
{
char tmpChar = /*'a' +*/ c;
string tmp(1,tmpChar);
face = TTF_RenderText_Blended(font, tmp.c_str(), color);
int mode;
if (face->format->BytesPerPixel == 3) { // RGB 24bit
mode = GL_RGB;
}
else if (face->format->BytesPerPixel == 4) { // RGBA 32bit
mode = GL_RGBA;
}
else {
SDL_FreeSurface(face);
return false;
}
GLuint texture = 0;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, mode, face->w, face->h, 0, mode, GL_UNSIGNED_BYTE, face->pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int minx, maxx, miny, maxy, advance;
if (TTF_GlyphMetrics(font, *(tmp.c_str()), &minx, &maxx, &miny, &maxy, &advance) == -1)
{
printf("%s\n", TTF_GetError());
}
Character character = {
texture,
Vector2(face->w, face->h),
Vector2(minx, maxy),
advance
};
Characters.insert(std::pair(tmpChar, character));
}
characterShader = new ShaderProgram("../../Assets/shader/character.vert", "../../Assets/shader/character.frag");
Matrix4x4 projection = Transform::OrthoFrustum(0.0f, static_cast(creationFlags.width), 0.0f, static_cast(creationFlags.height), -1000, 1000);
characterShader->Use();
glUniformMatrix4fv(glGetUniformLocation(characterShader->GetProgramID(), "projection"), 1, GL_FALSE, &projection[0]);
// Configure VAO/VBO for texture quads
glGenVertexArrays(1, &characterVAO);
glGenBuffers(1, &characterVBO);
glBindVertexArray(characterVAO);
glBindBuffer(GL_ARRAY_BUFFER, characterVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return true;
Matrix4x4 projection = Transform::OrthoFrustum(0.0f, static_cast(creationFlags.width), 0.0f, static_cast(creationFlags.height), -1000, 1000);
characterShader->Use();
glUniformMatrix4fv(glGetUniformLocation(characterShader->GetProgramID(), "projection"), 1, GL_FALSE, &projection[0]);
#version 330 core
layout (location = 0) in vec4 vertex; //
out vec2 TexCoords;
uniform mat4 projection;
void main()
{
gl_Position = projection * vec4(vertex.xy, 0, 1.0);
TexCoords = vertex.zw;
}
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D text;
uniform vec3 textColor;
void main()
{
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).a);
color = vec4(textColor, 1.0) * sampled;
}
void Renderer::RenderText(std::string text, GLfloat x, GLfloat y, GLfloat scale, Color color)
{
characterShader->Use();
glUniform3f(glGetUniformLocation(characterShader->GetProgramID(), "textColor"), color.r, color.g, color.b);
//glUniform3f(glGetUniformLocation(s.Program, "textColor"), color.r, color.g, color.b);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(characterVAO);
std::string::const_iterator c;
for (c = text.begin(); c != text.end(); c++)
{
Character ch = Characters[*c];
GLfloat xpos = x + ch.Bearing.x * scale;
//GLfloat ypos = y - (ch.Size.y - ch.Bearing.y) * scale;
GLfloat ypos = y;
GLfloat w = ch.Size.x * scale;
GLfloat h = ch.Size.y * scale;
// VBO
GLfloat vertices[6][4] = {
{ xpos, ypos, 0.0, 1.0 },
{ xpos, ypos + h, 0.0, 0.0 },
{ xpos + w, ypos + h, 1.0, 0.0 },
{ xpos, ypos, 0.0, 1.0 },
{ xpos + w, ypos + h, 1.0, 0.0 },
{ xpos + w, ypos, 1.0, 1.0 }
};
// Render glyph texture over quad
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
// Update content of VBO memory
glBindBuffer(GL_ARRAY_BUFFER, characterVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Render quad
glDrawArrays(GL_TRIANGLES, 0, 6);
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
x += ch.Advance * scale;
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
}
RenderText(fps.str(), - 0.5f * parent->GetWindowWidth(), 0.5f * parent->GetWindowHeight() - 100, 1, Color(1, 1, 1, 1));
Learnopengl_文字渲染
SDLTutorial Series - Part 6 - Displaying Text with SDL_ttf
TTF_GlyphMetrics