From ee47b7649a5f7bacb733a8cea43764dda81a1dda Mon Sep 17 00:00:00 2001 From: themancalledjakob Date: Wed, 12 Apr 2023 11:07:19 +0200 Subject: [PATCH] slight refactor --- example/src/ofApp.cpp | 4 +- example/src/ofApp.h | 4 +- src/glm.hpp | 18 - src/{ => gpufont}/defer.hpp | 0 src/gpufont/maingpufont.hpp | 717 --------------------------------- src/gpufont/shader_catalog.cpp | 2 + src/gpufont/shader_catalog.hpp | 2 + 7 files changed, 8 insertions(+), 739 deletions(-) delete mode 100644 src/glm.hpp rename src/{ => gpufont}/defer.hpp (100%) delete mode 100644 src/gpufont/maingpufont.hpp diff --git a/example/src/ofApp.cpp b/example/src/ofApp.cpp index d832511..111553a 100644 --- a/example/src/ofApp.cpp +++ b/example/src/ofApp.cpp @@ -88,7 +88,7 @@ start. I hope to capture something essential.)DONE"; #else string shaderDir = "data/ofxGPUFont/shaders/GL3"; #endif - shaderCatalog = std::make_unique (shaderDir); + shaderCatalog = std::make_unique (shaderDir); //backgroundShader = shaderCatalog->get("background"); fontShader = shaderCatalog->get("font"); @@ -252,7 +252,7 @@ void ofApp::keyReleased(int key){ #else string shaderDir = "data/ofxGPUFont/shaders/GL3"; #endif - shaderCatalog = std::make_unique (shaderDir); + shaderCatalog = std::make_unique (shaderDir); //backgroundShader = shaderCatalog->get("background"); fontShader = shaderCatalog->get("font"); } diff --git a/example/src/ofApp.h b/example/src/ofApp.h index e47ce5a..828b73c 100644 --- a/example/src/ofApp.h +++ b/example/src/ofApp.h @@ -46,9 +46,9 @@ class ofApp : public ofBaseApp { // because OpenGL still requires a non-zero VAO to be bound for the draw call. GLuint emptyVAO; - std::unique_ptr shaderCatalog; + std::unique_ptr shaderCatalog; //std::shared_ptr backgroundShader; - std::shared_ptr fontShader; + std::shared_ptr fontShader; ofxGPUFont::Font::BoundingBox bb; diff --git a/src/glm.hpp b/src/glm.hpp deleted file mode 100644 index e6c9e80..0000000 --- a/src/glm.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#define GLM_FORCE_RADIANS -#define GLM_ENABLE_EXPERIMENTAL - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include diff --git a/src/defer.hpp b/src/gpufont/defer.hpp similarity index 100% rename from src/defer.hpp rename to src/gpufont/defer.hpp diff --git a/src/gpufont/maingpufont.hpp b/src/gpufont/maingpufont.hpp deleted file mode 100644 index 16b4935..0000000 --- a/src/gpufont/maingpufont.hpp +++ /dev/null @@ -1,717 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ofMain.h" - -#include -#include FT_FREETYPE_H -#include FT_MULTIPLE_MASTERS_H - -#include "glm.hpp" - -#include "shader_catalog.hpp" - -#define F26DOT6_TO_DOUBLE(x) (1 / 64. * double(x)) -#define F16DOT16_TO_DOUBLE(x) (1 / 65536. * double(x)) -#define DOUBLE_TO_F16DOT16(x) FT_Fixed(65536. * x) - -#include "font.hpp" - -float wght = 700.0; -float wghtStep = 10.0; -std::string currentFontPath = ""; - -struct Transform { - float fovy = glm::radians(60.0f); - float distance = 0.42f; - glm::mat3 rotation = glm::mat3(1.0f); - glm::vec3 position = glm::vec3(0.0f); - - glm::mat4 getProjectionMatrix(float aspect){ - return glm::perspective( /* fovy = */ glm::radians(60.0f), aspect, 0.002f, 12.000f); - } - - glm::mat4 getViewMatrix(){ - auto translation = glm::translate(position); - return glm::lookAt(glm::vec3(0, 0, distance), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)) * glm::mat4(rotation) * translation; - } -}; - -struct DragController { - enum class Action { - NONE, - TRANSLATE, - ROTATE_TURNTABLE, - ROTATE_TRACKBALL - }; - - Transform * transform = nullptr; - int activeButton = -1; - Action activeAction = Action::NONE; - - double dragX, dragY; - double wrapX, wrapY; - double virtualX, virtualY; - glm::vec3 dragTarget; - - void reset(){ - // Reset transform. - *transform = Transform{}; - - // Cancel active action, if any. - activeButton = -1; - activeAction = Action::NONE; - } - - bool unprojectMousePositionToXYPlane(GLFWwindow * window, double x, double y, glm::vec3 & result){ - int iwidth = 0, iheight = 0; - glfwGetWindowSize(window, &iwidth, &iheight); - - double width = iwidth; - double height = iheight; - - glm::mat4 projection = transform->getProjectionMatrix(float(width / height)); - glm::mat4 view = transform->getViewMatrix(); - - double relX = x / width * 2.0 - 1.0; - double relY = y / height * 2.0 - 1.0; - - glm::vec4 clipPos = glm::vec4(float(relX), -float(relY), 0.5f, 1.0f); - glm::vec4 worldPos = glm::inverse(projection * view) * clipPos; - worldPos *= 1.0f / worldPos.w; - - glm::vec3 pos = glm::vec3(glm::column(glm::inverse(view), 3)); - glm::vec3 dir = glm::normalize(glm::vec3(worldPos) - pos); - float t = -pos.z / dir.z; - - result = pos + t * dir; - return t > 0.0f; - } - - void onMouseButton(GLFWwindow * window, int button, int action, int mods){ - if(action == GLFW_PRESS && activeButton == -1){ - activeButton = button; - - if(mods & GLFW_MOD_CONTROL){ - activeAction = Action::TRANSLATE; - }else{ - if(activeButton == GLFW_MOUSE_BUTTON_2){ - activeAction = Action::TRANSLATE; - }else if(activeButton == GLFW_MOUSE_BUTTON_3){ - activeAction = Action::ROTATE_TURNTABLE; - }else{ - activeAction = Action::ROTATE_TRACKBALL; - } - } - - glfwGetCursorPos(window, &dragX, &dragY); - wrapX = std::numeric_limits ::quiet_NaN(); - wrapY = std::numeric_limits ::quiet_NaN(); - virtualX = dragX; - virtualY = dragY; - - glm::vec3 target; - bool ok = unprojectMousePositionToXYPlane(window, dragX, dragY, target); - dragTarget = ok ? target : glm::vec3(); - }else if(action == GLFW_RELEASE && activeButton == button){ - activeButton = -1; - activeAction = Action::NONE; - dragX = 0.0; - dragY = 0.0; - wrapX = std::numeric_limits ::quiet_NaN(); - wrapY = std::numeric_limits ::quiet_NaN(); - virtualX = 0.0; - virtualY = 0.0; - dragTarget = glm::vec3(); - } - } - - void onCursorPos(GLFWwindow * window, double x, double y){ - if(activeAction == Action::NONE){ - return; - } - - int iwidth = 0, iheight = 0; - glfwGetWindowSize(window, &iwidth, &iheight); - - double width = iwidth; - double height = iheight; - - double deltaX = x - dragX; - double deltaY = y - dragY; - - if(!std::isnan(wrapX) && !std::isnan(wrapY)){ - double wrapDeltaX = x - wrapX; - double wrapDeltaY = y - wrapY; - if(wrapDeltaX * wrapDeltaX + wrapDeltaY * wrapDeltaY < deltaX * deltaX + deltaY * deltaY){ - deltaX = wrapDeltaX; - deltaY = wrapDeltaY; - wrapX = std::numeric_limits ::quiet_NaN(); - wrapY = std::numeric_limits ::quiet_NaN(); - } - } - - dragX = x; - dragY = y; - - double targetX = x; - double targetY = y; - bool changed = false; - if(targetX < 0){ - targetX += width - 1; - changed = true; - }else if(targetX >= width){ - targetX -= width - 1; - changed = true; - } - if(targetY < 0){ - targetY += height - 1; - changed = true; - }else if(targetY >= height){ - targetY -= height - 1; - changed = true; - } - if(changed){ - glfwSetCursorPos(window, targetX, targetY); - wrapX = targetX; - wrapY = targetY; - } - - if(activeAction == Action::TRANSLATE){ - virtualX += deltaX; - virtualY += deltaY; - - glm::vec3 target; - bool ok = unprojectMousePositionToXYPlane(window, virtualX, virtualY, target); - if(ok){ - float x = transform->position.x; - float y = transform->position.y; - glm::vec3 delta = target - dragTarget; - transform->position.x = glm::clamp(x + delta.x, -4.0f, 4.0f); - transform->position.y = glm::clamp(y + delta.y, -4.0f, 4.0f); - } - }else if(activeAction == Action::ROTATE_TURNTABLE){ - double size = glm::min(width, height); - glm::mat3 rx = glm::rotate(float(deltaX / size * glm::pi ()), glm::vec3(0, 0, 1)); - glm::mat3 ry = glm::rotate(float(deltaY / size * glm::pi ()), glm::vec3(1, 0, 0)); - transform->rotation = ry * transform->rotation * rx; - }else if(activeAction == Action::ROTATE_TRACKBALL){ - double size = glm::min(width, height); - glm::mat3 rx = glm::rotate(float(deltaX / size * glm::pi ()), glm::vec3(0, 1, 0)); - glm::mat3 ry = glm::rotate(float(deltaY / size * glm::pi ()), glm::vec3(1, 0, 0)); - transform->rotation = ry * rx * transform->rotation; - } - } - - void onScroll(GLFWwindow * window, double xOffset, double yOffset){ - float factor = glm::clamp(1.0 - float(yOffset) / 10.0, 0.1, 1.9); - transform->distance = glm::clamp(transform->distance * factor, 0.010f, 10.000f); - } -}; - -namespace { -FT_Library library; - -Transform transform; -DragController dragController; - -// Empty VAO used when the vertex shader has no input and only uses gl_VertexID, -// because OpenGL still requires a non-zero VAO to be bound for the draw call. -GLuint emptyVAO; - -std::unique_ptr shaderCatalog; -std::shared_ptr backgroundShader; -std::shared_ptr fontShader; - -std::unique_ptr mainFont; -std::unique_ptr helpFont; -std::vector > otherFonts; -std::vector otherWghts; -std::vector otherSteps; -static const int N_OTHER_FONTS = 5; - -constexpr float helpFontBaseSize = 20.0f; - -int antiAliasingWindowSize = 1; -bool enableSuperSamplingAntiAliasing = true; -bool enableControlPointsVisualization = false; - -bool showHelp = true; - -Font::BoundingBox bb; -std::string mainTexta = - R"DONE(AVM AAIn the center of Fedora, that gray stone metropolis, stands a metal building -[from Invisible Cities by Italo Calvino])DONE"; -std::string mainText = - R"DONE(In the center of Fedora, that gray stone metropolis, stands a metal building -with a crystal globe in every room. Looking into each globe, you see a blue -city, the model of a different Fedora. These are the forms the city could have -taken if, for one reason or another, it had not become what we see today. In -every age someone, looking at Fedora as it was, imagined a way of making it the -ideal city, but while he constructed his miniature model, Fedora was already no -longer the same as before, and what had been until yesterday a possible future -became only a toy in a glass globe. - -The building with the globes is now Fedora's museum: every inhabitant visits it, -chooses the city that corresponds to his desires, contemplates it, imagining his -reflection in the medusa pond that would have collected the waters of the canal -(if it had not been dried up), the view from the high canopied box along the -avenue reserved for elephants (now banished from the city), the fun of sliding -down the spiral, twisting minaret (which never found a pedestal from which to -rise). - -On the map of your empire, O Great Khan, there must be room both for the big, -stone Fedora and the little Fedoras in glass globes. Not because they are all -equally real, but because they are only assumptions. The one contains what is -accepted as necessary when it is not yet so; the others, what is imagined as -possible and, a moment later, is possible no longer. - -On the map of your empire, O Great Khan, there must be room both for the big, -stone Fedora and the little Fedoras in glass globes. Not because they are all -equally real, but because they are only assumptions. The one contains what is -accepted as necessary when it is not yet so; the others, what is imagined as -possible and, a moment later, is possible no longer. - -On the map of your empire, O Great Khan, there must be room both for the big, -stone Fedora and the little Fedoras in glass globes. Not because they are all -equally real, but because they are only assumptions. The one contains what is -accepted as necessary when it is not yet so; the others, what is imagined as -possible and, a moment later, is possible no longer. - -On the map of your empire, O Great Khan, there must be room both for the big, -stone Fedora and the little Fedoras in glass globes. Not because they are all -equally real, but because they are only assumptions. The one contains what is -accepted as necessary when it is not yet so; the others, what is imagined as -possible and, a moment later, is possible no longer. - -The building with the globes is now Fedora's museum: every inhabitant visits it, -chooses the city that corresponds to his desires, contemplates it, imagining his -reflection in the medusa pond that would have collected the waters of the canal -(if it had not been dried up), the view from the high canopied box along the -avenue reserved for elephants (now banished from the city), the fun of sliding -down the spiral, twisting minaret (which never found a pedestal from which to -rise). - -The building with the globes is now Fedora's museum: every inhabitant visits it, -chooses the city that corresponds to his desires, contemplates it, imagining his -reflection in the medusa pond that would have collected the waters of the canal -(if it had not been dried up), the view from the high canopied box along the -avenue reserved for elephants (now banished from the city), the fun of sliding -down the spiral, twisting minaret (which never found a pedestal from which to -rise). - -On the map of your empire, O Great Khan, there must be room both for the big, -stone Fedora and the little Fedoras in glass globes. Not because they are all -equally real, but because they are only assumptions. The one contains what is -accepted as necessary when it is not yet so; the others, what is imagined as -possible and, a moment later, is possible no longer. - -On the map of your empire, O Great Khan, there must be room both for the big, -stone Fedora and the little Fedoras in glass globes. Not because they are all -equally real, but because they are only assumptions. The one contains what is -accepted as necessary when it is not yet so; the others, what is imagined as -possible and, a moment later, is possible no longer. - -On the map of your empire, O Great Khan, there must be room both for the big, -stone Fedora and the little Fedoras in glass globes. Not because they are all -equally real, but because they are only assumptions. The one contains what is -accepted as necessary when it is not yet so; the others, what is imagined as -possible and, a moment later, is possible no longer. - -On the map of your empire, O Great Khan, there must be room both for the big, -stone Fedora and the little Fedoras in glass globes. Not because they are all -equally real, but because they are only assumptions. The one contains what is -accepted as necessary when it is not yet so; the others, what is imagined as -possible and, a moment later, is possible no longer. -[from Invisible Cities by Italo Calvino])DONE"; - -} - -void updateWght(float & value, float & step){ - value += step; - - if(value >= 700.0){ - if(step > 0){ - step *= -1; - } - value += step; - } - if(value <= 100.0){ - if(step < 0){ - step *= -1; - } - value += step; - } -} - -int currentIndexx = -1; - -static std::unique_ptr loadFont(const std::string & filename, float worldSize = 1.0f, bool hinting = false){ - std::string error; - FT_Face face = Font::loadFace(library, filename, error); - float & wghtValue = currentIndexx < 0 ? wght : otherWghts[currentIndexx]; - bool success = Font::setFontVariationAxis(library, face, "Weight", wghtValue); - //if(success){ - //std::cout << "lol, success?" << wght << std::endl; - //}else{ - //std::cout << "godverdomme" << wght << std::endl; - //} - if(error != ""){ - std::cerr << "[font] failed to load " << filename << ": " << error << std::endl; - return std::unique_ptr {}; - } - - return std::make_unique (face, worldSize, hinting); -} - -static void tryUpdateMainFont(const std::string & filename){ - { - currentIndexx = -1; - auto font = loadFont(filename, 0.05f); - if(!font){ - return; - } - - font->dilation = 0.1f; - - font->prepareGlyphsForText(mainText); - - mainFont = std::move(font); - bb = mainFont->measure(0, 0, mainText); - } - updateWght(wght, wghtStep); - - for(int i = 0; i < N_OTHER_FONTS; ++i){ - if(otherWghts.size() == i){ - int w = i * 213456; - while(w > 700){ - w -= 700; - } - otherWghts.push_back(float(w)); - otherSteps.push_back(float(wghtStep)); - } - currentIndexx = i; - auto font = loadFont(filename, 0.05f); - if(!font){ - return; - } - updateWght(otherWghts[i], otherSteps[i]); - //std::cout << "updateWght(" << otherWghts[i] << "," << otherSteps[i] << ");" << std::endl; - - font->dilation = 0.1f; - - font->prepareGlyphsForText(mainText); - - if(otherFonts.size() == i){ - otherFonts.push_back(std::move(font)); - }else{ - otherFonts[i] = std::move(font); - } - } -} - -static void mouseButtonCallback(GLFWwindow * window, int button, int action, int mods){ - dragController.onMouseButton(window, button, action, mods); -} - -static void cursorPosCallback(GLFWwindow * window, double x, double y){ - dragController.onCursorPos(window, x, y); -} - -static void scrollCallback(GLFWwindow * window, double xOffset, double yOffset){ - dragController.onScroll(window, xOffset, yOffset); -} - -static void keyCallback(GLFWwindow * window, int key, int scancode, int action, int mods){ - if(action != GLFW_PRESS){ - return; - } - switch(key){ - case GLFW_KEY_R: - dragController.reset(); - break; - - case GLFW_KEY_C: - enableControlPointsVisualization = !enableControlPointsVisualization; - break; - - case GLFW_KEY_A: - enableSuperSamplingAntiAliasing = !enableSuperSamplingAntiAliasing; - break; - - case GLFW_KEY_0: - antiAliasingWindowSize = 0; - break; - - case GLFW_KEY_1: - antiAliasingWindowSize = 1; - break; - - case GLFW_KEY_2: - antiAliasingWindowSize = 20; - break; - - case GLFW_KEY_3: - antiAliasingWindowSize = 40; - break; - - case GLFW_KEY_S: - antiAliasingWindowSize = 1; - enableSuperSamplingAntiAliasing = true; - break; - - case GLFW_KEY_H: - showHelp = !showHelp; - break; - } -} - -static void dropCallback(GLFWwindow * window, int pathCount, const char * paths[]){ - if(pathCount == 0){ - return; - } - currentFontPath = paths[0]; - tryUpdateMainFont(paths[0]); -} - -int main(int argc, char * argv[]){ - if(!glfwInit()){ - std::cerr << "ERROR: failed to initialize GLFW" << std::endl; - return 1; - } - - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); - glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE); - - GLFWwindow * window = glfwCreateWindow(1600, 900, "GPU Font Rendering Demo", nullptr, nullptr); - if(!window){ - std::cerr << "ERROR: failed to create GLFW window" << std::endl; - glfwTerminate(); - return 1; - } - - glfwMakeContextCurrent(window); - - if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){ - std::cerr << "ERROR: failed to initialize OpenGL context" << std::endl; - glfwTerminate(); - return 1; - } - - { - FT_Error error = FT_Init_FreeType(&library); - if(error){ - std::cerr << "ERROR: failed to initialize FreeType" << std::endl; - glfwTerminate(); - return 1; - } - } - - dragController.transform = &transform; - glfwSetMouseButtonCallback(window, mouseButtonCallback); - glfwSetCursorPosCallback(window, cursorPosCallback); - glfwSetScrollCallback(window, scrollCallback); - glfwSetKeyCallback(window, keyCallback); - glfwSetDropCallback(window, dropCallback); - - glGenVertexArrays(1, &emptyVAO); - - shaderCatalog = std::make_unique ("shaders"); - backgroundShader = shaderCatalog->get("background"); - fontShader = shaderCatalog->get("font"); - - currentFontPath = "fonts/SourceSerifPro-Regular.otf"; - tryUpdateMainFont(currentFontPath); - - { - float xscale, yscale; - glfwGetWindowContentScale(window, &xscale, &yscale); - float worldSize = std::ceil(helpFontBaseSize * yscale); - helpFont = loadFont("fonts/SourceSansPro-Semibold.otf", worldSize, true); - } - - while(!glfwWindowShouldClose(window)){ - tryUpdateMainFont(currentFontPath); - shaderCatalog->update(); - - glfwPollEvents(); - - int width, height; - glfwGetFramebufferSize(window, &width, &height); - glViewport(0, 0, width, height); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - GLuint location; - - glm::mat4 projection = transform.getProjectionMatrix((float)width / height); - glm::mat4 view = transform.getViewMatrix(); - glm::mat4 model = glm::mat4(1.0f); - - { // Draw background. - GLuint program = backgroundShader->program; - glUseProgram(program); - glBindVertexArray(emptyVAO); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindVertexArray(0); - glUseProgram(0); - } - - // Uses premultiplied-alpha. - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - for(int i = N_OTHER_FONTS - 1; i >= 0; i--){ - if(otherFonts.size() > i){ - //std::cout << "drawing " << i << " with " << otherWghts[i] << std::endl; - auto & otherFont = otherFonts[i]; - GLuint program = fontShader->program; - glUseProgram(program); - - otherFont->program = program; - otherFont->drawSetup(); - - location = glGetUniformLocation(program, "projection"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(projection)); - location = glGetUniformLocation(program, "view"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(view)); - location = glGetUniformLocation(program, "model"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(model)); - - location = glGetUniformLocation(program, "color"); - float r = float(i) / N_OTHER_FONTS; - float g = sin(42.143 * float(i) + otherWghts[i] * 0.0001) * 0.5 + 0.5; - float b = cos(3.143 * float(i) + otherWghts[i] * 0.0005) * 0.1 + 0.1; - glUniform4f(location, r, 1.0f - r, 1.0f - r, 1.0f); - float z = (i + 1) * -0.1; - location = glGetUniformLocation(program, "z"); - glUniform1f(location, z); - - location = glGetUniformLocation(program, "antiAliasingWindowSize"); - glUniform1f(location, (float)antiAliasingWindowSize); - location = glGetUniformLocation(program, "enableSuperSamplingAntiAliasing"); - glUniform1i(location, enableSuperSamplingAntiAliasing); - location = glGetUniformLocation(program, "enableControlPointsVisualization"); - glUniform1i(location, enableControlPointsVisualization); - - float cx = 0.5f * (bb.minX + bb.maxX); - float cy = 0.5f * (bb.minY + bb.maxY); - otherFont->draw(-cx, -cy, 0, mainText); - glUseProgram(0); - } - } - if(mainFont){ - GLuint program = fontShader->program; - glUseProgram(program); - - mainFont->program = program; - mainFont->drawSetup(); - - location = glGetUniformLocation(program, "projection"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(projection)); - location = glGetUniformLocation(program, "view"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(view)); - location = glGetUniformLocation(program, "model"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(model)); - float z = 0; - location = glGetUniformLocation(program, "z"); - glUniform1f(location, z); - - location = glGetUniformLocation(program, "color"); - glUniform4f(location, 1.0f, 1.0f, 1.0f, 1.0f); - - location = glGetUniformLocation(program, "antiAliasingWindowSize"); - glUniform1f(location, (float)antiAliasingWindowSize); - location = glGetUniformLocation(program, "enableSuperSamplingAntiAliasing"); - glUniform1i(location, enableSuperSamplingAntiAliasing); - location = glGetUniformLocation(program, "enableControlPointsVisualization"); - glUniform1i(location, enableControlPointsVisualization); - - float cx = 0.5f * (bb.minX + bb.maxX); - float cy = 0.5f * (bb.minY + bb.maxY); - mainFont->draw(-cx, -cy, 0, mainText); - glUseProgram(0); - } - - if(helpFont && showHelp){ - GLuint program = fontShader->program; - glUseProgram(program); - - helpFont->program = program; - helpFont->drawSetup(); - - glm::mat4 projection = glm::ortho(0.0f, (float)width, 0.0f, (float)height, -1.0f, 1.0f); - glm::mat4 view = glm::mat4(1.0f); - glm::mat4 model = glm::mat4(1.0f); - - location = glGetUniformLocation(program, "projection"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(projection)); - location = glGetUniformLocation(program, "view"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(view)); - location = glGetUniformLocation(program, "model"); - glUniformMatrix4fv(location, 1, false, glm::value_ptr(model)); - - location = glGetUniformLocation(program, "color"); - float r = 200, g = 35, b = 220, a = 0.8; - glUniform4f(location, r * a / 255.0f, g * a / 255.0f, b * a / 255.0f, a); - - location = glGetUniformLocation(program, "antiAliasingWindowSize"); - glUniform1f(location, 1.0f); - location = glGetUniformLocation(program, "enableSuperSamplingAntiAliasing"); - glUniform1i(location, true); - location = glGetUniformLocation(program, "enableControlPointsVisualization"); - glUniform1i(location, false); - - std::stringstream stream; - stream << "Drag and drop a .ttf or .otf file to change the font\n"; - stream << "\n"; - stream << "right drag (or CTRL drag) - move\n"; - stream << "left drag - trackball rotate\n"; - stream << "middle drag - turntable rotate\n"; - stream << "scroll wheel - zoom\n"; - stream << "\n"; - stream << "0, 1, 2, 3 - change anti-aliasing window size: " << antiAliasingWindowSize << " pixel" << ((antiAliasingWindowSize != 1) ? "s" : "") << "\n"; - stream << glfwGetKeyName(GLFW_KEY_A, 0) << " - " << (enableSuperSamplingAntiAliasing ? "disable" : "enable") << " 2D anti-aliasing\n"; - stream << "(using another ray along the y-axis)\n"; - stream << glfwGetKeyName(GLFW_KEY_S, 0) << " - reset anti-aliasing settings\n"; - stream << glfwGetKeyName(GLFW_KEY_C, 0) << " - " << (enableControlPointsVisualization ? "disable" : "enable") << " control points\n"; - stream << glfwGetKeyName(GLFW_KEY_R, 0) << " - reset view\n"; - stream << glfwGetKeyName(GLFW_KEY_H, 0) << " - toggle help\n"; - - std::string helpText = stream.str(); - helpFont->prepareGlyphsForText(helpText); - - float xscale, yscale; - glfwGetWindowContentScale(window, &xscale, &yscale); - helpFont->setWorldSize(std::ceil(helpFontBaseSize * yscale)); - - auto bb = helpFont->measure(0, 0, helpText); - helpFont->draw(10 - bb.minX, height - 10 - bb.maxY, 0, helpText); - glUseProgram(0); - } - - glDisable(GL_BLEND); - - glfwSwapBuffers(window); - } - - // Clean up OpenGL resources before termination. - mainFont = nullptr; - helpFont = nullptr; - - glfwTerminate(); - return 0; -} diff --git a/src/gpufont/shader_catalog.cpp b/src/gpufont/shader_catalog.cpp index 165ff4d..b3ed7d4 100644 --- a/src/gpufont/shader_catalog.cpp +++ b/src/gpufont/shader_catalog.cpp @@ -14,6 +14,7 @@ // UpdateList keeps track of which entries need to be updated. // The actual update is slightly delayed to avoid reading a partially written file. // It is threadsafe to allow safe communication with the asynchronous file watcher callback. +namespace ofxGPUFont { class UpdateList { std::mutex mutex; std::unordered_map updates; @@ -189,3 +190,4 @@ std::shared_ptr ShaderCatalog::get(const std::string & na void ShaderCatalog::update(){ impl->update(); } +} diff --git a/src/gpufont/shader_catalog.hpp b/src/gpufont/shader_catalog.hpp index e303e0e..e27f7f6 100644 --- a/src/gpufont/shader_catalog.hpp +++ b/src/gpufont/shader_catalog.hpp @@ -9,6 +9,7 @@ // example.frag are loaded and linked together to form the "example" program). // Whenever a shader file changes on disk, the corresponding program is // recompiled and relinked. +namespace ofxGPUFont { class ShaderCatalog { public: struct Entry { @@ -30,3 +31,4 @@ class ShaderCatalog { class Impl; std::unique_ptr impl; }; +}