m trying to write my own font rendering system using OGL, and for it I get te texture from a sf::Font like so:
#ifndef BITMAPTEXT_HPP_INCLUDED
#define BITMAPTEXT_HPP_INCLUDED
#include <GL/glew.h>
#include <GL/gl.h>
#include <vector>
#include <SFML/Graphics.hpp>
#include "./Shader.hpp"
#include <glm/glm.hpp>
class BitmapText
{
protected:
glm::vec3 Pos;
glm::mat4 Model;
GLuint vertexbuffer;
GLuint uvbuffer;
sf::Font font;
sf::Texture bitmap;
Shader shader;
std::vector<sf::IntRect> Positions;
std::string text;
glm::vec4 Color;
GLuint TextureID;
GLuint ColorID;
GLuint MVPID;
GLuint PositionID;
GLuint UVID;
void Rebuild();
public:
///
/// \brief Empty constructor
///
BitmapText();
///
/// \brief Empty deconstructor
///
~BitmapText();
///
/// \brief Construct class from given arguments
/// \param Bitmap image
/// \param Bitmap position array
bool LoadFile(const std::string& fontFile, int siz );
///
/// \brief Set text
///
void SetText(const std::string& eText);
void SetPosition(const glm::vec2 &pos);
virtual void Update();
virtual void Draw(glm::mat4 &VP);
void SetColor(float r , float g, float b , float a);
};
#endif // BITMAPTEXT_HPP_INCLUDED
#include <glm/gtx/transform2.hpp>
#include <GL/glew.h>
#include "./BitmapText.hpp"
#include <GL/glfw.h>
#include <iostream>
#include <fstream>
#include "./Utilities.hpp"
#include <limits>
BitmapText::BitmapText()
{
std::string vertexShader =
"#version 120\n"
"uniform mat4 MVP;\n"
"attribute vec4 Position;\n"
"attribute vec2 UV;\n"
"varying vec2 uv;\n"
"void main(){\n"
"uv = UV;\n"
"gl_Position = MVP * Position;\n"
"}";
std::string fragmentShader =
"#version 120\n"
"varying vec2 uv;\n"
"uniform sampler2D Texture;\n"
"uniform vec4 Color;\n"
"void main(){\n"
"vec4 textur = texture2D( Texture, uv ).rgba;\n"
"textur.rgb = Color.rgb;\n"
"if(textur.a == 0.0f){\n"
"textur = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n"
"}\n"
"gl_FragColor = textur;\n"
"}";
shader.LoadShaderCode(vertexShader ,fragmentShader);
Color = glm::vec4(1.0f);
text = "hi";
glGenBuffers(1, &vertexbuffer);
glGenBuffers(1, &uvbuffer);
MVPID = glGetUniformLocation(shader.GetShaderID(), "MVP");
TextureID = glGetUniformLocation(shader.GetShaderID(), "Texture");
PositionID = glGetAttribLocation(shader.GetShaderID(), "Position");
UVID = glGetAttribLocation(shader.GetShaderID(), "UV");
ColorID = glGetUniformLocation(shader.GetShaderID(), "Color");
//Rebuild();
}
BitmapText::~BitmapText()
{
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &uvbuffer);
}
bool BitmapText::LoadFile(const std::string& fontFile, int siz)
{
font.loadFromFile(fontFile);
for(unsigned char c = 0; c < std::numeric_limits<unsigned char>::max(); c++)
{
sf::Glyph g = font.getGlyph(c, siz, false);
Positions.push_back(g.textureRect);
}
bitmap = font.getTexture( siz );
bitmap.bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
Rebuild();
return true;
}
void BitmapText::SetText(const std::string& eText)
{
text = eText;
Rebuild();
}
void BitmapText::SetPosition(const glm::vec2& pos)
{
Pos = glm::vec3(pos.x, pos.y, 0.1f);
Rebuild();
}
void BitmapText::Update()
{
}
void BitmapText::Draw(glm::mat4 &VP)
{
//glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
glm::mat4 MVP = VP * Model;
shader.Bind();
glUniformMatrix4fv(MVPID, 1, GL_FALSE, &MVP[0][0]);
glActiveTexture(GL_TEXTURE0);
bitmap.bind();
glUniform1i(TextureID, 0);
glUniform4fv(ColorID,1 , &Color[0]);
glEnableVertexAttribArray(PositionID);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
PositionID, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glEnableVertexAttribArray(UVID);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(
UVID, // attribute 0. No particular reason for 0, but must match the layout in the shader.
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_TRIANGLES, 0, text.size() * 6);
glDisableVertexAttribArray(UVID);
glDisableVertexAttribArray(PositionID);
glBindTexture(GL_TEXTURE_2D, 0);
Shader::Unbind();
//if(asLines)
// glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
//else
// glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
}
void BitmapText::Rebuild()
{
std::vector<GLfloat> VertexList;
std::vector<GLfloat> UVList;
float disp = 0.0f;
float largestHeight = 0.0f;
for(int i = 0; i < text.size(); i++)
{
sf::IntRect charRect = Positions[text.c_str()[i]];
if(largestHeight < charRect.height) largestHeight = charRect.height;
VertexList.push_back(0.0f + disp);
VertexList.push_back(0.0f);
VertexList.push_back(0.0f);
VertexList.push_back(0.0f + disp);
VertexList.push_back(charRect.height);
VertexList.push_back(0.0f);
VertexList.push_back(charRect.width + disp);
VertexList.push_back(0.0f);
VertexList.push_back(0.0f);
VertexList.push_back(charRect.width + disp);
VertexList.push_back(0.0f);
VertexList.push_back(0.0f);
VertexList.push_back(0.0f + disp);
VertexList.push_back(charRect.height);
VertexList.push_back(0.0f);
VertexList.push_back(charRect.width + disp);
VertexList.push_back(charRect.height);
VertexList.push_back(0.0f);
UVList.push_back(charRect.left / bitmap.getSize().x);
UVList.push_back(charRect.top / bitmap.getSize().y);
UVList.push_back(charRect.left / bitmap.getSize().x);
UVList.push_back((charRect.top + charRect.height) / bitmap.getSize().y);
UVList.push_back((charRect.left + charRect.width ) / bitmap.getSize().x);
UVList.push_back(charRect.top / bitmap.getSize().y);
UVList.push_back((charRect.left + charRect.width ) / bitmap.getSize().x);
UVList.push_back(charRect.top / bitmap.getSize().y);
UVList.push_back(charRect.left / bitmap.getSize().x);
UVList.push_back((charRect.top + charRect.height) / bitmap.getSize().y);
UVList.push_back((charRect.left + charRect.width ) / bitmap.getSize().x);
UVList.push_back((charRect.top + charRect.height) / bitmap.getSize().y);
disp += charRect.width;
}
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, VertexList.size() * sizeof(GLfloat), &VertexList[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, UVList.size() * sizeof(GLfloat), &UVList[0], GL_STATIC_DRAW);
Model = glm::translate(glm::mat4(1.0f),Pos.x , Pos.y, 0.0f);
//MVP = * Model;
}
void BitmapText::SetColor(float r , float g, float b , float a)
{
Color.x = r;
Color.y = g;
Color.z = b;
Color.w = a;
}
The code to get the glyphs is:
bool BitmapText::LoadFile(const std::string& fontFile, int siz)
{
font.loadFromFile(fontFile);
for(unsigned char c = 0; c < std::numeric_limits<unsigned char>::max(); c++)
{
sf::Glyph g = font.getGlyph(c, siz, false);
Positions.push_back(g.textureRect);
}
bitmap = font.getTexture( siz );
bitmap.bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
Rebuild();
return true;
}
Is this the correct way to do it?