From 9aa059a5650ad82c5b08a8f0f113e80a3804c81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20De=20Lillo?= Date: Thu, 31 Jan 2019 18:49:22 +0100 Subject: [PATCH 1/2] [nodes] Add new node `LightingEstimation` --- .../nodes/aliceVision/LightingEstimation.py | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 meshroom/nodes/aliceVision/LightingEstimation.py diff --git a/meshroom/nodes/aliceVision/LightingEstimation.py b/meshroom/nodes/aliceVision/LightingEstimation.py new file mode 100644 index 0000000000..dc5b188fb4 --- /dev/null +++ b/meshroom/nodes/aliceVision/LightingEstimation.py @@ -0,0 +1,89 @@ +__version__ = "1.0" + +from meshroom.core import desc + + +class LightingEstimation(desc.CommandLineNode): + commandLine = 'aliceVision_utils_lightingEstimation {allParams}' + + inputs = [ + desc.File( + name='input', + label='Input', + description='SfMData file.', + value='', + uid=[0], + ), + desc.File( + name="depthMapsFilterFolder", + label='Filtered Depth Maps Folder', + description='Input filtered depth maps folder', + value='', + uid=[0], + ), + desc.File( + name='imagesFolder', + label='Images Folder', + description='Use images from a specific folder instead of those specify in the SfMData file.\nFilename should be the image uid.', + value='', + uid=[0], + ), + desc.ChoiceParam( + name='lightingEstimationMode', + label='Lighting Estimation Mode', + description='Lighting Estimation Mode.', + value='global', + values=['global', 'per_image'], + exclusive=True, + uid=[0], + advanced=True, + ), + desc.ChoiceParam( + name='lightingColor', + label='Lighting Color Mode', + description='Lighting Color Mode.', + value='RGB', + values=['RGB', 'Luminance'], + exclusive=True, + uid=[0], + advanced=True, + ), + desc.ChoiceParam( + name='albedoEstimationName', + label='Albedo Estimation Name', + description='Albedo estimation method used for light estimation.', + value='constant', + values=['constant', 'picture', 'median_filter', 'blur_filter'], + exclusive=True, + uid=[0], + advanced=True, + ), + desc.IntParam( + name='albedoEstimationFilterSize', + label='Albedo Estimation Filter Size', + description='Albedo filter size for estimation method using filter.', + value=3, + range=(0, 100, 1), + uid=[0], + advanced=True, + ), + desc.ChoiceParam( + name='verboseLevel', + label='Verbose Level', + description='Verbosity level (fatal, error, warning, info, debug, trace).', + value='info', + values=['fatal', 'error', 'warning', 'info', 'debug', 'trace'], + exclusive=True, + uid=[], + ), + ] + + outputs = [ + desc.File( + name='output', + label='Output Folder', + description='Folder for output lighting vector files.', + value=desc.Node.internalFolder, + uid=[], + ), + ] From 3ae95869bd698ccfb1f6633f91fb360c54b764ca Mon Sep 17 00:00:00 2001 From: Yann Lanthony Date: Fri, 8 Feb 2019 16:31:16 +0100 Subject: [PATCH 2/2] [ui] Viewer3D: introduce SphericalHarmonics shader + display mode Add experimental render mode to display model normals or shading based on spherical harmonics coefficients --- meshroom/ui/qml/Viewer3D/MaterialSwitcher.qml | 12 ++++ .../Materials/SphericalHarmonicsEffect.qml | 36 +++++++++++ .../Materials/SphericalHarmonicsMaterial.qml | 63 +++++++++++++++++++ .../Materials/shaders/SphericalHarmonics.frag | 34 ++++++++++ .../Materials/shaders/SphericalHarmonics.vert | 16 +++++ meshroom/ui/qml/Viewer3D/Viewer3D.qml | 28 ++++++++- meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml | 6 ++ 7 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 meshroom/ui/qml/Viewer3D/Materials/SphericalHarmonicsEffect.qml create mode 100644 meshroom/ui/qml/Viewer3D/Materials/SphericalHarmonicsMaterial.qml create mode 100644 meshroom/ui/qml/Viewer3D/Materials/shaders/SphericalHarmonics.frag create mode 100644 meshroom/ui/qml/Viewer3D/Materials/shaders/SphericalHarmonics.vert diff --git a/meshroom/ui/qml/Viewer3D/MaterialSwitcher.qml b/meshroom/ui/qml/Viewer3D/MaterialSwitcher.qml index 75081e1861..06b09a3fbf 100644 --- a/meshroom/ui/qml/Viewer3D/MaterialSwitcher.qml +++ b/meshroom/ui/qml/Viewer3D/MaterialSwitcher.qml @@ -3,6 +3,7 @@ import Qt3D.Render 2.9 import Qt3D.Input 2.0 import Qt3D.Extras 2.10 import QtQuick 2.0 +import Utils 1.0 import "Materials" /** @@ -67,6 +68,10 @@ Entity { // "textured" material resolution order: diffuse map > vertex color data > no color info material: diffuseMap ? textured : (Scene3DHelper.vertexColorCount(root.parent) ? colored : solid) } + }, + State { + name: "Spherical Harmonics" + PropertyChanges { target: m; material: shMaterial } } ] } @@ -112,4 +117,11 @@ Entity { specular: root.specular } + SphericalHarmonicsMaterial { + id: shMaterial + objectName: "SphericalHarmonicsMaterial" + effect: SphericalHarmonicsEffect {} + shlSource: Filepath.stringToUrl(Viewer3DSettings.shlFile) + displayNormals: Viewer3DSettings.displayNormals + } } diff --git a/meshroom/ui/qml/Viewer3D/Materials/SphericalHarmonicsEffect.qml b/meshroom/ui/qml/Viewer3D/Materials/SphericalHarmonicsEffect.qml new file mode 100644 index 0000000000..065992c9ba --- /dev/null +++ b/meshroom/ui/qml/Viewer3D/Materials/SphericalHarmonicsEffect.qml @@ -0,0 +1,36 @@ +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 + +Effect { + id: root + + + parameters: [ + Parameter { name: "shCoeffs[0]"; value: [] }, + Parameter { name: "displayNormals"; value: false } + ] + + techniques: [ + Technique { + graphicsApiFilter { + api: GraphicsApiFilter.OpenGL + profile: GraphicsApiFilter.CoreProfile + majorVersion: 3 + minorVersion: 1 + } + + + filterKeys: [ FilterKey { name: "renderingStyle"; value: "forward" } ] + + renderPasses: [ + RenderPass { + shaderProgram: ShaderProgram { + vertexShaderCode: loadSource(Qt.resolvedUrl("shaders/SphericalHarmonics.vert")) + fragmentShaderCode: loadSource(Qt.resolvedUrl("shaders/SphericalHarmonics.frag")) + + } + } + ] + } + ] +} diff --git a/meshroom/ui/qml/Viewer3D/Materials/SphericalHarmonicsMaterial.qml b/meshroom/ui/qml/Viewer3D/Materials/SphericalHarmonicsMaterial.qml new file mode 100644 index 0000000000..8ecc07bb16 --- /dev/null +++ b/meshroom/ui/qml/Viewer3D/Materials/SphericalHarmonicsMaterial.qml @@ -0,0 +1,63 @@ +import Qt3D.Core 2.0 +import Qt3D.Render 2.0 +import Utils 1.0 + +Material { + id: root + + /// Source file containing coefficients + property url shlSource + /// Spherical Harmonics coefficients (array of 9 vector3d) + property var coefficients: noCoeffs + /// Whether to display normals instead of SH + property bool displayNormals: false + + // default coefficients (uniform magenta) + readonly property var noCoeffs: [ + Qt.vector3d(0.0, 0.0, 0.0), + Qt.vector3d(0.0, 0.0, 0.0), + Qt.vector3d(0.0, 0.0, 0.0), + Qt.vector3d(1.0, 0.0, 1.0), + Qt.vector3d(0.0, 0.0, 0.0), + Qt.vector3d(0.0, 0.0, 0.0), + Qt.vector3d(0.0, 0.0, 0.0), + Qt.vector3d(0.0, 0.0, 0.0), + Qt.vector3d(0.0, 0.0, 0.0) + ] + + effect: SphericalHarmonicsEffect {} + + onShlSourceChanged: { + if(!shlSource) { + coefficients = noCoeffs; + return; + } + Request.get(Filepath.urlToString(shlSource), function(xhr) { + if(xhr.readyState === XMLHttpRequest.DONE) { + var coeffs = []; + var lines = xhr.responseText.split("\n"); + lines.forEach(function(l){ + var lineCoeffs = []; + l.split(" ").forEach(function(v){ + if(v) { lineCoeffs.push(v); } + }) + if(lineCoeffs.length == 3) + coeffs.push(Qt.vector3d(lineCoeffs[0], lineCoeffs[1], lineCoeffs[2])); + }); + + if(coeffs.length == 9) { + coefficients = coeffs; + } + else { + console.warn("Invalid SHL file: " + shlSource + " with " + coeffs.length + " coefficients."); + coefficients = noCoeffs; + } + } + }) + } + + parameters: [ + Parameter { name: "shCoeffs[0]"; value: coefficients }, + Parameter { name: "displayNormals"; value: displayNormals } + ] +} diff --git a/meshroom/ui/qml/Viewer3D/Materials/shaders/SphericalHarmonics.frag b/meshroom/ui/qml/Viewer3D/Materials/shaders/SphericalHarmonics.frag new file mode 100644 index 0000000000..ecc5d73061 --- /dev/null +++ b/meshroom/ui/qml/Viewer3D/Materials/shaders/SphericalHarmonics.frag @@ -0,0 +1,34 @@ +#version 330 core + +in vec3 normal; +out vec4 fragColor; + +uniform vec3 shCoeffs[9]; +uniform bool displayNormals = false; + +vec3 resolveSH_Opt(vec3 premulCoefficients[9], vec3 dir) +{ + vec3 result = premulCoefficients[0] * dir.x; + result += premulCoefficients[1] * dir.y; + result += premulCoefficients[2] * dir.z; + result += premulCoefficients[3]; + vec3 dirSq = dir * dir; + result += premulCoefficients[4] * (dir.x * dir.y); + result += premulCoefficients[5] * (dir.x * dir.z); + result += premulCoefficients[6] * (dir.y * dir.z); + result += premulCoefficients[7] * (dirSq.x - dirSq.y); + result += premulCoefficients[8] * (3 * dirSq.z - 1); + return result; +} + +void main() +{ + if(displayNormals) { + // Display normals mode + fragColor = vec4(normal, 1.0); + } + else { + // Calculate the color from spherical harmonics coeffs + fragColor = vec4(resolveSH_Opt(shCoeffs, normal), 1.0); + } +} diff --git a/meshroom/ui/qml/Viewer3D/Materials/shaders/SphericalHarmonics.vert b/meshroom/ui/qml/Viewer3D/Materials/shaders/SphericalHarmonics.vert new file mode 100644 index 0000000000..79d44323de --- /dev/null +++ b/meshroom/ui/qml/Viewer3D/Materials/shaders/SphericalHarmonics.vert @@ -0,0 +1,16 @@ +#version 330 core + +in vec3 vertexPosition; +in vec3 vertexNormal; + +out vec3 normal; + +uniform mat4 modelView; +uniform mat3 modelViewNormal; +uniform mat4 mvp; + +void main() +{ + normal = vertexNormal; + gl_Position = mvp * vec4( vertexPosition, 1.0 ); +} diff --git a/meshroom/ui/qml/Viewer3D/Viewer3D.qml b/meshroom/ui/qml/Viewer3D/Viewer3D.qml index 8451fda7bc..9bb7445a86 100644 --- a/meshroom/ui/qml/Viewer3D/Viewer3D.qml +++ b/meshroom/ui/qml/Viewer3D/Viewer3D.qml @@ -77,7 +77,7 @@ FocusScope { if (event.key == Qt.Key_F) { resetCameraPosition(); } - else if(Qt.Key_1 <= event.key && event.key <= Qt.Key_3) + else if(Qt.Key_1 <= event.key && event.key < Qt.Key_1 + Viewer3DSettings.renderModes.length) { Viewer3DSettings.renderMode = event.key - Qt.Key_1; } @@ -274,8 +274,34 @@ FocusScope { } } + FloatingPane { + visible: Viewer3DSettings.renderMode == 3 + anchors.bottom: renderModesPanel.top + GridLayout { + columns: 2 + rowSpacing: 0 + + RadioButton { text: "SHL File"; autoExclusive: true; checked: true } + TextField { + text: Viewer3DSettings.shlFile + selectByMouse: true + Layout.minimumWidth: 300 + onEditingFinished: Viewer3DSettings.shlFile = text + } + + RadioButton { + Layout.columnSpan: 2 + autoExclusive: true + text: "Normals" + onCheckedChanged: Viewer3DSettings.displayNormals = checked + } + + } + } + // Rendering modes FloatingPane { + id: renderModesPanel anchors.bottom: parent.bottom padding: 4 Row { diff --git a/meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml b/meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml index c53cb5f784..aded135a0b 100644 --- a/meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml +++ b/meshroom/ui/qml/Viewer3D/Viewer3DSettings.qml @@ -26,10 +26,16 @@ Item { {"name": "Solid", "icon": MaterialIcons.crop_din }, {"name": "Wireframe", "icon": MaterialIcons.details }, {"name": "Textured", "icon": MaterialIcons.texture }, + {"name": "Spherical Harmonics", "icon": MaterialIcons.brightness_7} ] // Current render mode property int renderMode: 2 + // Spherical Harmonics file + property string shlFile: "" + // Whether to display normals + property bool displayNormals: false + // Rasterized point size property real pointSize: 1.5 // Whether point size is fixed or view dependent