Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add contour shader #128

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/polyscope/render/opengl/shaders/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 14 additions & 1 deletion include/polyscope/scalar_quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,16 @@ 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();
QuantityT* setContourDarkness(double val);
double getContourDarkness();

protected:
// === Visualization parameters
Expand All @@ -62,6 +71,10 @@ class ScalarQuantity {
PersistentValue<bool> isolinesEnabled;
PersistentValue<ScaledValue<float>> isolineWidth;
PersistentValue<float> isolineDarkness;
PersistentValue<bool> contoursEnabled;
PersistentValue<ScaledValue<float>> contourFrequency;
PersistentValue<float> contourThickness;
PersistentValue<float> contourDarkness;
};

} // namespace polyscope
Expand Down
112 changes: 111 additions & 1 deletion include/polyscope/scalar_quantity.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ ScalarQuantity<QuantityT>::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),
contourDarkness(quantity.name + "#contourThickness", 0.5)

{
hist.updateColormap(cMap.get());
Expand Down Expand Up @@ -88,12 +92,55 @@ void ScalarQuantity<QuantityT>::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();
}

// Contour darkness
ImGui::TextUnformatted("Contour darkness");
ImGui::SameLine();
if (ImGui::DragFloat("##Contour darkness", &contourDarkness.get(), 0.01, 0., 1.)) {
contourDarkness.manuallyChanged();
requestRedraw();
}

ImGui::PopItemWidth();
}

}

template <typename QuantityT>
void ScalarQuantity<QuantityT>::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 <typename QuantityT>
Expand All @@ -102,6 +149,9 @@ std::vector<std::string> ScalarQuantity<QuantityT>::addScalarRules(std::vector<s
if (isolinesEnabled.get()) {
rules.push_back("ISOLINE_STRIPE_VALUECOLOR");
}
if (contoursEnabled.get()) {
rules.push_back("CONTOUR_VALUECOLOR");
}
return rules;
}

Expand All @@ -115,6 +165,12 @@ void ScalarQuantity<QuantityT>::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());
p.setUniform("u_modDarkness", getContourDarkness());
}
}

template <typename QuantityT>
Expand Down Expand Up @@ -201,4 +257,58 @@ bool ScalarQuantity<QuantityT>::getIsolinesEnabled() {
return isolinesEnabled.get();
}

template <typename QuantityT>
QuantityT* ScalarQuantity<QuantityT>::setContourFrequency(double size, bool isRelative) {
contourFrequency = ScaledValue<float>(size, isRelative);
if (!contoursEnabled.get()) {
setContoursEnabled(true);
}
requestRedraw();
return &quantity;
}
template <typename QuantityT>
double ScalarQuantity<QuantityT>::getContourFrequency() {
return contourFrequency.get().asAbsolute();
}

template <typename QuantityT>
QuantityT* ScalarQuantity<QuantityT>::setContourThickness(double val) {
contourThickness = val;
if (!contoursEnabled.get()) {
setContoursEnabled(true);
}
requestRedraw();
return &quantity;
}
template <typename QuantityT>
double ScalarQuantity<QuantityT>::getContourThickness() {
return contourThickness.get();
}

template <typename QuantityT>
QuantityT* ScalarQuantity<QuantityT>::setContourDarkness(double val) {
contourDarkness = val;
if (!contoursEnabled.get()) {
setContoursEnabled(true);
}
requestRedraw();
return &quantity;
}
template <typename QuantityT>
double ScalarQuantity<QuantityT>::getContourDarkness() {
return contourDarkness.get();
}

template <typename QuantityT>
QuantityT* ScalarQuantity<QuantityT>::setContoursEnabled(bool newEnabled) {
contoursEnabled = newEnabled;
quantity.refresh();
requestRedraw();
return &quantity;
}
template <typename QuantityT>
bool ScalarQuantity<QuantityT>::getContoursEnabled() {
return contoursEnabled.get();
}

} // namespace polyscope
1 change: 1 addition & 0 deletions src/render/mock_opengl/mock_gl_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/render/opengl/gl_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 26 additions & 0 deletions src/render/opengl/shaders/rules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,32 @@ 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;
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 = 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 */ {}
);

const ShaderReplacementRule CHECKER_VALUE2COLOR (
/* rule name */ "CHECKER_VALUE2COLOR",
{ /* replacement sources */
Expand Down