charcoal/charcoal-builtin/TextPipeline.h
elipzer 835fb62449 Got TextPipeline working.
I think that there needs to be a re-work or re-specification of
the text pipeline works to make the functions/methods more
intuitive rather than them being prefixed with "text".
2018-11-13 14:08:26 -05:00

134 lines
3.3 KiB
C++

#pragma once
#include <string>
#include <unordered_map>
#include <list>
#include <glm/glm.hpp>
#include <charcoal/Font.h>
#include <charcoal/TextureFactory.h>
#include <charcoal/Util.h>
#include "MeshGenerator.h"
#include "GLUtil.h"
#include "BuiltinPipeline.h"
#include "WithCamera.h"
#include "TextTypes.h"
#include "TextShaderProgram.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::LINEAR),
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)
{
CHECK_GL_ERR();
batch.init();
CHECK_GL_ERR();
}
}
void render()
{
CHECK_GL_ERR();
builtin::Pipeline<ShaderProgram, Batch>::render();
CHECK_GL_ERR();
}
void reset_text()
{
for (Batch& batch : m_text_batches)
{
CHECK_GL_ERR();
batch.reset_rendered();
CHECK_GL_ERR();
}
}
// 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);
CHECK_GL_ERR();
m_batches[m_text_to_index[s]]->add_rendered(charcoal::Poseable(p));
CHECK_GL_ERR();
p.x += m_text_to_width[s];
}
}
void prerender_text()
{
for (Batch& batch : m_text_batches)
{
CHECK_GL_ERR();
batch.prerender();
CHECK_GL_ERR();
}
}
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
{
CHECK_GL_ERR();
glutil::uniform_matrix(0, get_camera()->get_world_to_view_matrix());
CHECK_GL_ERR();
}
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;
};
}
}
}