#pragma once #include #include #include #include #include #include #include #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, 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(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::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 m_text_to_index; std::unordered_map m_text_to_width; std::list m_renderables; std::list m_text_batches; }; } } }