mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-03 08:48:40 +02:00
[ui] Viewer3D: introduce SphericalHarmonics shader + display mode
Add experimental render mode to display model normals or shading based on spherical harmonics coefficients
This commit is contained in:
parent
9aa059a565
commit
3ae95869bd
7 changed files with 194 additions and 1 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"))
|
||||
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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 }
|
||||
]
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue