From 5e00c5f10edae84ed7dd9fc33c344328fa36faad Mon Sep 17 00:00:00 2001 From: keenancrane Date: Mon, 11 Oct 2021 07:18:19 -0400 Subject: [PATCH 1/2] Add contour shader --- .../polyscope/render/opengl/shaders/rules.h | 1 + include/polyscope/scalar_quantity.h | 12 ++- include/polyscope/scalar_quantity.ipp | 88 ++++++++++++++++++- src/render/mock_opengl/mock_gl_engine.cpp | 1 + src/render/opengl/gl_engine.cpp | 1 + src/render/opengl/shaders/rules.cpp | 24 +++++ 6 files changed, 125 insertions(+), 2 deletions(-) diff --git a/include/polyscope/render/opengl/shaders/rules.h b/include/polyscope/render/opengl/shaders/rules.h index c1574b5f..8e41a2a3 100644 --- a/include/polyscope/render/opengl/shaders/rules.h +++ b/include/polyscope/render/opengl/shaders/rules.h @@ -24,6 +24,7 @@ extern const ShaderReplacementRule SHADE_GRID_VALUE2; // generate a tw extern const ShaderReplacementRule SHADE_CHECKER_VALUE2; // generate a two-color checker from shadeValue2 extern const ShaderReplacementRule SHADEVALUE_MAG_VALUE2; // generate a shadeValue from the magnitude of shadeValue2 extern const ShaderReplacementRule ISOLINE_STRIPE_VALUECOLOR; // modulate albedoColor based on shadeValue +extern const ShaderReplacementRule CONTOUR_VALUECOLOR; // modulate albedoColor based on shadeValue extern const ShaderReplacementRule CHECKER_VALUE2COLOR; // modulate albedoColor based on shadeValue2 // Positions, culling, etc diff --git a/include/polyscope/scalar_quantity.h b/include/polyscope/scalar_quantity.h index a6b86617..92753f2a 100644 --- a/include/polyscope/scalar_quantity.h +++ b/include/polyscope/scalar_quantity.h @@ -47,7 +47,14 @@ class ScalarQuantity { double getIsolineWidth(); QuantityT* setIsolineDarkness(double val); double getIsolineDarkness(); - + + // Contours + QuantityT* setContoursEnabled(bool newEnabled); + bool getContoursEnabled(); + QuantityT* setContourFrequency(double size, bool isRelative); + double getContourFrequency(); + QuantityT* setContourThickness(double val); + double getContourThickness(); protected: // === Visualization parameters @@ -62,6 +69,9 @@ class ScalarQuantity { PersistentValue isolinesEnabled; PersistentValue> isolineWidth; PersistentValue isolineDarkness; + PersistentValue contoursEnabled; + PersistentValue> contourFrequency; + PersistentValue contourThickness; }; } // namespace polyscope diff --git a/include/polyscope/scalar_quantity.ipp b/include/polyscope/scalar_quantity.ipp index dab47e43..b70cc018 100644 --- a/include/polyscope/scalar_quantity.ipp +++ b/include/polyscope/scalar_quantity.ipp @@ -6,7 +6,10 @@ ScalarQuantity::ScalarQuantity(QuantityT& quantity_, const std::vecto cMap(quantity.name + "#cmap", defaultColorMap(dataType)), isolinesEnabled(quantity.name + "#isolinesEnabled", false), isolineWidth(quantity.name + "#isolineWidth", absoluteValue((dataRange.second - dataRange.first) * 0.02)), - isolineDarkness(quantity.name + "#isolineDarkness", 0.7) + isolineDarkness(quantity.name + "#isolineDarkness", 0.7), + contoursEnabled(quantity.name + "#contoursEnabled", false), + contourFrequency(quantity.name + "#contourFrequency", absoluteValue((dataRange.second - dataRange.first) * 0.3)), + contourThickness(quantity.name + "#contourThickness", 0.2) { hist.updateColormap(cMap.get()); @@ -88,12 +91,47 @@ void ScalarQuantity::buildScalarUI() { ImGui::PopItemWidth(); } + + // Contours + if (contoursEnabled.get()) { + ImGui::PushItemWidth(100); + + // Contour frequency + ImGui::TextUnformatted("Contour frequency"); + ImGui::SameLine(); + if (contourFrequency.get().isRelative()) { + if (ImGui::DragFloat("##Contour frequency relative", contourFrequency.get().getValuePtr(), .001, 0.0001, 1.0, "%.4f", + 2.0)) { + contourFrequency.manuallyChanged(); + requestRedraw(); + } + } else { + float scaleWidth = dataRange.second - dataRange.first; + if (ImGui::DragFloat("##Contour frequency absolute", contourFrequency.get().getValuePtr(), scaleWidth / 1000, 0., + scaleWidth, "%.4f", 2.0)) { + contourFrequency.manuallyChanged(); + requestRedraw(); + } + } + + // Contour thickness + ImGui::TextUnformatted("Contour thickness"); + ImGui::SameLine(); + if (ImGui::DragFloat("##Contour thickness", &contourThickness.get(), 0.01, 0., 1.)) { + contourThickness.manuallyChanged(); + requestRedraw(); + } + + ImGui::PopItemWidth(); + } + } template void ScalarQuantity::buildScalarOptionsUI() { if (ImGui::MenuItem("Reset colormap range")) resetMapRange(); if (ImGui::MenuItem("Enable isolines", NULL, isolinesEnabled.get())) setIsolinesEnabled(!isolinesEnabled.get()); + if (ImGui::MenuItem("Enable contours", NULL, contoursEnabled.get())) setContoursEnabled(!contoursEnabled.get()); } template @@ -102,6 +140,9 @@ std::vector ScalarQuantity::addScalarRules(std::vector::setScalarUniforms(render::ShaderProgram& p) { p.setUniform("u_modLen", getIsolineWidth()); p.setUniform("u_modDarkness", getIsolineDarkness()); } + + if (contoursEnabled.get()) { + p.setUniform("u_modFrequency", getContourFrequency()); + p.setUniform("u_modThickness", getContourThickness()); + } } template @@ -201,4 +247,44 @@ bool ScalarQuantity::getIsolinesEnabled() { return isolinesEnabled.get(); } +template +QuantityT* ScalarQuantity::setContourFrequency(double size, bool isRelative) { + contourFrequency = ScaledValue(size, isRelative); + if (!contoursEnabled.get()) { + setContoursEnabled(true); + } + requestRedraw(); + return &quantity; +} +template +double ScalarQuantity::getContourFrequency() { + return contourFrequency.get().asAbsolute(); +} + +template +QuantityT* ScalarQuantity::setContourThickness(double val) { + contourThickness = val; + if (!contoursEnabled.get()) { + setContoursEnabled(true); + } + requestRedraw(); + return &quantity; +} +template +double ScalarQuantity::getContourThickness() { + return contourThickness.get(); +} + +template +QuantityT* ScalarQuantity::setContoursEnabled(bool newEnabled) { + contoursEnabled = newEnabled; + quantity.refresh(); + requestRedraw(); + return &quantity; +} +template +bool ScalarQuantity::getContoursEnabled() { + return contoursEnabled.get(); +} + } // namespace polyscope diff --git a/src/render/mock_opengl/mock_gl_engine.cpp b/src/render/mock_opengl/mock_gl_engine.cpp index 73551104..e05d74cf 100644 --- a/src/render/mock_opengl/mock_gl_engine.cpp +++ b/src/render/mock_opengl/mock_gl_engine.cpp @@ -1416,6 +1416,7 @@ void MockGLEngine::populateDefaultShadersAndRules() { registeredShaderRules.insert({"SHADE_CHECKER_VALUE2", SHADE_CHECKER_VALUE2}); registeredShaderRules.insert({"SHADEVALUE_MAG_VALUE2", SHADEVALUE_MAG_VALUE2}); registeredShaderRules.insert({"ISOLINE_STRIPE_VALUECOLOR", ISOLINE_STRIPE_VALUECOLOR}); + registeredShaderRules.insert({"CONTOUR_VALUECOLOR", CONTOUR_VALUECOLOR}); registeredShaderRules.insert({"CHECKER_VALUE2COLOR", CHECKER_VALUE2COLOR}); // mesh things diff --git a/src/render/opengl/gl_engine.cpp b/src/render/opengl/gl_engine.cpp index 2e00aaf6..a9b75dcd 100644 --- a/src/render/opengl/gl_engine.cpp +++ b/src/render/opengl/gl_engine.cpp @@ -2066,6 +2066,7 @@ void GLEngine::populateDefaultShadersAndRules() { registeredShaderRules.insert({"SHADE_CHECKER_VALUE2", SHADE_CHECKER_VALUE2}); registeredShaderRules.insert({"SHADEVALUE_MAG_VALUE2", SHADEVALUE_MAG_VALUE2}); registeredShaderRules.insert({"ISOLINE_STRIPE_VALUECOLOR", ISOLINE_STRIPE_VALUECOLOR}); + registeredShaderRules.insert({"CONTOUR_VALUECOLOR", CONTOUR_VALUECOLOR}); registeredShaderRules.insert({"CHECKER_VALUE2COLOR", CHECKER_VALUE2COLOR}); // mesh things diff --git a/src/render/opengl/shaders/rules.cpp b/src/render/opengl/shaders/rules.cpp index 7fc57a32..d0989b8f 100644 --- a/src/render/opengl/shaders/rules.cpp +++ b/src/render/opengl/shaders/rules.cpp @@ -242,6 +242,30 @@ const ShaderReplacementRule ISOLINE_STRIPE_VALUECOLOR ( /* textures */ {} ); + +const ShaderReplacementRule CONTOUR_VALUECOLOR ( + /* rule name */ "CONTOUR_VALUECOLOR", + { /* replacement sources */ + {"FRAG_DECLARATIONS", R"( + uniform float u_modFrequency; + uniform float u_modThickness; + )"}, + {"GENERATE_SHADE_COLOR", R"( + /* TODO: get rid of arbitrary constants */ + vec2 gradF = vec2( dFdx(shadeValue), dFdy(shadeValue) ); + float w = 1./( 1000. * u_modFrequency * u_modThickness * length(gradF) ); + float s = 1. - exp( -pow( w*(fract(abs(100.0*u_modFrequency*shadeValue))-0.5), 8.0 )); + albedoColor *= s; + )"} + }, + /* uniforms */ { + {"u_modFrequency", DataType::Float}, + {"u_modThickness", DataType::Float}, + }, + /* attributes */ {}, + /* textures */ {} +); + const ShaderReplacementRule CHECKER_VALUE2COLOR ( /* rule name */ "CHECKER_VALUE2COLOR", { /* replacement sources */ From 6c463c5600149243ff8f9d9db68f971ac4f94b79 Mon Sep 17 00:00:00 2001 From: keenancrane Date: Mon, 11 Oct 2021 07:34:35 -0400 Subject: [PATCH 2/2] Add darkness parameter to contour shader --- include/polyscope/scalar_quantity.h | 3 +++ include/polyscope/scalar_quantity.ipp | 26 +++++++++++++++++++++++++- src/render/opengl/shaders/rules.cpp | 6 ++++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/include/polyscope/scalar_quantity.h b/include/polyscope/scalar_quantity.h index 92753f2a..ab2705e2 100644 --- a/include/polyscope/scalar_quantity.h +++ b/include/polyscope/scalar_quantity.h @@ -55,6 +55,8 @@ class ScalarQuantity { double getContourFrequency(); QuantityT* setContourThickness(double val); double getContourThickness(); + QuantityT* setContourDarkness(double val); + double getContourDarkness(); protected: // === Visualization parameters @@ -72,6 +74,7 @@ class ScalarQuantity { PersistentValue contoursEnabled; PersistentValue> contourFrequency; PersistentValue contourThickness; + PersistentValue contourDarkness; }; } // namespace polyscope diff --git a/include/polyscope/scalar_quantity.ipp b/include/polyscope/scalar_quantity.ipp index b70cc018..410218b2 100644 --- a/include/polyscope/scalar_quantity.ipp +++ b/include/polyscope/scalar_quantity.ipp @@ -9,7 +9,8 @@ ScalarQuantity::ScalarQuantity(QuantityT& quantity_, const std::vecto isolineDarkness(quantity.name + "#isolineDarkness", 0.7), contoursEnabled(quantity.name + "#contoursEnabled", false), contourFrequency(quantity.name + "#contourFrequency", absoluteValue((dataRange.second - dataRange.first) * 0.3)), - contourThickness(quantity.name + "#contourThickness", 0.2) + contourThickness(quantity.name + "#contourThickness", 0.2), + contourDarkness(quantity.name + "#contourThickness", 0.5) { hist.updateColormap(cMap.get()); @@ -122,6 +123,14 @@ void ScalarQuantity::buildScalarUI() { requestRedraw(); } + // Contour darkness + ImGui::TextUnformatted("Contour darkness"); + ImGui::SameLine(); + if (ImGui::DragFloat("##Contour darkness", &contourDarkness.get(), 0.01, 0., 1.)) { + contourDarkness.manuallyChanged(); + requestRedraw(); + } + ImGui::PopItemWidth(); } @@ -160,6 +169,7 @@ void ScalarQuantity::setScalarUniforms(render::ShaderProgram& p) { if (contoursEnabled.get()) { p.setUniform("u_modFrequency", getContourFrequency()); p.setUniform("u_modThickness", getContourThickness()); + p.setUniform("u_modDarkness", getContourDarkness()); } } @@ -275,6 +285,20 @@ double ScalarQuantity::getContourThickness() { return contourThickness.get(); } +template +QuantityT* ScalarQuantity::setContourDarkness(double val) { + contourDarkness = val; + if (!contoursEnabled.get()) { + setContoursEnabled(true); + } + requestRedraw(); + return &quantity; +} +template +double ScalarQuantity::getContourDarkness() { + return contourDarkness.get(); +} + template QuantityT* ScalarQuantity::setContoursEnabled(bool newEnabled) { contoursEnabled = newEnabled; diff --git a/src/render/opengl/shaders/rules.cpp b/src/render/opengl/shaders/rules.cpp index d0989b8f..6e9ce1fd 100644 --- a/src/render/opengl/shaders/rules.cpp +++ b/src/render/opengl/shaders/rules.cpp @@ -249,18 +249,20 @@ const ShaderReplacementRule CONTOUR_VALUECOLOR ( {"FRAG_DECLARATIONS", R"( uniform float u_modFrequency; uniform float u_modThickness; + uniform float u_modDarkness; )"}, {"GENERATE_SHADE_COLOR", R"( /* TODO: get rid of arbitrary constants */ vec2 gradF = vec2( dFdx(shadeValue), dFdy(shadeValue) ); float w = 1./( 1000. * u_modFrequency * u_modThickness * length(gradF) ); - float s = 1. - exp( -pow( w*(fract(abs(100.0*u_modFrequency*shadeValue))-0.5), 8.0 )); - albedoColor *= s; + float s = u_modDarkness * exp( -pow( w*(fract(abs(100.0*u_modFrequency*shadeValue))-0.5), 8.0 )); + albedoColor *= 1.-s; )"} }, /* uniforms */ { {"u_modFrequency", DataType::Float}, {"u_modThickness", DataType::Float}, + {"u_modDarkness", DataType::Float}, }, /* attributes */ {}, /* textures */ {}