From 342403a02f8063903d0f38327430721d4d0ae331 Mon Sep 17 00:00:00 2001 From: Matt Strapp Date: Mon, 20 Sep 2021 18:15:14 -0500 Subject: do ass1 --- dev/MinGfx/src/text_shader.cc | 474 +++++++++++++++++++++--------------------- 1 file changed, 237 insertions(+), 237 deletions(-) (limited to 'dev/MinGfx/src/text_shader.cc') diff --git a/dev/MinGfx/src/text_shader.cc b/dev/MinGfx/src/text_shader.cc index ca99953..60d6e1b 100644 --- a/dev/MinGfx/src/text_shader.cc +++ b/dev/MinGfx/src/text_shader.cc @@ -1,238 +1,238 @@ -/* - Copyright (c) 2017,2018 Regents of the University of Minnesota. - All Rights Reserved. - See corresponding header file for details. - */ - -#include "text_shader.h" - -#include "platform.h" -#include - -// disable warnings for this 3rd party code -#pragma warning (push, 0) -#define STB_RECT_PACK_IMPLEMENTATION -#include "stb_rect_pack.h" -#define STB_TRUETYPE_IMPLEMENTATION -#include -#pragma warning (pop) - - -namespace mingfx { - -// Reference implementation: https://github.com/nothings/stb/blob/master/tests/oversample/main.c - - -TextShader::TextShader() : native_font_size_(0.0) -{ - for (int i = 0; i < 128; i++) { - chardata_[i] = stbtt_packedchar(); - } -} - -TextShader::~TextShader() { -} - - -bool TextShader::Init(const std::string &filename, int font_size) { - // load shader - shader_.AddVertexShaderFromFile(Platform::FindMinGfxShaderFile("text.vert")); - shader_.AddFragmentShaderFromFile(Platform::FindMinGfxShaderFile("text.frag")); - shader_.LinkProgram(); - - // load font - native_font_size_ = (float)font_size; - std::ifstream is(filename.c_str(), std::ifstream::binary); - if (is) { - is.seekg(0, is.end); - int length = (int)is.tellg(); - is.seekg(0, is.beg); - - char *ttf_buffer = new char[length]; - is.read(ttf_buffer, length); - if (is) - std::cout << "all characters read successfully."; - else - std::cout << "error: only " << is.gcount() << " could be read"; - is.close(); - - // todo: calc an appropriate pow of 2 size given the font_size - int atlas_width = 1024; - int atlas_height = 1024; - - stbtt_pack_context pc; - unsigned char *bitmap = new unsigned char[(size_t)atlas_width * atlas_height]; - - stbtt_PackBegin(&pc, bitmap, atlas_width, atlas_height, 0, 1, NULL); - stbtt_PackSetOversampling(&pc, 2, 2); - stbtt_PackFontRange(&pc, (unsigned char*)ttf_buffer, 0, (float)font_size, 32, 95, chardata_+32); - stbtt_PackEnd(&pc); - - // convert to 4-channel since that is all that Texture2D currently supports - unsigned char *bitmap4D = new unsigned char[(size_t)4 * atlas_width * atlas_height]; - for (int i=0; i < atlas_width * atlas_height; i++) { - bitmap4D[4*i + 0] = bitmap[i]; - bitmap4D[4*i + 1] = bitmap[i]; - bitmap4D[4*i + 2] = bitmap[i]; - bitmap4D[4*i + 3] = bitmap[i]; - } - - atlas_.InitFromBytes(atlas_width, atlas_height, bitmap4D); - - delete [] ttf_buffer; - delete [] bitmap; - delete [] bitmap4D; - - return true; - } - else { - std::cerr << "TextShader: Error font file does not exist: " << filename << std::endl; - return false; - } - -} - - -void TextShader::Draw3D(const Matrix4 &model, const Matrix4 &view, const Matrix4 &projection, - const std::string &text, TextFormat format, bool cache) -{ - MeshData *md = NULL; - std::map::iterator it = cache_.find(text); - if (it != cache_.end()) { - // use an existing cached mesh - md = &(it->second); - } - else { - // need to create a new mesh, add a new one to the cache or use the tmp_mesh - if (cache) { - MeshData new_md; - cache_[text] = new_md; - md = &(cache_[text]); - } - else { - md = &tmp_md_; - } - - // set appropriate vertices and texcoords for this text string - SetTextMesh(text, md); - } - - Vector3 offset; - if (format.h_align == HorizAlign::HORIZ_ALIGN_LEFT) { - offset[0] = 0; - } - else if (format.h_align == HorizAlign::HORIZ_ALIGN_CENTER) { - offset[0] = -0.5f * (md->max[0] - md->min[0]); - } - else if (format.h_align == HorizAlign::HORIZ_ALIGN_RIGHT) { - offset[0] = -(md->max[0] - md->min[0]); - } - - if (format.v_align == VertAlign::VERT_ALIGN_TOP) { - offset[1] = -md->max[1]; - } - else if (format.v_align == VertAlign::VERT_ALIGN_CENTER) { - offset[1] = -0.5f * md->max[1]; - } - else if (format.v_align == VertAlign::VERT_ALIGN_BASELINE) { - offset[1] = 0; - } - else if (format.v_align == VertAlign::VERT_ALIGN_BOTTOM) { - offset[1] = -md->min[1]; - } - - glDisable(GL_CULL_FACE); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - shader_.UseProgram(); - Matrix4 mvp = projection * view * model; - shader_.SetUniform("mvp_matrix", mvp); - shader_.SetUniform("scale", format.size / native_font_size_); - shader_.SetUniform("offset", offset); - shader_.SetUniform("color", format.color); - shader_.BindTexture("font_atlas", atlas_); - md->mesh.Draw(); - shader_.StopProgram(); - - glEnable(GL_CULL_FACE); -} - - -void TextShader::SetTextMesh(const std::string &text, MeshData *md) { - std::vector verts; - std::vector uvs; - std::vector indices; - - const char *c = text.c_str(); - float x = 0.0; - float y = 0.0; - while (*c) { - stbtt_aligned_quad q; - stbtt_GetPackedQuad(chardata_, atlas_.width(), atlas_.height(), *c++, &x, &y, &q, 0); - - // top left - verts.push_back(Point3(q.x0, -q.y0, 0.0)); - uvs.push_back(Point2(q.s0, q.t0)); - // top right - verts.push_back(Point3(q.x1, -q.y0, 0.0)); - uvs.push_back(Point2(q.s1, q.t0)); - // bot right - verts.push_back(Point3(q.x1, -q.y1, 0.0)); - uvs.push_back(Point2(q.s1, q.t1)); - // bot left - verts.push_back(Point3(q.x0, -q.y1, 0.0)); - uvs.push_back(Point2(q.s0, q.t1)); - - - indices.push_back((unsigned int)verts.size()-2); - indices.push_back((unsigned int)verts.size()-3); - indices.push_back((unsigned int)verts.size()-4); - - indices.push_back((unsigned int)verts.size()-2); - indices.push_back((unsigned int)verts.size()-4); - indices.push_back((unsigned int)verts.size()-1); - } - - md->mesh.SetVertices(verts); - md->mesh.SetTexCoords(0, uvs); - md->mesh.SetIndices(indices); - - md->min = Point2(verts[0][0], verts[0][1]); - md->max = md->min; - for (int i=0; imin[0]) md->min[0] = p[0]; - if (p[0] > md->max[0]) md->max[0] = p[0]; - if (p[1] < md->min[1]) md->min[1] = p[1]; - if (p[1] > md->max[1]) md->max[1] = p[1]; - } -} - -Vector2 TextShader::TextExtents(const std::string &text, TextFormat format, bool cache) { - MeshData *md = NULL; - std::map::iterator it = cache_.find(text); - if (it != cache_.end()) { - // use an existing cached mesh - md = &(it->second); - } - else { - // need to create a new mesh, add a new one to the cache or use the tmp_mesh - if (cache) { - MeshData new_md; - cache_[text] = new_md; - md = &(cache_[text]); - } - else { - md = &tmp_md_; - } - - // set appropriate vertices and texcoords for this text string - SetTextMesh(text, md); - } - - return format.size / native_font_size_ * (md->max - md->min); -} - - +/* + Copyright (c) 2017,2018 Regents of the University of Minnesota. + All Rights Reserved. + See corresponding header file for details. + */ + +#include "text_shader.h" + +#include "platform.h" +#include + +// disable warnings for this 3rd party code +#pragma warning (push, 0) +#define STB_RECT_PACK_IMPLEMENTATION +#include "stb_rect_pack.h" +#define STB_TRUETYPE_IMPLEMENTATION +#include +#pragma warning (pop) + + +namespace mingfx { + +// Reference implementation: https://github.com/nothings/stb/blob/master/tests/oversample/main.c + + +TextShader::TextShader() : native_font_size_(0.0) +{ + for (int i = 0; i < 128; i++) { + chardata_[i] = stbtt_packedchar(); + } +} + +TextShader::~TextShader() { +} + + +bool TextShader::Init(const std::string &filename, int font_size) { + // load shader + shader_.AddVertexShaderFromFile(Platform::FindMinGfxShaderFile("text.vert")); + shader_.AddFragmentShaderFromFile(Platform::FindMinGfxShaderFile("text.frag")); + shader_.LinkProgram(); + + // load font + native_font_size_ = (float)font_size; + std::ifstream is(filename.c_str(), std::ifstream::binary); + if (is) { + is.seekg(0, is.end); + int length = (int)is.tellg(); + is.seekg(0, is.beg); + + char *ttf_buffer = new char[length]; + is.read(ttf_buffer, length); + if (is) + std::cout << "all characters read successfully."; + else + std::cout << "error: only " << is.gcount() << " could be read"; + is.close(); + + // todo: calc an appropriate pow of 2 size given the font_size + int atlas_width = 1024; + int atlas_height = 1024; + + stbtt_pack_context pc; + unsigned char *bitmap = new unsigned char[(size_t)atlas_width * atlas_height]; + + stbtt_PackBegin(&pc, bitmap, atlas_width, atlas_height, 0, 1, NULL); + stbtt_PackSetOversampling(&pc, 2, 2); + stbtt_PackFontRange(&pc, (unsigned char*)ttf_buffer, 0, (float)font_size, 32, 95, chardata_+32); + stbtt_PackEnd(&pc); + + // convert to 4-channel since that is all that Texture2D currently supports + unsigned char *bitmap4D = new unsigned char[(size_t)4 * atlas_width * atlas_height]; + for (int i=0; i < atlas_width * atlas_height; i++) { + bitmap4D[4*i + 0] = bitmap[i]; + bitmap4D[4*i + 1] = bitmap[i]; + bitmap4D[4*i + 2] = bitmap[i]; + bitmap4D[4*i + 3] = bitmap[i]; + } + + atlas_.InitFromBytes(atlas_width, atlas_height, bitmap4D); + + delete [] ttf_buffer; + delete [] bitmap; + delete [] bitmap4D; + + return true; + } + else { + std::cerr << "TextShader: Error font file does not exist: " << filename << std::endl; + return false; + } + +} + + +void TextShader::Draw3D(const Matrix4 &model, const Matrix4 &view, const Matrix4 &projection, + const std::string &text, TextFormat format, bool cache) +{ + MeshData *md = NULL; + std::map::iterator it = cache_.find(text); + if (it != cache_.end()) { + // use an existing cached mesh + md = &(it->second); + } + else { + // need to create a new mesh, add a new one to the cache or use the tmp_mesh + if (cache) { + MeshData new_md; + cache_[text] = new_md; + md = &(cache_[text]); + } + else { + md = &tmp_md_; + } + + // set appropriate vertices and texcoords for this text string + SetTextMesh(text, md); + } + + Vector3 offset; + if (format.h_align == HorizAlign::HORIZ_ALIGN_LEFT) { + offset[0] = 0; + } + else if (format.h_align == HorizAlign::HORIZ_ALIGN_CENTER) { + offset[0] = -0.5f * (md->max[0] - md->min[0]); + } + else if (format.h_align == HorizAlign::HORIZ_ALIGN_RIGHT) { + offset[0] = -(md->max[0] - md->min[0]); + } + + if (format.v_align == VertAlign::VERT_ALIGN_TOP) { + offset[1] = -md->max[1]; + } + else if (format.v_align == VertAlign::VERT_ALIGN_CENTER) { + offset[1] = -0.5f * md->max[1]; + } + else if (format.v_align == VertAlign::VERT_ALIGN_BASELINE) { + offset[1] = 0; + } + else if (format.v_align == VertAlign::VERT_ALIGN_BOTTOM) { + offset[1] = -md->min[1]; + } + + glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + shader_.UseProgram(); + Matrix4 mvp = projection * view * model; + shader_.SetUniform("mvp_matrix", mvp); + shader_.SetUniform("scale", format.size / native_font_size_); + shader_.SetUniform("offset", offset); + shader_.SetUniform("color", format.color); + shader_.BindTexture("font_atlas", atlas_); + md->mesh.Draw(); + shader_.StopProgram(); + + glEnable(GL_CULL_FACE); +} + + +void TextShader::SetTextMesh(const std::string &text, MeshData *md) { + std::vector verts; + std::vector uvs; + std::vector indices; + + const char *c = text.c_str(); + float x = 0.0; + float y = 0.0; + while (*c) { + stbtt_aligned_quad q; + stbtt_GetPackedQuad(chardata_, atlas_.width(), atlas_.height(), *c++, &x, &y, &q, 0); + + // top left + verts.push_back(Point3(q.x0, -q.y0, 0.0)); + uvs.push_back(Point2(q.s0, q.t0)); + // top right + verts.push_back(Point3(q.x1, -q.y0, 0.0)); + uvs.push_back(Point2(q.s1, q.t0)); + // bot right + verts.push_back(Point3(q.x1, -q.y1, 0.0)); + uvs.push_back(Point2(q.s1, q.t1)); + // bot left + verts.push_back(Point3(q.x0, -q.y1, 0.0)); + uvs.push_back(Point2(q.s0, q.t1)); + + + indices.push_back((unsigned int)verts.size()-2); + indices.push_back((unsigned int)verts.size()-3); + indices.push_back((unsigned int)verts.size()-4); + + indices.push_back((unsigned int)verts.size()-2); + indices.push_back((unsigned int)verts.size()-4); + indices.push_back((unsigned int)verts.size()-1); + } + + md->mesh.SetVertices(verts); + md->mesh.SetTexCoords(0, uvs); + md->mesh.SetIndices(indices); + + md->min = Point2(verts[0][0], verts[0][1]); + md->max = md->min; + for (int i=0; imin[0]) md->min[0] = p[0]; + if (p[0] > md->max[0]) md->max[0] = p[0]; + if (p[1] < md->min[1]) md->min[1] = p[1]; + if (p[1] > md->max[1]) md->max[1] = p[1]; + } +} + +Vector2 TextShader::TextExtents(const std::string &text, TextFormat format, bool cache) { + MeshData *md = NULL; + std::map::iterator it = cache_.find(text); + if (it != cache_.end()) { + // use an existing cached mesh + md = &(it->second); + } + else { + // need to create a new mesh, add a new one to the cache or use the tmp_mesh + if (cache) { + MeshData new_md; + cache_[text] = new_md; + md = &(cache_[text]); + } + else { + md = &tmp_md_; + } + + // set appropriate vertices and texcoords for this text string + SetTextMesh(text, md); + } + + return format.size / native_font_size_ * (md->max - md->min); +} + + } // end namespace \ No newline at end of file -- cgit v1.2.3