diff --git a/src/LayerComposition.cpp b/src/LayerComposition.cpp index cb4af93..9e19007 100644 --- a/src/LayerComposition.cpp +++ b/src/LayerComposition.cpp @@ -184,7 +184,7 @@ void LayerComposition::draw(int width, int height) const { for(const auto & [identifier, layerCombo] : atlasLayerCombos){ if(identifier.type == LayerType::MSDFGEN){ auto combo = static_pointer_cast (layerCombo); - //combo->draw(); + combo->draw(); } } for(unsigned int i = layerOrder.size(); i-- > 0;){ @@ -219,7 +219,7 @@ void LayerComposition::drawCamera(const ofCamera & camera) const { for(const auto & [identifier, layerCombo] : atlasLayerCombos){ if(identifier.type == LayerType::MSDFGEN){ auto combo = static_pointer_cast (layerCombo); - combo->draw(camera); + //combo->draw(camera); } } } diff --git a/src/MsdfAtlasLayerCombo.cpp b/src/MsdfAtlasLayerCombo.cpp index d51bfa1..c7619b5 100644 --- a/src/MsdfAtlasLayerCombo.cpp +++ b/src/MsdfAtlasLayerCombo.cpp @@ -2,7 +2,9 @@ #include "AtlasLayerCombo.h" #include "MsdfLayer.h" #include "Utils.h" +#include "of3dGraphics.h" #include "ofFileUtils.h" +#include "ofGraphics.h" #include #include @@ -24,16 +26,37 @@ void MsdfAtlasLayerCombo::setup(const ComboIdentifier & layerIdentifier, msdfShader = make_shared (); #ifdef TARGET_EMSCRIPTEN - if(ofFile("shaders/ES3/msdf/shader.frag").exists()){ - msdfShader->load("shaders/ES3/msdf/shader"); - }else{ - msdfShader->load("ofxMsdfgen/shaders/mix/ES3/shader"); - } + //if(ofFile("shaders/ES3/msdf/shader.frag").exists()){ + //msdfShader->load("shaders/ES3/msdf/shader"); + //}else{ + msdfShader->load("ofxMsdfgen/shaders/mix/ES3/shader"); + //} #else msdfShader->load("ofxMsdfgen/shaders/mix/GL3/shader"); #endif atlas->setup(this->identifier.fontPath, atlasSettings); + + glGenVertexArrays(1, &vao); + + glGenBuffers(1, &vbo); + glGenBuffers(1, &ebo); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, false, sizeof(BufferVertex), (void *)offsetof(BufferVertex, position)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(BufferVertex), (void *)offsetof(BufferVertex, uv_a)); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, false, sizeof(BufferVertex), (void *)offsetof(BufferVertex, uv_b)); + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 4, GL_FLOAT, false, sizeof(BufferVertex), (void *)offsetof(BufferVertex, color)); + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 1, GL_FLOAT, false, sizeof(BufferVertex), (void *)offsetof(BufferVertex, mix)); + glBindVertexArray(0); + } void MsdfAtlasLayerCombo::update(){ @@ -43,9 +66,9 @@ void MsdfAtlasLayerCombo::update(){ atlas->generate(useCache, saveToCache); isDirty = false; } - if(!uboIsSetup){ - setupUbo(); - } + //if(!uboIsSetup){ + //setupUbo(); + //} } void MsdfAtlasLayerCombo::setupUbo(){ @@ -115,13 +138,77 @@ bool MsdfAtlasLayerCombo::hasChildren(){ } // unique -void MsdfAtlasLayerCombo::draw(const ofCamera & camera){ - vertices.clear(); - parameters.clear(); +void MsdfAtlasLayerCombo::draw(){ + int elements = 0; for(const auto & layer : layers){ - vertices.insert(vertices.end(), layer->vertices.begin(), layer->vertices.end()); - parameters.insert(parameters.end(), layer->parameters.begin(), layer->parameters.end()); + elements += layer->nElements; } + //vertices.resize(elements * 4); + //indices.resize(elements * 6); + vertices.clear(); + indices.clear(); + int offset = 0; + glm::vec4 bgColor; + for(const auto & layer : layers){ + //vertices.insert(vertices.begin() + (offset * 4), layer->vertices.begin(), layer->vertices.end()); + //indices.insert(indices.begin() + (offset * 6), layer->indices.begin(), layer->indices.end()); + vertices.insert(vertices.end(), layer->vertices.begin(), layer->vertices.end()); + indices.insert(indices.end(), layer->indices.begin(), layer->indices.end()); + offset += layer->nElements; + layer->vertices.clear(); + layer->indices.clear(); + layer->nElements = 0; + bgColor = layer->uboParameters.bgColor; + } + float pixelRange = 2; + int atlas_w = getAtlasImage().getWidth(); + int atlas_h = getAtlasImage().getHeight(); + glm::vec2 unitRange = glm::vec2(pixelRange) / glm::vec2(atlas_w, atlas_h); + + //ofPushStyle(); + //vector colors{ + //ofColor::yellow, + //ofColor::green, + //ofColor::blue, + //ofColor::red + //}; + //int i = 0; + //for(BufferVertex & vertex : vertices){ + //const auto & color = colors[int(i * 0.25) % colors.size()]; + //ofSetColor(color); + //vertex.color[0] = color.r; + //vertex.color[1] = color.g; + //vertex.color[2] = color.b; + //vertex.color[3] = 1; + //ofDrawSphere(vertex.position[0], vertex.position[1], vertex.position[2], 2); + //i++; + //} + //ofPopStyle(); + + msdfShader->begin(); + msdfShader->setUniform2f("unitRange", unitRange); + msdfShader->setUniform4f("bgColor", bgColor); + msdfShader->setUniformTexture("msdf", getAtlasImage().getTexture(), 0); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(BufferVertex) * vertices.size(), vertices.data(), GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int32_t) * indices.size(), indices.data(), GL_DYNAMIC_DRAW); + + glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); + + glBindVertexArray(0); + msdfShader->end(); + +} + +void MsdfAtlasLayerCombo::exit(){ + glDeleteVertexArrays(1, &vao); + + glDeleteBuffers(1, &vbo); + glDeleteBuffers(1, &ebo); } const ofImage & MsdfAtlasLayerCombo::getAtlasImage(){ diff --git a/src/MsdfAtlasLayerCombo.h b/src/MsdfAtlasLayerCombo.h index 11afd8b..a25c0c7 100644 --- a/src/MsdfAtlasLayerCombo.h +++ b/src/MsdfAtlasLayerCombo.h @@ -5,6 +5,7 @@ #include "Utils.h" namespace ofxVariableLab { +using BufferVertex = MsdfLayer::BufferVertex; struct MsdfAtlasLayerComboSettings : public AtlasLayerComboSettings { float scale = 64; float minimumScale = 64; @@ -20,7 +21,8 @@ class MsdfAtlasLayerCombo : public AtlasLayerCombo { const ComboIdentifier & getIdentifier() const override; void setVFlip(VFlipState vFlipState) override; bool hasChildren() override; - void draw(const ofCamera & camera); + void draw(); + void exit(); const ofImage & getAtlasImage(); string getAtlasImagePath(); shared_ptr getLayer(); // TODO: is this used @@ -40,7 +42,11 @@ class MsdfAtlasLayerCombo : public AtlasLayerCombo { GLint uboIndex; void setupUbo(); bool uboIsSetup = false; - std::vector vertices; - std::vector parameters; + std::vector vertices; + std::vector indices; + + GLuint vbo; + GLuint ebo; + GLuint vao; }; } diff --git a/src/MsdfLayer.cpp b/src/MsdfLayer.cpp index 369c6f8..54b09e6 100644 --- a/src/MsdfLayer.cpp +++ b/src/MsdfLayer.cpp @@ -314,15 +314,15 @@ void MsdfLayer::setBoundingBox(const Layer::BoundingBox & boundingBox){ } void MsdfLayer::collectCharacter(const char character, const ofNode & node, + const ofCamera & camera, glm::vec4 color, ofxVariableLab::FontVariation fontVariation){ + const ofImage & atlasImage = atlas->getAtlasImage(); ofNode n = node; n.setScale(n.getScale() * scaleFactor); - float pixelRange = 2; int atlas_w = atlasImage.getWidth(); int atlas_h = atlasImage.getHeight(); - glm::vec2 unitRange = glm::vec2(pixelRange) / glm::vec2(atlas_w, atlas_h); float mix = -1; ofxMsdfgen::GlyphGeometry gg_a; @@ -354,18 +354,12 @@ void MsdfLayer::collectCharacter(const char character, gg_a.getQuadPlaneBounds(pl_a, pb_a, pr_a, pt_a); gg_b.getQuadPlaneBounds(pl_b, pb_b, pr_b, pt_b); - double advance_a = gg_a.getAdvance(); - double advance_b = gg_b.getAdvance(); - float w = glm::mix(float(w_a), float(w_b), mix); float h = glm::mix(float(h_a), float(h_b), mix); float pl = glm::mix(float(pl_a), float(pl_b), mix); float pt = glm::mix(float(pt_a), float(pt_b), mix); - double advance = glm::mix(advance_a, advance_b, mix); - ofPushMatrix(); float magic = atlas->settings.scale; - ofSetColor(ofFloatColor(1, 1, 1, 1)); getVFlip(settings.vFlipBehaviour, ofGetCurrentOrientationMatrix(), vFlip); @@ -384,49 +378,57 @@ void MsdfLayer::collectCharacter(const char character, glm::vec2 scale_b = glm::vec2(float(w_b) / float(atlas_w), float(h_b) / float(atlas_h)); - BufferVertex v[4]; glm::vec4 p0 = n.getGlobalTransformMatrix() * glm::vec4(0, 0, 0, 1); glm::vec4 p1 = n.getGlobalTransformMatrix() * glm::vec4(w, 0, 0, 1); glm::vec4 p2 = n.getGlobalTransformMatrix() * glm::vec4(w, h, 0, 1); glm::vec4 p3 = n.getGlobalTransformMatrix() * glm::vec4(0, h, 0, 1); - glm::vec2 uv0_a = glm::vec2(); - glm::vec2 uv0_b = glm::vec2(); - glm::vec2 uv1_a = glm::vec2(); - glm::vec2 uv1_b = glm::vec2(); - glm::vec2 uv2_a = glm::vec2(); - glm::vec2 uv2_b = glm::vec2(); - glm::vec2 uv3_a = glm::vec2(); - glm::vec2 uv3_b = glm::vec2(); - vertices.push_back(BufferVertex{ - {p0.x, p0.y, p0.z, p0.w}, - {uv0_a.x, uv0_a.y}, - {uv0_b.x, uv0_b.y} - }); - vertices.push_back(BufferVertex{ - {p1.x, p1.y, p1.z, p1.w}, - {uv1_a.x, uv1_a.y}, - {uv1_b.x, uv1_b.y} - }); - vertices.push_back(BufferVertex{ - {p2.x, p2.y, p2.z, p2.w}, - {uv2_a.x, uv2_a.y}, - {uv2_b.x, uv2_b.y} - }); - vertices.push_back(BufferVertex{ - {p3.x, p3.y, p3.z, p3.w}, - {uv3_a.x, uv3_a.y}, - {uv3_b.x, uv3_b.y} - }); - CharacterDrawParameters characterDrawParameters; - characterDrawParameters.unitRange = unitRange; - characterDrawParameters.fontColor = color; - characterDrawParameters.bgColor = uboParameters.bgColor; - characterDrawParameters.translation_a = translation_a; - characterDrawParameters.translation_b = translation_b; - characterDrawParameters.scale_a = scale_a; - characterDrawParameters.scale_b = scale_b; - characterDrawParameters.mix = mix; - parameters.push_back(characterDrawParameters); + if(isInside(camera, p0) + || isInside(camera, p1) + || isInside(camera, p2) + || isInside(camera, p3)){ + glm::vec3 screenPosition = camera.worldToScreen(p0); + glm::vec3 cameraPosition = camera.worldToCamera(p0); + + glm::vec2 uv0_a = translation_a; + glm::vec2 uv0_b = translation_b; + glm::vec2 uv1_a = glm::vec2(0, scale_a.y) + translation_a; + glm::vec2 uv1_b = glm::vec2(0, scale_b.y) + translation_b; + glm::vec2 uv2_a = scale_a + translation_a; + glm::vec2 uv2_b = scale_a + translation_a; + glm::vec2 uv3_a = glm::vec2(scale_a.x, 0) + translation_a; + glm::vec2 uv3_b = glm::vec2(scale_b.x, 0) + translation_b; + int32_t base = static_cast (vertices.size()); + vertices.push_back(BufferVertex{ + {p0.x, p0.y, p0.z, p0.w}, + {uv0_a.x, uv0_a.y}, + {uv0_b.x, uv0_b.y}, + {color.r, color.g, color.b, color.a}, + mix + }); + vertices.push_back(BufferVertex{ + {p1.x, p1.y, p1.z, p1.w}, + {uv1_a.x, uv1_a.y}, + {uv1_b.x, uv1_b.y}, + {color.r, color.g, color.b, color.a}, + mix + }); + vertices.push_back(BufferVertex{ + {p2.x, p2.y, p2.z, p2.w}, + {uv2_a.x, uv2_a.y}, + {uv2_b.x, uv2_b.y}, + {color.r, color.g, color.b, color.a}, + mix + }); + vertices.push_back(BufferVertex{ + {p3.x, p3.y, p3.z, p3.w}, + {uv3_a.x, uv3_a.y}, + {uv3_b.x, uv3_b.y}, + {color.r, color.g, color.b, color.a}, + mix + }); + indices.insert(indices.end(), {base, base + 1, base + 2, base + 2, base + 3, base}); + nElements++; + } } void MsdfLayer::setAtlas(shared_ptr _atlas){ atlas = _atlas; diff --git a/src/MsdfLayer.h b/src/MsdfLayer.h index a957933..7d195db 100644 --- a/src/MsdfLayer.h +++ b/src/MsdfLayer.h @@ -25,17 +25,8 @@ class MsdfLayer : public Layer { GLfloat position[4]; GLfloat uv_a[2]; GLfloat uv_b[2]; - }; - struct CharacterDrawParameters { - glm::vec2 dimensions; - glm::vec4 fontColor; - glm::vec4 bgColor; - glm::vec2 unitRange; - glm::vec2 translation_a; - glm::vec2 scale_a; - glm::vec2 translation_b; - glm::vec2 scale_b; - float mix; + GLfloat color[4]; + GLfloat mix; }; void setup(const LayerSettings & settings = LayerSettings()) override; void update() override; @@ -67,6 +58,7 @@ class MsdfLayer : public Layer { void setBoundingBox(const Layer::BoundingBox & boundingBox) override; void collectCharacter(const char character, const ofNode & node, + const ofCamera & camera, glm::vec4 color = glm::vec4(1, 1, 1, 1), ofxVariableLab::FontVariation fontVariation = ofxVariableLab::FontVariation()); @@ -88,7 +80,8 @@ class MsdfLayer : public Layer { UboParameters uboParameters; std::vector vertices; - std::vector parameters; + std::vector indices; + int nElements = 0; private: Props lastProps; diff --git a/src/Utils.h b/src/Utils.h index 6c5a80e..3ee01ad 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -6,6 +6,10 @@ #include #include #include "json.hpp" +#include "ofAppRunner.h" +#include "of3dGraphics.h" +#include "ofCamera.h" +#include "ofUtils.h" #include #include FT_FREETYPE_H #include FT_MULTIPLE_MASTERS_H @@ -163,4 +167,19 @@ static bool isInside(float px, float py, float x, float y, float w, float h){ return px >= x && px <= x + w && py >= y && py <= y + h; } +static bool isInside(const ofCamera & camera, const glm::vec4 & position){ + const auto & viewport = ofGetCurrentRenderer()->getCurrentViewport(); + glm::vec3 screenPosition = camera.worldToScreen(position); + glm::vec3 cameraPosition = camera.worldToCamera(position); + //glm::mat4 clipSpaceToWorld = camera.getGlobalTransformMatrix() * glm::inverse(camera.getProjectionMatrix(viewport)); + //glm::mat4 worldToClipSpace = camera.getProjectionMatrix(viewport); + //glm::vec4 worldSpacePosition = position * worldToClipSpace; + if(screenPosition.x >= 0.0f && screenPosition.x <= ofGetWidth() + && screenPosition.y >= 0.0f && screenPosition.y <= ofGetHeight() + && screenPosition.z <= 1.0f){ + return true; + } + return false; +} + }