From 13a31ec9af3226cfbd0217a81153345da95739b2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 28 Oct 2019 15:32:31 +0100 Subject: [PATCH] Add a Viewer option to use a specif shader to make more obvious the orientation of the fragments in the shaded programs. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 13 +++ Polyhedron/demo/Polyhedron/Preferences.ui | 13 ++- Polyhedron/demo/Polyhedron/Viewer.cpp | 98 ++++++++++++++++++- Polyhedron/demo/Polyhedron/Viewer.h | 2 + .../shader_with_light.frag | 17 +++- .../resources/shader_with_light.frag | 24 ++++- Three/include/CGAL/Three/Viewer_interface.h | 3 + 7 files changed, 161 insertions(+), 9 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 9fb344a24b3..0b1a6661b6c 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -2275,6 +2275,11 @@ void MainWindow::on_actionPreferences_triggered() this->s_defaultPSRM = CGAL::Three::Three::modeFromName(text); }); + connect(prefdiag.backFrontColor_pushButton, &QPushButton::clicked, + this, [this](){ + qobject_cast(CGAL::Three::Three::activeViewer())->setBackFrontColors(); + }); + std::vector items; QBrush successBrush(Qt::green), errorBrush(Qt::red), @@ -2959,6 +2964,9 @@ void MainWindow::setupViewer(Viewer* viewer, SubViewer* subviewer) } viewer->setTotalPass(nb); }); + action= subviewer->findChild("actionBackFrontShading"); + connect(action, SIGNAL(toggled(bool)), + viewer, SLOT(setBackFrontShading(bool))); connect(viewer, SIGNAL(requestContextMenu(QPoint)), this, SLOT(contextMenuRequested(QPoint))); connect(viewer, SIGNAL(selected(int)), @@ -3127,6 +3135,11 @@ SubViewer::SubViewer(QWidget *parent, MainWindow* mw, Viewer* mainviewer) QAction* actionTotalPass = new QAction("Set Transparency Pass &Number...",this); actionTotalPass->setObjectName("actionTotalPass"); viewMenu->addAction(actionTotalPass); + QAction* actionBackFrontShading = new QAction("Activate Back/Front shading.",this); + actionBackFrontShading->setObjectName("actionBackFrontShading"); + actionBackFrontShading->setCheckable(true); + actionBackFrontShading->setChecked(false); + viewMenu->addAction(actionBackFrontShading); if(mainviewer) setAttribute(Qt::WA_DeleteOnClose); setWindowIcon(QIcon(":/cgal/icons/resources/menu.png")); diff --git a/Polyhedron/demo/Polyhedron/Preferences.ui b/Polyhedron/demo/Polyhedron/Preferences.ui index 34613871e8d..10a7f773f85 100644 --- a/Polyhedron/demo/Polyhedron/Preferences.ui +++ b/Polyhedron/demo/Polyhedron/Preferences.ui @@ -58,9 +58,9 @@ 0 - 0 - 278 - 499 + -96 + 275 + 528 @@ -285,6 +285,13 @@ + + + + Change Back/Front Colors... + + + diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index cc5cb24d158..bfb1a2331ad 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -50,6 +50,10 @@ public: QVector4D diffuse; QVector4D specular; float spec_power; + + //Back and Front Colors + QColor front_color; + QColor back_color; // M e s s a g e s QString message; @@ -250,12 +254,23 @@ void Viewer::doBindings() specular.split(",").at(1).toFloat(), specular.split(",").at(2).toFloat(), 1.0f); - + + QString front_color = viewer_settings.value("front_color", QString("1.0,0.0,0.0")).toString(); + d->front_color= QColor(255*front_color.split(",").at(0).toFloat(), + 255*front_color.split(",").at(1).toFloat(), + 255*front_color.split(",").at(2).toFloat(), + 1.0f); + QString back_color = viewer_settings.value("back_color", QString("0.0,0.0,1.0")).toString(); + d->back_color= QColor( 255*back_color.split(",").at(0).toFloat(), + 255*back_color.split(",").at(1).toFloat(), + 255*back_color.split(",").at(2).toFloat(), + 1.0f); d->spec_power = viewer_settings.value("spec_power", 51.8).toFloat(); d->scene = 0; d->projection_is_ortho = false; d->twosides = false; this->setProperty("draw_two_sides", false); + this->setProperty("back_front_shading", false); d->macro_mode = false; d->inFastDrawing = true; d->inDrawWithNames = false; @@ -333,6 +348,7 @@ Viewer::Viewer(QWidget* parent, is_sharing = true; d->antialiasing = antialiasing; this->setProperty("draw_two_sides", false); + this->setProperty("back_front_shading", false); this->setProperty("helpText", QString("This is a sub-viewer. It displays the scene " "from another point of view. \n ")); is_ogl_4_3 = sharedWidget->is_ogl_4_3; @@ -367,6 +383,17 @@ Viewer::~Viewer() .arg(d->specular.z())); viewer_settings.setValue("spec_power", d->spec_power); + viewer_settings.setValue("front_color", + QString("%1,%2,%3") + .arg(d->front_color.redF()) + .arg(d->front_color.greenF()) + .arg(d->front_color.blueF())); + viewer_settings.setValue("back_color", + QString("%1,%2,%3") + .arg(d->back_color.redF()) + .arg(d->back_color.greenF()) + .arg(d->back_color.blueF())); + if(d->_recentFunctions) delete d->_recentFunctions; if(d->painter) @@ -401,6 +428,13 @@ void Viewer::setTwoSides(bool b) } +void Viewer::setBackFrontShading(bool b) +{ + this->setProperty("back_front_shading", b); + update(); +} + + void Viewer::setFastDrawing(bool b) { d->inFastDrawing = b; @@ -947,7 +981,10 @@ void Viewer::attribBuffers(int program_name) const { program->setUniformValue("light_spec", d->specular); program->setUniformValue("light_amb", d->ambient); program->setUniformValue("spec_power", d->spec_power); + program->setUniformValue("front_color", d->front_color); + program->setUniformValue("back_color", d->back_color); program->setUniformValue("is_two_side", d->twosides); + program->setUniformValue("back_front_shading", this->property("back_front_shading").toBool()); break; } switch(program_name) @@ -1805,6 +1842,65 @@ void Viewer::setLighting() } } +void Viewer::setBackFrontColors() +{ + + //save current settings; + + QColor prev_front_color = d->front_color; + QColor prev_back_color = d->back_color; + QDialog *dialog = new QDialog(this); + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok + | QDialogButtonBox::Cancel, dialog); + + connect(buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject); + + QGridLayout* layout = new QGridLayout(dialog); + layout->addWidget(new QLabel("Front color: ",dialog),0,0); + QPalette front_palette; + front_palette.setColor(QPalette::Button, d->front_color); + QPushButton* frontButton = new QPushButton(dialog); + frontButton->setPalette(front_palette); + QPalette back_palette; + back_palette.setColor(QPalette::Button, d->back_color); + QPushButton* backButton = new QPushButton(dialog); + backButton->setPalette(back_palette); + layout->addWidget(frontButton,0,1); + layout->addWidget(new QLabel("Back color: ",dialog),1,0); + layout->addWidget(backButton,1,1); + layout->addWidget(buttonBox); + dialog->setLayout(layout); + connect(frontButton, &QPushButton::clicked, + [this, dialog, frontButton](){ + QColorDialog *color_dial = new QColorDialog(dialog); + color_dial->exec(); + QColor front_color = color_dial->selectedColor(); + QPalette palette; + palette.setColor(QPalette::Button, front_color); + frontButton->setPalette(palette); + d->front_color= front_color; + }); + connect(backButton, &QPushButton::clicked, + [this, dialog, backButton](){ + QColorDialog *color_dial = new QColorDialog(dialog); + color_dial->exec(); + QColor back_color = color_dial->selectedColor(); + QPalette palette; + palette.setColor(QPalette::Button, back_color); + backButton->setPalette(palette); + d->back_color= back_color; + + }); + if(!dialog->exec()) + { + //restore previous settings + d->front_color= prev_front_color; + d->back_color= prev_back_color; + return; + } +} + void Viewer::setGlPointSize(const GLfloat &p) { d->gl_point_size = p; } const GLfloat& Viewer::getGlPointSize() const { return d->gl_point_size; } diff --git a/Polyhedron/demo/Polyhedron/Viewer.h b/Polyhedron/demo/Polyhedron/Viewer.h index 6d33097f672..600b9a6f041 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.h +++ b/Polyhedron/demo/Polyhedron/Viewer.h @@ -101,6 +101,7 @@ public Q_SLOTS: //! If b is true, facets will be ligted from both internal and external sides. //! If b is false, only the side that is exposed to the light source will be lighted. void setTwoSides(bool b) Q_DECL_OVERRIDE; + void setBackFrontShading(bool b) Q_DECL_OVERRIDE; void SetOrthoProjection( bool b) Q_DECL_OVERRIDE; //! If b is true, some items are displayed in a simplified version when moving the camera. //! If b is false, items display is never altered, even when moving. @@ -127,6 +128,7 @@ public Q_SLOTS: } void setLighting(); + void setBackFrontColors(); void messageLogged(QOpenGLDebugMessage); diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag index 2c0b38aa039..302fa0e6123 100644 --- a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag +++ b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag @@ -3,6 +3,8 @@ varying highp vec4 color; varying highp vec4 fP; varying highp vec3 fN; varying highp float dist[6]; +uniform highp vec4 front_color; +uniform highp vec4 back_color; uniform highp vec4 light_pos; uniform highp vec4 light_diff; uniform highp vec4 light_spec; @@ -17,6 +19,7 @@ uniform highp float width; uniform highp float height; uniform bool comparing; uniform bool writing; +uniform bool back_front_shading; uniform sampler2D sampler; uniform highp float alpha; @@ -44,7 +47,6 @@ void main(void) { gl_FragColor = vec4(d,d,d,1.0); else { - highp vec4 my_color = vec4(color.xyz, 1.0); highp vec3 L = light_pos.xyz - fP.xyz; highp vec3 V = -fP.xyz; highp vec3 N; @@ -56,6 +58,19 @@ void main(void) { V = normalize(V); highp vec3 R = reflect(-L, N); highp vec4 diffuse; + float dot_prod = dot(N,L); + highp vec4 my_color; + if(back_front_shading) + { + if (dot_prod > 0) + my_color = front_color; + else + my_color = back_color; + } + else + { + my_color = highp vec4(color.xyz, 1.0); + } if(is_two_side == 1) diffuse = abs(dot(N,L)) * light_diff * color; else diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag b/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag index 2bb3354848f..e1fbe4d1139 100644 --- a/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag +++ b/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag @@ -3,6 +3,8 @@ in vec4 color; in vec4 fP; in vec3 fN; in float dist[6]; +uniform vec4 front_color; +uniform vec4 back_color; uniform vec4 light_pos; uniform vec4 light_diff; uniform vec4 light_spec; @@ -17,6 +19,7 @@ uniform float width; uniform float height; uniform bool comparing; uniform bool writing; +uniform bool back_front_shading; uniform sampler2D sampler; uniform float alpha; out vec4 out_color; @@ -45,7 +48,6 @@ void main(void) { out_color = vec4(d,d,d,1.0); else { - vec4 my_color = vec4(color.xyz, 1.0); vec3 L = light_pos.xyz - fP.xyz; vec3 V = -fP.xyz; vec3 N; @@ -57,10 +59,24 @@ void main(void) { V = normalize(V); vec3 R = reflect(-L, N); vec4 diffuse; - if(is_two_side == 1) - diffuse = abs(dot(N,L)) * light_diff * color; + float dot_prod = dot(N,L); + vec4 my_color; + if(back_front_shading) + { + if (dot_prod > 0) + my_color = front_color; + else + my_color = back_color; + } else - diffuse = max(dot(N,L), 0.0) * light_diff * my_color; + { + my_color = vec4(color.xyz, 1.0); + } + if(is_two_side == 1) + diffuse = abs(dot_prod) * light_diff * color; + else + diffuse = max(dot_prod, 0.0) * light_diff * my_color; + vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; vec4 ret_color = vec4((my_color*light_amb).xyz + diffuse.xyz + specular.xyz,1); if(is_selected) diff --git a/Three/include/CGAL/Three/Viewer_interface.h b/Three/include/CGAL/Three/Viewer_interface.h index 26b0778098e..0a4ceea06fb 100644 --- a/Three/include/CGAL/Three/Viewer_interface.h +++ b/Three/include/CGAL/Three/Viewer_interface.h @@ -238,6 +238,9 @@ public Q_SLOTS: //! If b is true, faces will be ligted from both internal and external side. //! If b is false, only the side that is exposed to the light source will be lighted. virtual void setTwoSides(bool b) = 0; + //! If b is true, then a special color mask is applied to points and meshes to differenciate + //! front-faced and back-faced elements. + virtual void setBackFrontShading(bool b) =0; //! \brief Sets the fast drawing mode //! @see inFastDrawing() virtual void setFastDrawing(bool b) = 0;