charcoal/charcoal-builtin/TextPipeline.h

119 lines
3.0 KiB
C
Raw Normal View History

#pragma once
#include <string>
#include <unordered_map>
#include <list>
#include <glm/glm.hpp>
#include <charcoal/Font.h>
#include <charcoal/TextureFactory.h>
#include "MeshGenerator.h"
#include "GLUtil.h"
#include "BuiltinPipeline.h"
#include "WithCamera.h"
#include "TextTypes.h"
#include "TextBatch.h"
namespace charcoal
{
namespace builtin
{
namespace text
{
class Pipeline : private builtin::Pipeline<ShaderProgram, Batch>, public WithCamera
{
public:
Pipeline(
Font& font
)
: m_font(font)
{
std::string prepared_text = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`1234567890-=[]\\;',./~!@#$%^&*()_+{}|:\"<>?";
for (char c : prepared_text)
{
std::string s(1, c);
const charcoal::image_loader::ImageRGBA& image = m_font.get_text_image(s);
m_renderables.emplace_back(
meshgenerator::gen_rect_pt<Vertex, Index>(DrawMode::DRAW_TRIANGLES, (float)image.width, (float)image.height),
TextureFactory::gen_image_texture(image),
TextureFactory::gen_sampler(Sampler::Wrap::CLAMP_TO_EDGE, Sampler::Wrap::CLAMP_TO_EDGE, Sampler::MagFilter::LINEAR, Sampler::MinFilter::NEAREST),
DrawMode::DRAW_TRIANGLES
);
m_text_batches.emplace_back(&m_renderables.back());
add_batch(&m_text_batches.back());
m_text_to_index[s] = (unsigned int)(m_batches.size() - 1);
m_text_to_width[s] = image.width;
}
}
void init_text()
{
for (Batch& batch : m_text_batches)
{
batch.init();
}
}
void render()
{
builtin::Pipeline<ShaderProgram, Batch>::render();
}
void reset_text()
{
for (Batch& batch : m_text_batches)
{
batch.reset_rendered();
}
}
// Position specified as center of left most character.
// TODO: May want to change this to be specifyable by different than center
// and maybe do top/bottom/other stuff
void add_text(const vec3& position, const std::string& text)
{
// For now, always do aa per-char calculation.
// TODO for future would be to cache the commonly used words for faster word
// rendering.
vec3 p = position;
for (char c : text)
{
std::string s(1, c);
m_batches[m_text_to_index[s]]->add_rendered(charcoal::Poseable(p));
p.x += m_text_to_width[s];
}
}
void prerender_text()
{
for (Batch& batch : m_text_batches)
{
batch.prerender();
}
}
void prepare_opengl() override
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
}
void prepare_uniforms() override
{
glutil::uniform_matrix(0, get_camera()->get_world_to_view_matrix());
}
private:
Font& m_font;
std::unordered_map<std::string, unsigned int> m_text_to_index;
std::unordered_map<std::string, unsigned int> m_text_to_width;
std::list<Renderable> m_renderables;
std::list<Batch> m_text_batches;
};
}
}
}