From 9f060f9135ae1510a14f84fb5edb942186ea06b1 Mon Sep 17 00:00:00 2001 From: "jun.zhang" Date: Tue, 10 Dec 2024 19:30:08 +0800 Subject: [PATCH] NEW: cherry-pick rendering-stuff to github branch jira: no-jira Change-Id: If615d572b2021e707cc9ff037fefeabf46dacfa4 --- .../shaders/{cali.fs => 110/background.fs} | 4 +- resources/shaders/110/background.vs | 8 + resources/shaders/110/flat_instance.vs | 12 +- resources/shaders/110/flat_texture.fs | 10 + resources/shaders/110/flat_texture.vs | 16 + resources/shaders/110/fxaa.fs | 78 + resources/shaders/110/fxaa.vs | 12 + resources/shaders/110/gaussian_blur33.fs | 35 + resources/shaders/110/gaussian_blur33.vs | 12 + resources/shaders/{ => 110}/gouraud.fs | 1 - resources/shaders/{ => 110}/gouraud.vs | 20 +- resources/shaders/{ => 110}/gouraud_light.fs | 0 .../{thumbnail.vs => 110/gouraud_light.vs} | 22 +- .../{ => 110}/gouraud_light_instanced.vs | 0 resources/shaders/110/hotbed.fs | 10 +- resources/shaders/110/imgui.fs | 3 + resources/shaders/110/imgui.vs | 4 + resources/shaders/110/mainframe_composite.fs | 10 + resources/shaders/110/mainframe_composite.vs | 12 + resources/shaders/{ => 110}/mm_contour.fs | 0 resources/shaders/110/mm_contour.vs | 11 + .../shaders/{ => 110}/mm_gouraud_wireframe.fs | 8 +- .../shaders/{ => 110}/mm_gouraud_wireframe.vs | 18 +- resources/shaders/110/printbed.fs | 10 +- resources/shaders/{ => 110}/thumbnail.fs | 0 resources/shaders/110/thumbnail.vs | 50 + .../shaders/{ => 110}/toolpaths_lines.fs | 0 resources/shaders/110/toolpaths_lines.vs | 16 + .../{ => 110}/variable_layer_height.fs | 0 .../{ => 110}/variable_layer_height.vs | 26 +- resources/shaders/140/background.fs | 8 + resources/shaders/140/background.vs | 8 + resources/shaders/140/flat.fs | 9 + resources/shaders/140/flat.vs | 11 + resources/shaders/140/flat_instance.vs | 19 + resources/shaders/140/flat_texture.fs | 12 + resources/shaders/140/flat_texture.vs | 16 + resources/shaders/140/fxaa.fs | 79 + resources/shaders/140/fxaa.vs | 12 + resources/shaders/140/gaussian_blur33.fs | 34 + resources/shaders/140/gaussian_blur33.vs | 12 + resources/shaders/140/gouraud.fs | 111 ++ .../{gouraud_130.vs => 140/gouraud.vs} | 50 +- resources/shaders/140/gouraud_light.fs | 14 + resources/shaders/{ => 140}/gouraud_light.vs | 21 +- .../shaders/140/gouraud_light_instanced.vs | 67 + resources/shaders/140/hotbed.fs | 52 + resources/shaders/140/hotbed.vs | 47 + resources/shaders/140/imgui.fs | 12 + resources/shaders/140/imgui.vs | 17 + resources/shaders/140/mainframe_composite.fs | 12 + resources/shaders/140/mainframe_composite.vs | 12 + resources/shaders/140/mm_contour.fs | 12 + resources/shaders/140/mm_contour.vs | 11 + .../mm_gouraud_wireframe.fs} | 50 +- resources/shaders/140/mm_gouraud_wireframe.vs | 47 + resources/shaders/140/printbed.fs | 29 + resources/shaders/140/printbed.vs | 15 + resources/shaders/140/silhouette.fs | 8 + resources/shaders/140/silhouette.vs | 11 + resources/shaders/140/silhouette_composite.fs | 41 + resources/shaders/140/silhouette_composite.vs | 12 + resources/shaders/140/thumbnail.fs | 23 + resources/shaders/140/thumbnail.vs | 50 + resources/shaders/140/toolpaths_lines.fs | 30 + resources/shaders/140/toolpaths_lines.vs | 16 + .../shaders/140/variable_layer_height.fs | 43 + .../shaders/140/variable_layer_height.vs | 60 + resources/shaders/cali.vs | 6 - resources/shaders/gouraud_130.fs | 124 -- resources/shaders/gouraud_light_instanced.fs | 12 - resources/shaders/mm_contour.vs | 6 - resources/shaders/mm_gouraud.vs | 30 - resources/shaders/options_110.fs | 8 - resources/shaders/options_110.vs | 22 - resources/shaders/options_120.fs | 22 - resources/shaders/options_120.vs | 22 - resources/shaders/outline.fs | 10 - resources/shaders/outline.vs | 12 - resources/shaders/toolpaths_lines.vs | 9 - src/BambuStudio.cpp | 7 +- src/libslic3r/AppConfig.cpp | 6 + src/libslic3r/Frustum.cpp | 92 +- src/libslic3r/Frustum.hpp | 32 +- src/slic3r/GUI/3DBed.cpp | 37 +- src/slic3r/GUI/3DScene.cpp | 190 +- src/slic3r/GUI/3DScene.hpp | 14 +- src/slic3r/GUI/Camera.cpp | 245 ++- src/slic3r/GUI/Camera.hpp | 2 +- src/slic3r/GUI/GCodeViewer.cpp | 190 +- src/slic3r/GUI/GCodeViewer.hpp | 1 - src/slic3r/GUI/GLCanvas3D.cpp | 1639 ++++++++++++----- src/slic3r/GUI/GLCanvas3D.hpp | 69 +- src/slic3r/GUI/GLModel.cpp | 189 +- src/slic3r/GUI/GLModel.hpp | 8 +- src/slic3r/GUI/GLSelectionRectangle.cpp | 96 +- src/slic3r/GUI/GLSelectionRectangle.hpp | 7 +- src/slic3r/GUI/GLShader.cpp | 18 +- src/slic3r/GUI/GLShader.hpp | 7 +- src/slic3r/GUI/GLShadersManager.cpp | 94 +- src/slic3r/GUI/GLShadersManager.hpp | 17 +- src/slic3r/GUI/GLTexture.cpp | 100 +- src/slic3r/GUI/GLTexture.hpp | 6 +- src/slic3r/GUI/GUI_App.cpp | 30 +- src/slic3r/GUI/GUI_App.hpp | 6 +- src/slic3r/GUI/GUI_Preview.cpp | 44 +- src/slic3r/GUI/GUI_Preview.hpp | 33 +- src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp | 261 ++- src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp | 4 + src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 181 +- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 11 +- src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp | 47 +- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 6 +- src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp | 22 +- src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 24 +- src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp | 51 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 77 +- src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 79 +- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 22 +- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 109 +- src/slic3r/GUI/Gizmos/GLGizmoMove.hpp | 7 + src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 551 +++--- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 23 +- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 376 ++-- src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp | 24 +- src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp | 18 +- src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 118 +- src/slic3r/GUI/Gizmos/GLGizmoScale.hpp | 11 +- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 16 +- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 36 +- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 90 +- src/slic3r/GUI/Gizmos/GLGizmoText.cpp | 23 +- src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 18 +- src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 1 + src/slic3r/GUI/ImGuiWrapper.cpp | 65 +- src/slic3r/GUI/MeshUtils.cpp | 37 +- src/slic3r/GUI/OpenGLManager.cpp | 589 +++++- src/slic3r/GUI/OpenGLManager.hpp | 94 +- src/slic3r/GUI/PartPlate.cpp | 74 +- src/slic3r/GUI/Plater.cpp | 11 + src/slic3r/GUI/Plater.hpp | 2 + src/slic3r/GUI/Selection.cpp | 361 ++-- src/slic3r/GUI/Selection.hpp | 13 +- src/slic3r/Utils/CalibUtils.cpp | 2 +- 145 files changed, 5755 insertions(+), 2664 deletions(-) rename resources/shaders/{cali.fs => 110/background.fs} (95%) create mode 100644 resources/shaders/110/background.vs create mode 100644 resources/shaders/110/flat_texture.fs create mode 100644 resources/shaders/110/flat_texture.vs create mode 100644 resources/shaders/110/fxaa.fs create mode 100644 resources/shaders/110/fxaa.vs create mode 100644 resources/shaders/110/gaussian_blur33.fs create mode 100644 resources/shaders/110/gaussian_blur33.vs rename resources/shaders/{ => 110}/gouraud.fs (99%) rename resources/shaders/{ => 110}/gouraud.vs (84%) rename resources/shaders/{ => 110}/gouraud_light.fs (100%) rename resources/shaders/{thumbnail.vs => 110/gouraud_light.vs} (77%) rename resources/shaders/{ => 110}/gouraud_light_instanced.vs (100%) create mode 100644 resources/shaders/110/mainframe_composite.fs create mode 100644 resources/shaders/110/mainframe_composite.vs rename resources/shaders/{ => 110}/mm_contour.fs (100%) create mode 100644 resources/shaders/110/mm_contour.vs rename resources/shaders/{ => 110}/mm_gouraud_wireframe.fs (94%) rename resources/shaders/{ => 110}/mm_gouraud_wireframe.vs (76%) rename resources/shaders/{ => 110}/thumbnail.fs (100%) create mode 100644 resources/shaders/110/thumbnail.vs rename resources/shaders/{ => 110}/toolpaths_lines.fs (100%) create mode 100644 resources/shaders/110/toolpaths_lines.vs rename resources/shaders/{ => 110}/variable_layer_height.fs (100%) rename resources/shaders/{ => 110}/variable_layer_height.vs (74%) create mode 100644 resources/shaders/140/background.fs create mode 100644 resources/shaders/140/background.vs create mode 100644 resources/shaders/140/flat.fs create mode 100644 resources/shaders/140/flat.vs create mode 100644 resources/shaders/140/flat_instance.vs create mode 100644 resources/shaders/140/flat_texture.fs create mode 100644 resources/shaders/140/flat_texture.vs create mode 100644 resources/shaders/140/fxaa.fs create mode 100644 resources/shaders/140/fxaa.vs create mode 100644 resources/shaders/140/gaussian_blur33.fs create mode 100644 resources/shaders/140/gaussian_blur33.vs create mode 100644 resources/shaders/140/gouraud.fs rename resources/shaders/{gouraud_130.vs => 140/gouraud.vs} (71%) create mode 100644 resources/shaders/140/gouraud_light.fs rename resources/shaders/{ => 140}/gouraud_light.vs (76%) create mode 100644 resources/shaders/140/gouraud_light_instanced.vs create mode 100644 resources/shaders/140/hotbed.fs create mode 100644 resources/shaders/140/hotbed.vs create mode 100644 resources/shaders/140/imgui.fs create mode 100644 resources/shaders/140/imgui.vs create mode 100644 resources/shaders/140/mainframe_composite.fs create mode 100644 resources/shaders/140/mainframe_composite.vs create mode 100644 resources/shaders/140/mm_contour.fs create mode 100644 resources/shaders/140/mm_contour.vs rename resources/shaders/{mm_gouraud.fs => 140/mm_gouraud_wireframe.fs} (65%) create mode 100644 resources/shaders/140/mm_gouraud_wireframe.vs create mode 100644 resources/shaders/140/printbed.fs create mode 100644 resources/shaders/140/printbed.vs create mode 100644 resources/shaders/140/silhouette.fs create mode 100644 resources/shaders/140/silhouette.vs create mode 100644 resources/shaders/140/silhouette_composite.fs create mode 100644 resources/shaders/140/silhouette_composite.vs create mode 100644 resources/shaders/140/thumbnail.fs create mode 100644 resources/shaders/140/thumbnail.vs create mode 100644 resources/shaders/140/toolpaths_lines.fs create mode 100644 resources/shaders/140/toolpaths_lines.vs create mode 100644 resources/shaders/140/variable_layer_height.fs create mode 100644 resources/shaders/140/variable_layer_height.vs delete mode 100644 resources/shaders/cali.vs delete mode 100644 resources/shaders/gouraud_130.fs delete mode 100644 resources/shaders/gouraud_light_instanced.fs delete mode 100644 resources/shaders/mm_contour.vs delete mode 100644 resources/shaders/mm_gouraud.vs delete mode 100644 resources/shaders/options_110.fs delete mode 100644 resources/shaders/options_110.vs delete mode 100644 resources/shaders/options_120.fs delete mode 100644 resources/shaders/options_120.vs delete mode 100644 resources/shaders/outline.fs delete mode 100644 resources/shaders/outline.vs delete mode 100644 resources/shaders/toolpaths_lines.vs diff --git a/resources/shaders/cali.fs b/resources/shaders/110/background.fs similarity index 95% rename from resources/shaders/cali.fs rename to resources/shaders/110/background.fs index ab656998d..1f86a2be4 100644 --- a/resources/shaders/cali.fs +++ b/resources/shaders/110/background.fs @@ -1,8 +1,6 @@ #version 110 - uniform vec4 uniform_color; - void main() { gl_FragColor = uniform_color; -} +} \ No newline at end of file diff --git a/resources/shaders/110/background.vs b/resources/shaders/110/background.vs new file mode 100644 index 000000000..f30460dfa --- /dev/null +++ b/resources/shaders/110/background.vs @@ -0,0 +1,8 @@ +#version 110 + +attribute vec3 v_position; + +void main() +{ + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/110/flat_instance.vs b/resources/shaders/110/flat_instance.vs index e0662e99b..6655da50a 100644 --- a/resources/shaders/110/flat_instance.vs +++ b/resources/shaders/110/flat_instance.vs @@ -4,9 +4,15 @@ uniform mat4 view_matrix; uniform mat4 projection_matrix; attribute vec3 v_position; -attribute vec2 v_undefine; -attribute mat4 instanceMatrix; +// per instance data +// in mat4 instanceMatrix; +attribute vec4 i_data0; +attribute vec4 i_data1; +attribute vec4 i_data2; +attribute vec4 i_data3; +// end per instance data void main() { - gl_Position = projection_matrix * view_matrix * instanceMatrix * vec4(v_position, 1.0); + mat4 model_matrix = mat4(i_data0, i_data1, i_data2, i_data3); + gl_Position = projection_matrix * view_matrix * model_matrix * vec4(v_position, 1.0); } diff --git a/resources/shaders/110/flat_texture.fs b/resources/shaders/110/flat_texture.fs new file mode 100644 index 000000000..d4676d7ed --- /dev/null +++ b/resources/shaders/110/flat_texture.fs @@ -0,0 +1,10 @@ +#version 110 + +uniform sampler2D u_texture; + +varying vec2 v_texcoord; + +void main() +{ + gl_FragColor = texture2D(u_texture, v_texcoord); +} diff --git a/resources/shaders/110/flat_texture.vs b/resources/shaders/110/flat_texture.vs new file mode 100644 index 000000000..40b7c14d5 --- /dev/null +++ b/resources/shaders/110/flat_texture.vs @@ -0,0 +1,16 @@ +#version 110 + +attribute vec3 v_position; +attribute vec2 v_tex_coord; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 u_uvTransformMatrix; + +varying vec2 v_texcoord; + +void main() +{ + v_texcoord = (u_uvTransformMatrix * vec3(v_tex_coord, 1.0)).xy; + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/110/fxaa.fs b/resources/shaders/110/fxaa.fs new file mode 100644 index 000000000..f718f2088 --- /dev/null +++ b/resources/shaders/110/fxaa.fs @@ -0,0 +1,78 @@ +#version 110 + +uniform vec4 u_viewport_size; +uniform sampler2D u_sampler; + +varying vec2 tex_coords; + +// thanks https://github.com/mattdesl/glsl-fxaa +#ifndef FXAA_REDUCE_MIN + #define FXAA_REDUCE_MIN (1.0/ 128.0) +#endif +#ifndef FXAA_REDUCE_MUL + #define FXAA_REDUCE_MUL (1.0 / 8.0) +#endif +#ifndef FXAA_SPAN_MAX + #define FXAA_SPAN_MAX 8.0 +#endif + +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 inv_resolution, + vec2 v_rgbNW, vec2 v_rgbNE, + vec2 v_rgbSW, vec2 v_rgbSE, + vec2 v_rgbM) { + vec4 color; + vec2 inverseVP = inv_resolution; + vec3 rgbNW = texture2D(tex, v_rgbNW).xyz; + vec3 rgbNE = texture2D(tex, v_rgbNE).xyz; + vec3 rgbSW = texture2D(tex, v_rgbSW).xyz; + vec3 rgbSE = texture2D(tex, v_rgbSE).xyz; + vec4 texColor = texture2D(tex, v_rgbM); + vec3 rgbM = texColor.xyz; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * inverseVP; + + vec3 rgbA = 0.5 * ( + texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + + texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color = vec4(rgbA, texColor.a); + else + color = vec4(rgbB, texColor.a); + return color; +} + +void main() +{ + vec2 fragCoord = tex_coords * u_viewport_size.xy; + vec2 add = u_viewport_size.zw; + + vec2 rgbNW = tex_coords+vec2(-add.x, -add.y); + vec2 rgbNE = tex_coords+vec2( add.x, -add.y); + vec2 rgbSW = tex_coords+vec2(-add.x, add.y); + vec2 rgbSE = tex_coords+vec2( add.x, add.y); + vec2 rgbM = tex_coords; + gl_FragColor = fxaa(u_sampler, fragCoord, u_viewport_size.zw, rgbNW, rgbNE, rgbSW, rgbSE, rgbM); +} \ No newline at end of file diff --git a/resources/shaders/110/fxaa.vs b/resources/shaders/110/fxaa.vs new file mode 100644 index 000000000..7561fcc34 --- /dev/null +++ b/resources/shaders/110/fxaa.vs @@ -0,0 +1,12 @@ +#version 110 + +attribute vec3 v_position; +attribute vec2 v_tex_coord; + +varying vec2 tex_coords; + +void main() +{ + tex_coords = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/110/gaussian_blur33.fs b/resources/shaders/110/gaussian_blur33.fs new file mode 100644 index 000000000..d9c1157d9 --- /dev/null +++ b/resources/shaders/110/gaussian_blur33.fs @@ -0,0 +1,35 @@ +#version 110 +uniform sampler2D u_sampler; +uniform mat3 u_convolution_matrix; +uniform vec2 u_viewport_size; + +varying vec2 tex_coords; + +vec4 sample(float offsetX, float offsetY) +{ + return texture2D(u_sampler, vec2(tex_coords.x + offsetX, tex_coords.y + offsetY)); +} +void main() +{ + vec4 pixels[9]; + float deltaWidth = 1.0 / u_viewport_size.x; + float deltaHeight = 1.0 / u_viewport_size.y; + pixels[0] = sample(-deltaWidth, deltaHeight ); + pixels[1] = sample(0.0, deltaHeight ); + pixels[2] = sample(deltaWidth, deltaHeight ); + pixels[3] = sample(-deltaWidth, 0.0); + pixels[4] = sample(0.0, 0.0); + pixels[5] = sample(deltaWidth, 0.0); + pixels[6] = sample(-deltaWidth, -deltaHeight); + pixels[7] = sample(0.0, -deltaHeight); + pixels[8] = sample(deltaWidth, -deltaHeight); + vec4 accumulator = vec4(0.0); + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; ++j) + { + accumulator += pixels[3 * i + j] * u_convolution_matrix[i][j]; + } + } + gl_FragColor = accumulator; +} \ No newline at end of file diff --git a/resources/shaders/110/gaussian_blur33.vs b/resources/shaders/110/gaussian_blur33.vs new file mode 100644 index 000000000..7561fcc34 --- /dev/null +++ b/resources/shaders/110/gaussian_blur33.vs @@ -0,0 +1,12 @@ +#version 110 + +attribute vec3 v_position; +attribute vec2 v_tex_coord; + +varying vec2 tex_coords; + +void main() +{ + tex_coords = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/gouraud.fs b/resources/shaders/110/gouraud.fs similarity index 99% rename from resources/shaders/gouraud.fs rename to resources/shaders/110/gouraud.fs index 5004daf06..e12f8b875 100644 --- a/resources/shaders/gouraud.fs +++ b/resources/shaders/110/gouraud.fs @@ -49,7 +49,6 @@ varying vec2 intensity; uniform PrintVolumeDetection print_volume; uniform vec3 extruder_printable_heights; -varying vec4 model_pos; varying vec4 world_pos; varying float world_normal_z; varying vec3 eye_normal; diff --git a/resources/shaders/gouraud.vs b/resources/shaders/110/gouraud.vs similarity index 84% rename from resources/shaders/gouraud.vs rename to resources/shaders/110/gouraud.vs index cf7c75d5e..cb9b918d7 100644 --- a/resources/shaders/gouraud.vs +++ b/resources/shaders/110/gouraud.vs @@ -27,6 +27,13 @@ struct SlopeDetection mat3 volume_world_normal_matrix; }; +attribute vec3 v_position; +attribute vec3 v_normal; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + uniform mat4 volume_world_matrix; uniform SlopeDetection slope; @@ -48,15 +55,15 @@ varying vec3 eye_normal; void main() { // First transform the normal into camera space and normalize the result. - eye_normal = normalize(gl_NormalMatrix * gl_Normal); + eye_normal = normalize(normal_matrix * v_normal); // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz; - intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); + vec4 position = (view_model_matrix * vec4(v_position, 1.0)); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular applied). NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); @@ -66,14 +73,13 @@ void main() NdotL = max(dot(eye_normal, LIGHT_BACK_DIR), 0.0); intensity.x += NdotL * LIGHT_BACK_DIFFUSE; } - model_pos = gl_Vertex; // Point in homogenous coordinates. - world_pos = volume_world_matrix * gl_Vertex; + world_pos = volume_world_matrix * vec4(v_position, 1.0); // z component of normal vector in world coordinate used for slope shading - world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * gl_Normal)).z : 0.0; + world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0; - gl_Position = ftransform(); + gl_Position = projection_matrix * position; // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); } diff --git a/resources/shaders/gouraud_light.fs b/resources/shaders/110/gouraud_light.fs similarity index 100% rename from resources/shaders/gouraud_light.fs rename to resources/shaders/110/gouraud_light.fs diff --git a/resources/shaders/thumbnail.vs b/resources/shaders/110/gouraud_light.vs similarity index 77% rename from resources/shaders/thumbnail.vs rename to resources/shaders/110/gouraud_light.vs index a02248f28..fffd1b302 100644 --- a/resources/shaders/thumbnail.vs +++ b/resources/shaders/110/gouraud_light.vs @@ -14,30 +14,32 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 -uniform mat4 volume_world_matrix; +attribute vec3 v_position; +attribute vec3 v_normal; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + // x = tainted, y = specular; varying vec2 intensity; -varying vec4 world_pos; void main() { // First transform the normal into camera space and normalize the result. - vec3 normal = normalize(gl_NormalMatrix * gl_Normal); - + vec3 normal = normalize(normal_matrix * v_normal); + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz; - intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular applied). NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; - // Point in homogenous coordinates. - world_pos = volume_world_matrix * gl_Vertex; - - gl_Position = ftransform(); + gl_Position = projection_matrix * position; } diff --git a/resources/shaders/gouraud_light_instanced.vs b/resources/shaders/110/gouraud_light_instanced.vs similarity index 100% rename from resources/shaders/gouraud_light_instanced.vs rename to resources/shaders/110/gouraud_light_instanced.vs diff --git a/resources/shaders/110/hotbed.fs b/resources/shaders/110/hotbed.fs index d985865b8..6d8bb6983 100644 --- a/resources/shaders/110/hotbed.fs +++ b/resources/shaders/110/hotbed.fs @@ -2,6 +2,7 @@ const vec3 ZERO = vec3(0.0, 0.0, 0.0); const vec3 WHITE = vec3(1.0, 1.0, 1.0); +const float ONE_OVER_EPSILON = 1e4; struct PrintVolumeDetection { // 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid @@ -31,13 +32,20 @@ void main() if (print_volume.type == 0) {// rectangle pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); + + pv_check_min = pv_check_min * ONE_OVER_EPSILON; + pv_check_max = pv_check_max * ONE_OVER_EPSILON; + color = (any(lessThan(pv_check_min, vec3(1.0))) || any(greaterThan(pv_check_max, vec3(1.0)))) ? mix(color, WHITE, 0.3333) : color; } else if (print_volume.type == 1) {// circle float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); + + pv_check_min = pv_check_min * ONE_OVER_EPSILON; + pv_check_max = pv_check_max * ONE_OVER_EPSILON; + color = (any(lessThan(pv_check_min, vec3(1.0))) || any(greaterThan(pv_check_max, vec3(1.0)))) ? mix(color, WHITE, 0.3333) : color; } - color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, WHITE, 0.3333) : color; //gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); gl_FragColor = vec4(vec3(intensity.y) + color * (intensity.x + emission_factor), alpha); } \ No newline at end of file diff --git a/resources/shaders/110/imgui.fs b/resources/shaders/110/imgui.fs index 94a113344..e711b69e3 100644 --- a/resources/shaders/110/imgui.fs +++ b/resources/shaders/110/imgui.fs @@ -1,7 +1,10 @@ #version 110 + uniform sampler2D Texture; + varying vec2 Frag_UV; varying vec4 color; + void main() { gl_FragColor = color * texture2D(Texture, Frag_UV.st); diff --git a/resources/shaders/110/imgui.vs b/resources/shaders/110/imgui.vs index b03b0304f..66b005bc0 100644 --- a/resources/shaders/110/imgui.vs +++ b/resources/shaders/110/imgui.vs @@ -1,10 +1,14 @@ #version 110 + uniform mat4 ProjMtx; + attribute vec2 Position; attribute vec2 UV; attribute vec4 Color; + varying vec2 Frag_UV; varying vec4 color; + void main() { Frag_UV = UV; diff --git a/resources/shaders/110/mainframe_composite.fs b/resources/shaders/110/mainframe_composite.fs new file mode 100644 index 000000000..a3bba9844 --- /dev/null +++ b/resources/shaders/110/mainframe_composite.fs @@ -0,0 +1,10 @@ +#version 110 + +uniform sampler2D u_sampler; + +varying vec2 tex_coords; + +void main() +{ + gl_FragColor = texture2D(u_sampler, tex_coords); +} \ No newline at end of file diff --git a/resources/shaders/110/mainframe_composite.vs b/resources/shaders/110/mainframe_composite.vs new file mode 100644 index 000000000..7561fcc34 --- /dev/null +++ b/resources/shaders/110/mainframe_composite.vs @@ -0,0 +1,12 @@ +#version 110 + +attribute vec3 v_position; +attribute vec2 v_tex_coord; + +varying vec2 tex_coords; + +void main() +{ + tex_coords = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/mm_contour.fs b/resources/shaders/110/mm_contour.fs similarity index 100% rename from resources/shaders/mm_contour.fs rename to resources/shaders/110/mm_contour.fs diff --git a/resources/shaders/110/mm_contour.vs b/resources/shaders/110/mm_contour.vs new file mode 100644 index 000000000..d9063f0c7 --- /dev/null +++ b/resources/shaders/110/mm_contour.vs @@ -0,0 +1,11 @@ +#version 110 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +attribute vec3 v_position; + +void main() +{ + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/mm_gouraud_wireframe.fs b/resources/shaders/110/mm_gouraud_wireframe.fs similarity index 94% rename from resources/shaders/mm_gouraud_wireframe.fs rename to resources/shaders/110/mm_gouraud_wireframe.fs index 3c35ea051..ea8f0ce7e 100644 --- a/resources/shaders/mm_gouraud_wireframe.fs +++ b/resources/shaders/110/mm_gouraud_wireframe.fs @@ -24,7 +24,7 @@ const vec3 LightBlue = vec3(0.73, 1.0, 1.0); uniform vec4 uniform_color; varying vec3 clipping_planes_dots; -varying vec4 model_pos; +varying vec3 model_pos; varying vec4 world_pos; uniform bool volume_mirrored; @@ -57,6 +57,8 @@ vec3 getWireframeColor(vec3 fill) { return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988); } uniform bool show_wireframe; +uniform mat4 view_model_matrix; +uniform mat3 normal_matrix; void main() { @@ -86,7 +88,7 @@ void main() } // First transform the normal into camera space and normalize the result. - vec3 eye_normal = normalize(gl_NormalMatrix * triangle_normal); + vec3 eye_normal = normalize(normal_matrix * triangle_normal); // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. @@ -95,7 +97,7 @@ void main() // x = diffuse, y = specular; vec2 intensity = vec2(0.0, 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec3 position = (gl_ModelViewMatrix * model_pos).xyz; + vec3 position = (view_model_matrix * vec4(model_pos, 1.0)).xyz; intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular applied). diff --git a/resources/shaders/mm_gouraud_wireframe.vs b/resources/shaders/110/mm_gouraud_wireframe.vs similarity index 76% rename from resources/shaders/mm_gouraud_wireframe.vs rename to resources/shaders/110/mm_gouraud_wireframe.vs index 51dfe1b5f..f31f3fd5d 100644 --- a/resources/shaders/mm_gouraud_wireframe.vs +++ b/resources/shaders/110/mm_gouraud_wireframe.vs @@ -2,17 +2,19 @@ const vec3 ZERO = vec3(0.0, 0.0, 0.0); -//attribute vec3 v_position; -//attribute vec3 v_barycentric; - +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; uniform mat4 volume_world_matrix; // Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. uniform vec2 z_range; // Clipping plane - general orientation. Used by the SLA gizmo. uniform vec4 clipping_plane; +attribute vec3 v_position; +attribute vec3 v_color; + varying vec3 clipping_planes_dots; -varying vec4 model_pos; +varying vec3 model_pos; varying vec4 world_pos; varying vec3 barycentric_coordinates; @@ -25,12 +27,12 @@ struct SlopeDetection uniform SlopeDetection slope; void main() { - model_pos = gl_Vertex; + model_pos = v_position; //model_pos = vec4(v_position, 1.0); // Point in homogenous coordinates. - world_pos = volume_world_matrix * model_pos; + world_pos = volume_world_matrix * vec4(model_pos, 1.0); - gl_Position = ftransform(); + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); //gl_Position = gl_ModelViewProjectionMatrix * vec4(v_position, 1.0); // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); @@ -38,5 +40,5 @@ void main() //compute the Barycentric Coordinates //int vertexMod3 = gl_VertexID % 3; //barycentric_coordinates = vec3(float(vertexMod3 == 0), float(vertexMod3 == 1), float(vertexMod3 == 2)); - barycentric_coordinates = gl_Color.xyz;//v_barycentric + barycentric_coordinates = v_color.xyz; } diff --git a/resources/shaders/110/printbed.fs b/resources/shaders/110/printbed.fs index b9a284291..cc272a8bf 100644 --- a/resources/shaders/110/printbed.fs +++ b/resources/shaders/110/printbed.fs @@ -3,7 +3,7 @@ const vec3 back_color_dark = vec3(0.235, 0.235, 0.235); const vec3 back_color_light = vec3(0.365, 0.365, 0.365); -uniform sampler2D texture; +uniform sampler2D u_sampler; uniform bool transparent_background; uniform bool svg_source; @@ -11,8 +11,8 @@ varying vec2 tex_coord; vec4 svg_color(vec2 uv) { - // takes foreground from texture - vec4 fore_color = texture2D(texture, uv); + // takes foreground from u_sampler + vec4 fore_color = texture2D(u_sampler, uv); // calculates radial gradient vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(uv) - vec2(0.5))))); @@ -23,8 +23,8 @@ vec4 svg_color(vec2 uv) vec4 non_svg_color(vec2 uv) { - // takes foreground from texture - vec4 color = texture2D(texture, uv); + // takes foreground from u_sampler + vec4 color = texture2D(u_sampler, uv); return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); } diff --git a/resources/shaders/thumbnail.fs b/resources/shaders/110/thumbnail.fs similarity index 100% rename from resources/shaders/thumbnail.fs rename to resources/shaders/110/thumbnail.fs diff --git a/resources/shaders/110/thumbnail.vs b/resources/shaders/110/thumbnail.vs new file mode 100644 index 000000000..682d4c496 --- /dev/null +++ b/resources/shaders/110/thumbnail.vs @@ -0,0 +1,50 @@ +#version 110 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +attribute vec3 v_position; +attribute vec3 v_normal; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +uniform mat4 volume_world_matrix; +// x = tainted, y = specular; +varying vec2 intensity; +varying vec4 world_pos; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 normal = normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 position = (view_model_matrix * vec4(v_position, 1.0)); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + // Point in homogenous coordinates. + world_pos = volume_world_matrix * vec4(v_position, 1.0); + + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/toolpaths_lines.fs b/resources/shaders/110/toolpaths_lines.fs similarity index 100% rename from resources/shaders/toolpaths_lines.fs rename to resources/shaders/110/toolpaths_lines.fs diff --git a/resources/shaders/110/toolpaths_lines.vs b/resources/shaders/110/toolpaths_lines.vs new file mode 100644 index 000000000..f4a6817a0 --- /dev/null +++ b/resources/shaders/110/toolpaths_lines.vs @@ -0,0 +1,16 @@ +#version 110 + +attribute vec3 v_position; +attribute vec3 v_normal; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +varying vec3 eye_normal; + +void main() +{ + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); + eye_normal = normal_matrix * v_normal; +} diff --git a/resources/shaders/variable_layer_height.fs b/resources/shaders/110/variable_layer_height.fs similarity index 100% rename from resources/shaders/variable_layer_height.fs rename to resources/shaders/110/variable_layer_height.fs diff --git a/resources/shaders/variable_layer_height.vs b/resources/shaders/110/variable_layer_height.vs similarity index 74% rename from resources/shaders/variable_layer_height.vs rename to resources/shaders/110/variable_layer_height.vs index 0e966b081..3a25f9fb1 100644 --- a/resources/shaders/variable_layer_height.vs +++ b/resources/shaders/110/variable_layer_height.vs @@ -14,6 +14,14 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 +attribute vec3 v_position; +attribute vec3 v_normal; +attribute vec2 v_tex_coord; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + uniform mat4 volume_world_matrix; uniform float object_max_z; @@ -25,28 +33,28 @@ varying float object_z; void main() { // First transform the normal into camera space and normalize the result. - vec3 normal = normalize(gl_NormalMatrix * gl_Normal); - + vec3 normal = normalize(normal_matrix * v_normal); + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz; - intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular) NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); - + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; // Scaled to widths of the Z texture. if (object_max_z > 0.0) // when rendering the overlay - object_z = object_max_z * gl_MultiTexCoord0.y; + object_z = object_max_z * v_tex_coord.y; else // when rendering the volumes - object_z = (volume_world_matrix * gl_Vertex).z; - - gl_Position = ftransform(); + object_z = (volume_world_matrix * vec4(v_position, 1.0)).z; + + gl_Position = projection_matrix * position; } diff --git a/resources/shaders/140/background.fs b/resources/shaders/140/background.fs new file mode 100644 index 000000000..d96035bbe --- /dev/null +++ b/resources/shaders/140/background.fs @@ -0,0 +1,8 @@ +#version 140 +uniform vec4 uniform_color; + +out vec4 frag_color; +void main() +{ + frag_color = uniform_color; +} \ No newline at end of file diff --git a/resources/shaders/140/background.vs b/resources/shaders/140/background.vs new file mode 100644 index 000000000..f50595969 --- /dev/null +++ b/resources/shaders/140/background.vs @@ -0,0 +1,8 @@ +#version 140 + +in vec3 v_position; + +void main() +{ + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/140/flat.fs b/resources/shaders/140/flat.fs new file mode 100644 index 000000000..806129e9f --- /dev/null +++ b/resources/shaders/140/flat.fs @@ -0,0 +1,9 @@ +#version 140 + +uniform vec4 uniform_color; + +out vec4 frag_color; +void main() +{ + frag_color = uniform_color; +} diff --git a/resources/shaders/140/flat.vs b/resources/shaders/140/flat.vs new file mode 100644 index 000000000..7042671de --- /dev/null +++ b/resources/shaders/140/flat.vs @@ -0,0 +1,11 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; + +void main() +{ + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/flat_instance.vs b/resources/shaders/140/flat_instance.vs new file mode 100644 index 000000000..1b517d0c3 --- /dev/null +++ b/resources/shaders/140/flat_instance.vs @@ -0,0 +1,19 @@ +#version 140 + +uniform mat4 view_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; + +// per instance data +// in mat4 instanceMatrix; +in vec4 i_data0; +in vec4 i_data1; +in vec4 i_data2; +in vec4 i_data3; +// end per instance data +void main() +{ + mat4 model_matrix = mat4(i_data0, i_data1, i_data2, i_data3); + gl_Position = projection_matrix * view_matrix * model_matrix* vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/flat_texture.fs b/resources/shaders/140/flat_texture.fs new file mode 100644 index 000000000..61fe5e6b3 --- /dev/null +++ b/resources/shaders/140/flat_texture.fs @@ -0,0 +1,12 @@ +#version 140 + +uniform sampler2D u_texture; + +in vec2 v_texcoord; + +out vec4 frag_color; + +void main() +{ + frag_color = texture(u_texture, v_texcoord); +} diff --git a/resources/shaders/140/flat_texture.vs b/resources/shaders/140/flat_texture.vs new file mode 100644 index 000000000..581b16bf2 --- /dev/null +++ b/resources/shaders/140/flat_texture.vs @@ -0,0 +1,16 @@ +#version 140 + +in vec3 v_position; +in vec2 v_tex_coord; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 u_uvTransformMatrix; + +out vec2 v_texcoord; + +void main() +{ + v_texcoord = (u_uvTransformMatrix * vec3(v_tex_coord, 1.0)).xy; + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/140/fxaa.fs b/resources/shaders/140/fxaa.fs new file mode 100644 index 000000000..114558ce4 --- /dev/null +++ b/resources/shaders/140/fxaa.fs @@ -0,0 +1,79 @@ +#version 140 + +uniform vec4 u_viewport_size; +uniform sampler2D u_sampler; + +in vec2 tex_coords; +out vec4 frag_color; + +// thanks https://github.com/mattdesl/glsl-fxaa +#ifndef FXAA_REDUCE_MIN + #define FXAA_REDUCE_MIN (1.0/ 128.0) +#endif +#ifndef FXAA_REDUCE_MUL + #define FXAA_REDUCE_MUL (1.0 / 8.0) +#endif +#ifndef FXAA_SPAN_MAX + #define FXAA_SPAN_MAX 8.0 +#endif + +vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 inv_resolution, + vec2 v_rgbNW, vec2 v_rgbNE, + vec2 v_rgbSW, vec2 v_rgbSE, + vec2 v_rgbM) { + vec4 color; + vec2 inverseVP = inv_resolution; + vec3 rgbNW = texture(tex, v_rgbNW).xyz; + vec3 rgbNE = texture(tex, v_rgbNE).xyz; + vec3 rgbSW = texture(tex, v_rgbSW).xyz; + vec3 rgbSE = texture(tex, v_rgbSE).xyz; + vec4 texColor = texture(tex, v_rgbM); + vec3 rgbM = texColor.xyz; + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * + (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), + dir * rcpDirMin)) * inverseVP; + + vec3 rgbA = 0.5 * ( + texture(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + + texture(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * ( + texture(tex, fragCoord * inverseVP + dir * -0.5).xyz + + texture(tex, fragCoord * inverseVP + dir * 0.5).xyz); + + float lumaB = dot(rgbB, luma); + if ((lumaB < lumaMin) || (lumaB > lumaMax)) + color = vec4(rgbA, texColor.a); + else + color = vec4(rgbB, texColor.a); + return color; +} + +void main() +{ + vec2 fragCoord = tex_coords * u_viewport_size.xy; + vec2 add = u_viewport_size.zw; + + vec2 rgbNW = tex_coords+vec2(-add.x, -add.y); + vec2 rgbNE = tex_coords+vec2( add.x, -add.y); + vec2 rgbSW = tex_coords+vec2(-add.x, add.y); + vec2 rgbSE = tex_coords+vec2( add.x, add.y); + vec2 rgbM = tex_coords; + frag_color = fxaa(u_sampler, fragCoord, add, rgbNW, rgbNE, rgbSW, rgbSE, rgbM); +} \ No newline at end of file diff --git a/resources/shaders/140/fxaa.vs b/resources/shaders/140/fxaa.vs new file mode 100644 index 000000000..9c6a90120 --- /dev/null +++ b/resources/shaders/140/fxaa.vs @@ -0,0 +1,12 @@ +#version 140 + +in vec3 v_position; +in vec2 v_tex_coord; + +out vec2 tex_coords; + +void main() +{ + tex_coords = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/140/gaussian_blur33.fs b/resources/shaders/140/gaussian_blur33.fs new file mode 100644 index 000000000..314816012 --- /dev/null +++ b/resources/shaders/140/gaussian_blur33.fs @@ -0,0 +1,34 @@ +#version 140 +uniform sampler2D u_sampler; +uniform mat3 u_convolution_matrix; +uniform vec2 u_viewport_size; + +in vec2 tex_coords; + +out vec4 frag_color; + +vec4 sample(float offsetX, float offsetY) +{ + return texture(u_sampler, vec2(tex_coords.x + offsetX, tex_coords.y + offsetY)); +} +void main() +{ + vec4 pixels[9]; + float deltaWidth = 1.0 / u_viewport_size.x; + float deltaHeight = 1.0 / u_viewport_size.y; + pixels[0] = sample(-deltaWidth, deltaHeight ); + pixels[1] = sample(0.0, deltaHeight ); + pixels[2] = sample(deltaWidth, deltaHeight ); + pixels[3] = sample(-deltaWidth, 0.0); + pixels[4] = sample(0.0, 0.0); + pixels[5] = sample(deltaWidth, 0.0); + pixels[6] = sample(-deltaWidth, -deltaHeight); + pixels[7] = sample(0.0, -deltaHeight); + pixels[8] = sample(deltaWidth, -deltaHeight); + vec4 accumulator = vec4(0.0); + for (int i = 0; i < 9; ++i) + { + accumulator += pixels[i] * u_convolution_matrix[i / 3][i % 3]; + } + frag_color = accumulator; +} \ No newline at end of file diff --git a/resources/shaders/140/gaussian_blur33.vs b/resources/shaders/140/gaussian_blur33.vs new file mode 100644 index 000000000..9c6a90120 --- /dev/null +++ b/resources/shaders/140/gaussian_blur33.vs @@ -0,0 +1,12 @@ +#version 140 + +in vec3 v_position; +in vec2 v_tex_coord; + +out vec2 tex_coords; + +void main() +{ + tex_coords = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs new file mode 100644 index 000000000..86b61f6af --- /dev/null +++ b/resources/shaders/140/gouraud.fs @@ -0,0 +1,111 @@ +#version 140 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); +//BBS: add grey and orange +//const vec3 GREY = vec3(0.9, 0.9, 0.9); +const vec3 ORANGE = vec3(0.8, 0.4, 0.0); +const vec3 LightRed = vec3(0.78, 0.0, 0.0); +const vec3 LightBlue = vec3(0.73, 1.0, 1.0); +const float EPSILON = 0.0001; +const float ONE_OVER_EPSILON = 1e4; + +struct PrintVolumeDetection +{ + // 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid + int type; + // type = 0 (rectangle): + // x = min.x, y = min.y, z = max.x, w = max.y + // type = 1 (circle): + // x = center.x, y = center.y, z = radius + vec4 xy_data; + // x = min z, y = max z + vec2 z_data; +}; + +struct SlopeDetection +{ + bool actived; + float normal_z; + mat3 volume_world_normal_matrix; +}; + +uniform vec4 uniform_color; +uniform SlopeDetection slope; + +//BBS: add outline_color +uniform bool is_outline; + +uniform bool offset_depth_buffer; + +#ifdef ENABLE_ENVIRONMENT_MAP + uniform sampler2D environment_tex; + uniform bool use_environment_tex; +#endif // ENABLE_ENVIRONMENT_MAP + +in vec3 clipping_planes_dots; + +// x = diffuse, y = specular; +in vec2 intensity; + +uniform PrintVolumeDetection print_volume; +uniform vec3 extruder_printable_heights; +in vec4 world_pos; +in float world_normal_z; +in vec3 eye_normal; + +out vec4 frag_color; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + vec3 color = uniform_color.rgb; + float alpha = uniform_color.a; + + if (slope.actived) { + if(world_pos.z<0.1&&world_pos.z>-0.1) + { + color = LightBlue; + alpha = 0.8; + } + else if( world_normal_z < slope.normal_z - EPSILON) + { + color = color * 0.5 + LightRed * 0.5; + alpha = 0.8; + } + } + // if the fragment is outside the print volume -> use darker color + vec3 pv_check_min = (world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x)) * ONE_OVER_EPSILON; + vec3 pv_check_max = (world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y)) * ONE_OVER_EPSILON; + bool is_out_print_limit =(any(lessThan(pv_check_min, vec3(1.0))) || any(greaterThan(pv_check_max, vec3(1.0)))); + if (print_volume.type == 0) {// rectangle + color = is_out_print_limit ? mix(color, ZERO, 0.3333) : color; + } + else if (print_volume.type == 1) { + // circle + float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); + pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x) * ONE_OVER_EPSILON; + pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y) * ONE_OVER_EPSILON; + color = (any(lessThan(pv_check_min, vec3(1.0))) || any(greaterThan(pv_check_max, vec3(1.0)))) ? mix(color, ZERO, 0.3333) : color; + } + if(extruder_printable_heights.x >= 1.0 ){ + pv_check_min = (world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, extruder_printable_heights.y)) * ONE_OVER_EPSILON; + pv_check_max = (world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, extruder_printable_heights.z)) * ONE_OVER_EPSILON; + bool is_out_printable_height = (all(greaterThan(pv_check_min, vec3(1.0))) && all(lessThan(pv_check_max, vec3(1.0)))) ; + color = is_out_printable_height ? mix(color, ZERO, 0.7) : color; + } + //BBS: add outline_color + if (is_outline) + frag_color = uniform_color; +#ifdef ENABLE_ENVIRONMENT_MAP + else if (use_environment_tex) + frag_color = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); +#endif + else + frag_color = vec4(vec3(intensity.y) + color * intensity.x, alpha); + + // In the support painting gizmo and the seam painting gizmo are painted triangles rendered over the already + // rendered object. To resolved z-fighting between previously rendered object and painted triangles, values + // inside the depth buffer are offset by small epsilon for painted triangles inside those gizmos. + gl_FragDepth = gl_FragCoord.z - (offset_depth_buffer ? EPSILON : 0.0); +} \ No newline at end of file diff --git a/resources/shaders/gouraud_130.vs b/resources/shaders/140/gouraud.vs similarity index 71% rename from resources/shaders/gouraud_130.vs rename to resources/shaders/140/gouraud.vs index 9d46b5c55..2b0eeccd4 100644 --- a/resources/shaders/gouraud_130.vs +++ b/resources/shaders/140/gouraud.vs @@ -1,5 +1,4 @@ -#version 130 - +#version 140 #define INTENSITY_CORRECTION 0.6 // normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) @@ -14,6 +13,9 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); //#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION) //#define LIGHT_FRONT_SHININESS 5.0 +const vec3 LIGHT_BACK_DIR = vec3(0.1397015, 0.6985074,0.6985074); +#define LIGHT_BACK_DIFFUSE (0.3 * INTENSITY_CORRECTION) + #define INTENSITY_AMBIENT 0.3 const vec3 ZERO = vec3(0.0, 0.0, 0.0); @@ -25,6 +27,13 @@ struct SlopeDetection mat3 volume_world_normal_matrix; }; +in vec3 v_position; +in vec3 v_normal; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + uniform mat4 volume_world_matrix; uniform SlopeDetection slope; @@ -32,48 +41,45 @@ uniform SlopeDetection slope; uniform vec2 z_range; // Clipping plane - general orientation. Used by the SLA gizmo. uniform vec4 clipping_plane; - +uniform bool is_text_shape; // x = diffuse, y = specular; -varying vec2 intensity; +out vec2 intensity; -varying vec3 clipping_planes_dots; +out vec3 clipping_planes_dots; -varying vec4 model_pos; -varying vec4 world_pos; -varying float world_normal_z; -varying vec3 eye_normal; - -varying vec3 barycentric_coordinates; +out vec4 model_pos; +out vec4 world_pos; +out float world_normal_z; +out vec3 eye_normal; void main() { // First transform the normal into camera space and normalize the result. - eye_normal = normalize(gl_NormalMatrix * gl_Normal); + eye_normal = normalize(normal_matrix * v_normal); // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz; - intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); + vec4 position = (view_model_matrix * vec4(v_position, 1.0)); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular applied). NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; - model_pos = gl_Vertex; + if(!is_text_shape){ + NdotL = max(dot(eye_normal, LIGHT_BACK_DIR), 0.0); + intensity.x += NdotL * LIGHT_BACK_DIFFUSE; + } // Point in homogenous coordinates. - world_pos = volume_world_matrix * gl_Vertex; + world_pos = volume_world_matrix * vec4(v_position, 1.0); // z component of normal vector in world coordinate used for slope shading - world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * gl_Normal)).z : 0.0; + world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0; - gl_Position = ftransform(); + gl_Position = projection_matrix * position; // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); - - //compute the Barycentric Coordinates - int vertexMod3 = gl_VertexID % 3; - barycentric_coordinates = vec3(float(vertexMod3 == 0), float(vertexMod3 == 1), float(vertexMod3 == 2)); } diff --git a/resources/shaders/140/gouraud_light.fs b/resources/shaders/140/gouraud_light.fs new file mode 100644 index 000000000..96eee3a5e --- /dev/null +++ b/resources/shaders/140/gouraud_light.fs @@ -0,0 +1,14 @@ +#version 140 + +uniform vec4 uniform_color; +uniform float emission_factor; + +// x = tainted, y = specular; +in vec2 intensity; + +out vec4 frag_color; + +void main() +{ + frag_color = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a); +} diff --git a/resources/shaders/gouraud_light.vs b/resources/shaders/140/gouraud_light.vs similarity index 76% rename from resources/shaders/gouraud_light.vs rename to resources/shaders/140/gouraud_light.vs index d4f71938a..9687ea9bd 100644 --- a/resources/shaders/gouraud_light.vs +++ b/resources/shaders/140/gouraud_light.vs @@ -1,4 +1,4 @@ -#version 110 +#version 140 #define INTENSITY_CORRECTION 0.6 @@ -14,25 +14,32 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 +in vec3 v_position; +in vec3 v_normal; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + // x = tainted, y = specular; -varying vec2 intensity; +out vec2 intensity; void main() { // First transform the normal into camera space and normalize the result. - vec3 normal = normalize(gl_NormalMatrix * gl_Normal); - + vec3 normal = normalize(normal_matrix * v_normal); + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz; - intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular applied). NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; - gl_Position = ftransform(); + gl_Position = projection_matrix * position; } diff --git a/resources/shaders/140/gouraud_light_instanced.vs b/resources/shaders/140/gouraud_light_instanced.vs new file mode 100644 index 000000000..981df69dd --- /dev/null +++ b/resources/shaders/140/gouraud_light_instanced.vs @@ -0,0 +1,67 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +// vertex attributes +in vec3 v_position; +in vec3 v_normal; +// instance attributes +in vec3 i_offset; +in vec2 i_scales; + +in mat4 instanceMatrix; +uniform mat4 view_matrix; +uniform mat4 projection_matrix; + +// x = tainted, y = specular; +out vec2 intensity; + +mat3 inverse_mat3(mat3 m) { + float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2]; + float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2]; + float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2]; + + float b01 = a22 * a11 - a12 * a21; + float b11 = -a22 * a10 + a12 * a20; + float b21 = a21 * a10 - a11 * a20; + + float det = a00 * b01 + a01 * b11 + a02 * b21; + + return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11), + b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10), + b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det; +} + +void main() +{ + mat4 view_model_matrix = view_matrix * instanceMatrix; + + // First transform the normal into camera space and normalize the result. + vec3 normal = normalize(transpose(inverse_mat3(mat3(view_model_matrix))) * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/140/hotbed.fs b/resources/shaders/140/hotbed.fs new file mode 100644 index 000000000..4e932fe9b --- /dev/null +++ b/resources/shaders/140/hotbed.fs @@ -0,0 +1,52 @@ +#version 140 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); +const vec3 WHITE = vec3(1.0, 1.0, 1.0); +const float ONE_OVER_EPSILON = 1e4; +struct PrintVolumeDetection +{ + // 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid + int type; + // type = 0 (rectangle): + // x = min.x, y = min.y, z = max.x, w = max.y + // type = 1 (circle): + // x = center.x, y = center.y, z = radius + vec4 xy_data; + // x = min z, y = max z + vec2 z_data; +}; + +uniform vec4 uniform_color; +uniform float emission_factor; +uniform PrintVolumeDetection print_volume; +// x = diffuse, y = specular; +in vec2 intensity; +in vec4 world_pos; + +out vec4 frag_color; +void main() +{ + vec3 color = uniform_color.rgb; + float alpha = uniform_color.a; + // if the fragment is outside the print volume -> use darker color + vec3 pv_check_min = ZERO; + vec3 pv_check_max = ZERO; + if (print_volume.type == 0) {// rectangle + pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); + pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); + + pv_check_min = pv_check_min * ONE_OVER_EPSILON; + pv_check_max = pv_check_max * ONE_OVER_EPSILON; + color = (any(lessThan(pv_check_min, vec3(1.0))) || any(greaterThan(pv_check_max, vec3(1.0)))) ? mix(color, WHITE, 0.3333) : color; + } + else if (print_volume.type == 1) {// circle + float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); + pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); + pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); + + pv_check_min = pv_check_min * ONE_OVER_EPSILON; + pv_check_max = pv_check_max * ONE_OVER_EPSILON; + color = (any(lessThan(pv_check_min, vec3(1.0))) || any(greaterThan(pv_check_max, vec3(1.0)))) ? mix(color, WHITE, 0.3333) : color; + } + frag_color = vec4(vec3(intensity.y) + color * (intensity.x + emission_factor), alpha); +} \ No newline at end of file diff --git a/resources/shaders/140/hotbed.vs b/resources/shaders/140/hotbed.vs new file mode 100644 index 000000000..fa2c438d6 --- /dev/null +++ b/resources/shaders/140/hotbed.vs @@ -0,0 +1,47 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 view_normal_matrix; +uniform mat4 volume_world_matrix; + +in vec3 v_position; +in vec3 v_normal; + +// x = tainted, y = specular; +out vec2 intensity; +out vec4 world_pos; +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 normal = normalize(view_normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + world_pos = volume_world_matrix * vec4(v_position, 1.0); + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/140/imgui.fs b/resources/shaders/140/imgui.fs new file mode 100644 index 000000000..21641ac3c --- /dev/null +++ b/resources/shaders/140/imgui.fs @@ -0,0 +1,12 @@ +#version 140 + +uniform sampler2D Texture; + +in vec2 Frag_UV; +in vec4 color; + +out vec4 frag_color; +void main() +{ + frag_color = color * texture(Texture, Frag_UV.st); +} \ No newline at end of file diff --git a/resources/shaders/140/imgui.vs b/resources/shaders/140/imgui.vs new file mode 100644 index 000000000..9f7f9c08e --- /dev/null +++ b/resources/shaders/140/imgui.vs @@ -0,0 +1,17 @@ +#version 140 + +uniform mat4 ProjMtx; + +in vec2 Position; +in vec2 UV; +in vec4 Color; + +out vec2 Frag_UV; +out vec4 color; + +void main() +{ + Frag_UV = UV; + color = Color; + gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/140/mainframe_composite.fs b/resources/shaders/140/mainframe_composite.fs new file mode 100644 index 000000000..b75bd60a6 --- /dev/null +++ b/resources/shaders/140/mainframe_composite.fs @@ -0,0 +1,12 @@ +#version 140 + +uniform sampler2D u_sampler; + +in vec2 tex_coords; + +out vec4 frag_color; + +void main() +{ + frag_color = texture(u_sampler, tex_coords); +} \ No newline at end of file diff --git a/resources/shaders/140/mainframe_composite.vs b/resources/shaders/140/mainframe_composite.vs new file mode 100644 index 000000000..9c6a90120 --- /dev/null +++ b/resources/shaders/140/mainframe_composite.vs @@ -0,0 +1,12 @@ +#version 140 + +in vec3 v_position; +in vec2 v_tex_coord; + +out vec2 tex_coords; + +void main() +{ + tex_coords = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/140/mm_contour.fs b/resources/shaders/140/mm_contour.fs new file mode 100644 index 000000000..54a78afe6 --- /dev/null +++ b/resources/shaders/140/mm_contour.fs @@ -0,0 +1,12 @@ +#version 140 + +const float EPSILON = 0.0001; + +out vec4 frag_color; +void main() +{ + frag_color = vec4(1.0, 1.0, 1.0, 1.0); + // Values inside depth buffer for fragments of the contour of a selected area are offset + // by small epsilon to solve z-fighting between painted triangles and contour lines. + gl_FragDepth = gl_FragCoord.z - EPSILON; +} diff --git a/resources/shaders/140/mm_contour.vs b/resources/shaders/140/mm_contour.vs new file mode 100644 index 000000000..7042671de --- /dev/null +++ b/resources/shaders/140/mm_contour.vs @@ -0,0 +1,11 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; + +void main() +{ + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/mm_gouraud.fs b/resources/shaders/140/mm_gouraud_wireframe.fs similarity index 65% rename from resources/shaders/mm_gouraud.fs rename to resources/shaders/140/mm_gouraud_wireframe.fs index ee78991a3..6935ebc5e 100644 --- a/resources/shaders/mm_gouraud.fs +++ b/resources/shaders/140/mm_gouraud_wireframe.fs @@ -1,4 +1,4 @@ -#version 110 +#version 140 #define INTENSITY_CORRECTION 0.6 @@ -23,9 +23,9 @@ const vec3 LightRed = vec3(0.78, 0.0, 0.0); const vec3 LightBlue = vec3(0.73, 1.0, 1.0); uniform vec4 uniform_color; -varying vec3 clipping_planes_dots; -varying vec4 model_pos; -varying vec4 world_pos; +in vec3 clipping_planes_dots; +in vec3 model_pos; +in vec4 world_pos; uniform bool volume_mirrored; struct SlopeDetection @@ -36,6 +36,32 @@ struct SlopeDetection }; uniform SlopeDetection slope; +//BBS: add wireframe logic +in vec3 barycentric_coordinates; +float edgeFactor(float lineWidth) { + vec3 d = fwidth(barycentric_coordinates); + vec3 a3 = smoothstep(vec3(0.0), d * lineWidth, barycentric_coordinates); + return min(min(a3.x, a3.y), a3.z); +} + +vec3 wireframe(vec3 fill, vec3 stroke, float lineWidth) { + return mix(stroke, fill, edgeFactor(lineWidth)); + //if (any(lessThan(barycentric_coordinates, vec3(0.005, 0.005, 0.005)))) + // return vec3(1.0, 0.0, 0.0); + //else + // return fill; +} + +vec3 getWireframeColor(vec3 fill) { + float brightness = 0.2126 * fill.r + 0.7152 * fill.g + 0.0722 * fill.b; + return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988); +} +uniform bool show_wireframe; +uniform mat4 view_model_matrix; +uniform mat3 normal_matrix; + +out vec4 frag_color; + void main() { if (any(lessThan(clipping_planes_dots, ZERO))) @@ -49,7 +75,7 @@ void main() triangle_normal = -triangle_normal; } vec3 transformed_normal = normalize(slope.volume_world_normal_matrix * triangle_normal); - + if (slope.actived) { if(world_pos.z<0.1&&world_pos.z>-0.1) { @@ -62,8 +88,9 @@ void main() alpha = 1.0; } } + // First transform the normal into camera space and normalize the result. - vec3 eye_normal = normalize(gl_NormalMatrix * triangle_normal); + vec3 eye_normal = normalize(normal_matrix * triangle_normal); // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. @@ -72,12 +99,19 @@ void main() // x = diffuse, y = specular; vec2 intensity = vec2(0.0, 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec3 position = (gl_ModelViewMatrix * model_pos).xyz; + vec3 position = (view_model_matrix * vec4(model_pos, 1.0)).xyz; intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular applied). NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; - gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); + if (show_wireframe) { + vec3 wireframeColor = show_wireframe ? getWireframeColor(color) : color; + vec3 triangleColor = wireframe(color, wireframeColor, 1.0); + frag_color = vec4(vec3(intensity.y) + triangleColor * intensity.x, alpha); + } + else { + frag_color = vec4(vec3(intensity.y) + color * intensity.x, alpha); + } } diff --git a/resources/shaders/140/mm_gouraud_wireframe.vs b/resources/shaders/140/mm_gouraud_wireframe.vs new file mode 100644 index 000000000..ffe2d0cb9 --- /dev/null +++ b/resources/shaders/140/mm_gouraud_wireframe.vs @@ -0,0 +1,47 @@ +#version 140 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +//attribute vec3 v_position; +//attribute vec3 v_barycentric; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat4 volume_world_matrix; +// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. +uniform vec2 z_range; +// Clipping plane - general orientation. Used by the SLA gizmo. +uniform vec4 clipping_plane; + +in vec3 v_position; +in vec3 v_color; + +out vec3 clipping_planes_dots; +out vec3 model_pos; +out vec4 world_pos; +out vec3 barycentric_coordinates; + +struct SlopeDetection +{ + bool actived; + float normal_z; + mat3 volume_world_normal_matrix; +}; +uniform SlopeDetection slope; +void main() +{ + model_pos = v_position; + //model_pos = vec4(v_position, 1.0); + // Point in homogenous coordinates. + world_pos = volume_world_matrix * vec4(model_pos, 1.0); + + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); + //gl_Position = gl_ModelViewProjectionMatrix * vec4(v_position, 1.0); + // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. + clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); + + //compute the Barycentric Coordinates + //int vertexMod3 = gl_VertexID % 3; + //barycentric_coordinates = vec3(float(vertexMod3 == 0), float(vertexMod3 == 1), float(vertexMod3 == 2)); + barycentric_coordinates = v_color.xyz;//v_barycentric +} diff --git a/resources/shaders/140/printbed.fs b/resources/shaders/140/printbed.fs new file mode 100644 index 000000000..17f5c157f --- /dev/null +++ b/resources/shaders/140/printbed.fs @@ -0,0 +1,29 @@ +#version 140 +const vec3 back_color_dark = vec3(0.235, 0.235, 0.235); +const vec3 back_color_light = vec3(0.365, 0.365, 0.365); +uniform sampler2D u_sampler; +uniform bool transparent_background; +uniform bool svg_source; +in vec2 tex_coord; +out vec4 frag_color; +vec4 svg_color(vec2 uv) +{ + // takes foreground from u_sampler + vec4 fore_color = texture(u_sampler, uv); + // calculates radial gradient + vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(uv) - vec2(0.5))))); + // blends foreground with background + return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0); +} +vec4 non_svg_color(vec2 uv) +{ + // takes foreground from u_sampler + vec4 color = texture(u_sampler, uv); + return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); +} +void main() +{ + // flip uv + vec2 uv = vec2(tex_coord.x, 1.0 - tex_coord.y); + frag_color = svg_source ? svg_color(uv) : non_svg_color(uv); +} \ No newline at end of file diff --git a/resources/shaders/140/printbed.vs b/resources/shaders/140/printbed.vs new file mode 100644 index 000000000..5ca1517db --- /dev/null +++ b/resources/shaders/140/printbed.vs @@ -0,0 +1,15 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; +in vec2 v_tex_coord; + +out vec2 tex_coord; + +void main() +{ + tex_coord = v_tex_coord; + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/silhouette.fs b/resources/shaders/140/silhouette.fs new file mode 100644 index 000000000..33178205d --- /dev/null +++ b/resources/shaders/140/silhouette.fs @@ -0,0 +1,8 @@ +#version 140 +uniform vec4 u_base_color; + +out vec4 frag_color; +void main() +{ + frag_color = u_base_color; +} \ No newline at end of file diff --git a/resources/shaders/140/silhouette.vs b/resources/shaders/140/silhouette.vs new file mode 100644 index 000000000..325c20703 --- /dev/null +++ b/resources/shaders/140/silhouette.vs @@ -0,0 +1,11 @@ +#version 140 + +uniform mat4 u_model_matrix; +uniform mat4 u_view_projection_matrix; + +in vec3 v_position; + +void main() +{ + gl_Position = u_view_projection_matrix * u_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/silhouette_composite.fs b/resources/shaders/140/silhouette_composite.fs new file mode 100644 index 000000000..64a5d1622 --- /dev/null +++ b/resources/shaders/140/silhouette_composite.fs @@ -0,0 +1,41 @@ +#version 140 +uniform sampler2D u_sampler; +uniform mat3 u_convolution_matrix; +uniform vec2 u_viewport_size; + +in vec2 tex_coords; + +out vec4 frag_color; + +vec4 sample(float offsetX, float offsetY) +{ + return texture(u_sampler, vec2(tex_coords.x + offsetX, tex_coords.y + offsetY)); +} +void main() +{ + vec4 pixels[9]; + float deltaWidth = 1.0 / u_viewport_size.x; + float deltaHeight = 1.0 / u_viewport_size.y; + float effect_width = 1.0f; + deltaWidth = deltaWidth * effect_width; + deltaWidth = deltaWidth * effect_width; + + pixels[0] = sample(-deltaWidth, deltaHeight ); + pixels[1] = sample(0.0, deltaHeight ); + pixels[2] = sample(deltaWidth, deltaHeight ); + pixels[3] = sample(-deltaWidth, 0.0); + pixels[4] = sample(0.0, 0.0); + pixels[5] = sample(deltaWidth, 0.0); + pixels[6] = sample(-deltaWidth, -deltaHeight); + pixels[7] = sample(0.0, -deltaHeight); + pixels[8] = sample(deltaWidth, -deltaHeight); + vec4 accumulator = vec4(0.0); + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; ++j) + { + accumulator += pixels[3 * i + j] * u_convolution_matrix[i][j]; + } + } + frag_color = accumulator; +} \ No newline at end of file diff --git a/resources/shaders/140/silhouette_composite.vs b/resources/shaders/140/silhouette_composite.vs new file mode 100644 index 000000000..9c6a90120 --- /dev/null +++ b/resources/shaders/140/silhouette_composite.vs @@ -0,0 +1,12 @@ +#version 140 + +in vec3 v_position; +in vec2 v_tex_coord; + +out vec2 tex_coords; + +void main() +{ + tex_coords = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/140/thumbnail.fs b/resources/shaders/140/thumbnail.fs new file mode 100644 index 000000000..1ba0edbe2 --- /dev/null +++ b/resources/shaders/140/thumbnail.fs @@ -0,0 +1,23 @@ +#version 140 + +uniform bool ban_light; +uniform vec4 uniform_color; +uniform float emission_factor; + +// x = tainted, y = specular; +in vec2 intensity; +//varying float drop; +in vec4 world_pos; + +out vec4 frag_color; + +void main() +{ + if (world_pos.z < 0.0) + discard; + if(ban_light){ + frag_color = uniform_color; + } else{ + frag_color = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a); + } +} diff --git a/resources/shaders/140/thumbnail.vs b/resources/shaders/140/thumbnail.vs new file mode 100644 index 000000000..931037566 --- /dev/null +++ b/resources/shaders/140/thumbnail.vs @@ -0,0 +1,50 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +in vec3 v_position; +in vec3 v_normal; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +uniform mat4 volume_world_matrix; +// x = tainted, y = specular; +out vec2 intensity; +out vec4 world_pos; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 normal = normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 position = (view_model_matrix * vec4(v_position, 1.0)); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + // Point in homogenous coordinates. + world_pos = volume_world_matrix * vec4(v_position, 1.0); + + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/140/toolpaths_lines.fs b/resources/shaders/140/toolpaths_lines.fs new file mode 100644 index 000000000..e43bbf520 --- /dev/null +++ b/resources/shaders/140/toolpaths_lines.fs @@ -0,0 +1,30 @@ +#version 140 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +const vec3 LIGHT_FRONT_DIR = vec3(0.0, 0.0, 1.0); + +// x = ambient, y = top diffuse, z = front diffuse, w = global +uniform vec4 light_intensity; +uniform vec4 uniform_color; + +in vec3 eye_normal; + +out vec4 frag_color; + +void main() +{ + vec3 normal = normalize(eye_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. Take the abs value to light the lines no matter in which direction the normal points. + float NdotL = abs(dot(normal, LIGHT_TOP_DIR)); + + float intensity = light_intensity.x + NdotL * light_intensity.y; + + // Perform the same lighting calculation for the 2nd light source. + NdotL = abs(dot(normal, LIGHT_FRONT_DIR)); + intensity += NdotL * light_intensity.z; + + frag_color = vec4(uniform_color.rgb * light_intensity.w * intensity, uniform_color.a); +} diff --git a/resources/shaders/140/toolpaths_lines.vs b/resources/shaders/140/toolpaths_lines.vs new file mode 100644 index 000000000..97937c616 --- /dev/null +++ b/resources/shaders/140/toolpaths_lines.vs @@ -0,0 +1,16 @@ +#version 140 + +in vec3 v_position; +in vec3 v_normal; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +out vec3 eye_normal; + +void main() +{ + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); + eye_normal = normal_matrix * v_normal; +} diff --git a/resources/shaders/140/variable_layer_height.fs b/resources/shaders/140/variable_layer_height.fs new file mode 100644 index 000000000..185f237ee --- /dev/null +++ b/resources/shaders/140/variable_layer_height.fs @@ -0,0 +1,43 @@ +#version 140 + +#define M_PI 3.1415926535897932384626433832795 + +// 2D texture (1D texture split by the rows) of color along the object Z axis. +uniform sampler2D z_texture; +// Scaling from the Z texture rows coordinate to the normalized texture row coordinate. +uniform float z_to_texture_row; +uniform float z_texture_row_to_normalized; +uniform float z_cursor; +uniform float z_cursor_band_width; + +// x = tainted, y = specular; +in vec2 intensity; + +in float object_z; + +out vec4 frag_color; + +void main() +{ + float object_z_row = z_to_texture_row * object_z; + // Index of the row in the texture. + float z_texture_row = floor(object_z_row); + // Normalized coordinate from 0. to 1. + float z_texture_col = object_z_row - z_texture_row; + float z_blend = 0.25 * cos(min(M_PI, abs(M_PI * (object_z - z_cursor) * 1.8 / z_cursor_band_width))) + 0.25; + // Calculate level of detail from the object Z coordinate. + // This makes the slowly sloping surfaces to be shown with high detail (with stripes), + // and the vertical surfaces to be shown with low detail (no stripes) + float z_in_cells = object_z_row * 190.; + // Gradient of Z projected on the screen. + float dx_vtc = dFdx(z_in_cells); + float dy_vtc = dFdy(z_in_cells); + float lod = clamp(0.5 * log2(max(dx_vtc * dx_vtc, dy_vtc * dy_vtc)), 0., 1.); + // Sample the Z texture. Texture coordinates are normalized to <0, 1>. + vec4 color = vec4(0.25, 0.25, 0.25, 1.0); + if (z_texture_row >= 0.0) + color = mix(texture(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.), + texture(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod); + // Mix the final color. + frag_color = vec4(vec3(intensity.y), 1.0) + intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend); +} diff --git a/resources/shaders/140/variable_layer_height.vs b/resources/shaders/140/variable_layer_height.vs new file mode 100644 index 000000000..7396075d8 --- /dev/null +++ b/resources/shaders/140/variable_layer_height.vs @@ -0,0 +1,60 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) +//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION) +//#define LIGHT_FRONT_SHININESS 5.0 + +#define INTENSITY_AMBIENT 0.3 + +in vec3 v_position; +in vec3 v_normal; +in vec2 v_tex_coord; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +uniform mat4 volume_world_matrix; +uniform float object_max_z; + +// x = tainted, y = specular; +out vec2 intensity; + +out float object_z; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 normal = normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular) + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + // Scaled to widths of the Z texture. + if (object_max_z > 0.0) + // when rendering the overlay + object_z = object_max_z * v_tex_coord.y; + else + // when rendering the volumes + object_z = (volume_world_matrix * vec4(v_position, 1.0)).z; + + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/cali.vs b/resources/shaders/cali.vs deleted file mode 100644 index d0d3ee42a..000000000 --- a/resources/shaders/cali.vs +++ /dev/null @@ -1,6 +0,0 @@ -#version 110 - -void main() -{ - gl_Position = ftransform(); -} diff --git a/resources/shaders/gouraud_130.fs b/resources/shaders/gouraud_130.fs deleted file mode 100644 index 9ab12676e..000000000 --- a/resources/shaders/gouraud_130.fs +++ /dev/null @@ -1,124 +0,0 @@ -#version 130 - -const vec3 ZERO = vec3(0.0, 0.0, 0.0); -//BBS: add grey and orange -//const vec3 GREY = vec3(0.9, 0.9, 0.9); -const vec3 ORANGE = vec3(0.8, 0.4, 0.0); -const float EPSILON = 0.0001; - -struct PrintVolumeDetection -{ - // 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid - int type; - // type = 0 (rectangle): - // x = min.x, y = min.y, z = max.x, w = max.y - // type = 1 (circle): - // x = center.x, y = center.y, z = radius - vec4 xy_data; - // x = min z, y = max z - vec2 z_data; -}; - -struct SlopeDetection -{ - bool actived; - float normal_z; - mat3 volume_world_normal_matrix; -}; - -//BBS: add wireframe logic -varying vec3 barycentric_coordinates; -float edgeFactor(float lineWidth) { - vec3 d = fwidth(barycentric_coordinates); - vec3 a3 = smoothstep(vec3(0.0), d * lineWidth, barycentric_coordinates); - return min(min(a3.x, a3.y), a3.z); -} - -vec3 wireframe(vec3 fill, vec3 stroke, float lineWidth) { - return mix(stroke, fill, edgeFactor(lineWidth)); -} - -vec3 getWireframeColor(vec3 fill) { - float brightness = 0.2126 * fill.r + 0.7152 * fill.g + 0.0722 * fill.b; - return (brightness > 0.75) ? vec3(0.11, 0.165, 0.208) : vec3(0.988, 0.988, 0.988); -} - -uniform vec4 uniform_color; -uniform SlopeDetection slope; - -//BBS: add outline_color -uniform bool is_outline; -uniform bool show_wireframe; - -uniform bool offset_depth_buffer; - -#ifdef ENABLE_ENVIRONMENT_MAP - uniform sampler2D environment_tex; - uniform bool use_environment_tex; -#endif // ENABLE_ENVIRONMENT_MAP - -varying vec3 clipping_planes_dots; - -// x = diffuse, y = specular; -varying vec2 intensity; - -uniform PrintVolumeDetection print_volume; - -varying vec4 model_pos; -varying vec4 world_pos; -varying float world_normal_z; -varying vec3 eye_normal; - -void main() -{ - if (any(lessThan(clipping_planes_dots, ZERO))) - discard; - vec3 color = uniform_color.rgb; - float alpha = uniform_color.a; - - if (slope.actived && world_normal_z < slope.normal_z - EPSILON) { - //color = vec3(0.7, 0.7, 1.0); - color = ORANGE; - alpha = 1.0; - } - - // if the fragment is outside the print volume -> use darker color - vec3 pv_check_min = ZERO; - vec3 pv_check_max = ZERO; - if (print_volume.type == 0) { - // rectangle - pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); - pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); - color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; - } - else if (print_volume.type == 1) { - // circle - float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); - pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); - pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); - color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; - } - - //BBS: add outline_color - if (is_outline) - gl_FragColor = uniform_color; -#ifdef ENABLE_ENVIRONMENT_MAP - else if (use_environment_tex) - gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); -#endif - else { - //gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); - if (show_wireframe) { - vec3 wireframeColor = show_wireframe ? getWireframeColor(color) : color; - vec3 triangleColor = wireframe(color, wireframeColor, 1.0); - gl_FragColor = vec4(vec3(intensity.y) + triangleColor * intensity.x, alpha); - } - else { - gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); - } - } - // In the support painting gizmo and the seam painting gizmo are painted triangles rendered over the already - // rendered object. To resolved z-fighting between previously rendered object and painted triangles, values - // inside the depth buffer are offset by small epsilon for painted triangles inside those gizmos. - gl_FragDepth = gl_FragCoord.z - (offset_depth_buffer ? EPSILON : 0.0); -} \ No newline at end of file diff --git a/resources/shaders/gouraud_light_instanced.fs b/resources/shaders/gouraud_light_instanced.fs deleted file mode 100644 index 970185a00..000000000 --- a/resources/shaders/gouraud_light_instanced.fs +++ /dev/null @@ -1,12 +0,0 @@ -#version 110 - -uniform vec4 uniform_color; -uniform float emission_factor; - -// x = tainted, y = specular; -varying vec2 intensity; - -void main() -{ - gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a); -} diff --git a/resources/shaders/mm_contour.vs b/resources/shaders/mm_contour.vs deleted file mode 100644 index d0d3ee42a..000000000 --- a/resources/shaders/mm_contour.vs +++ /dev/null @@ -1,6 +0,0 @@ -#version 110 - -void main() -{ - gl_Position = ftransform(); -} diff --git a/resources/shaders/mm_gouraud.vs b/resources/shaders/mm_gouraud.vs deleted file mode 100644 index 5929c88be..000000000 --- a/resources/shaders/mm_gouraud.vs +++ /dev/null @@ -1,30 +0,0 @@ -#version 110 - -const vec3 ZERO = vec3(0.0, 0.0, 0.0); - -uniform mat4 volume_world_matrix; -// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. -uniform vec2 z_range; -// Clipping plane - general orientation. Used by the SLA gizmo. -uniform vec4 clipping_plane; - -varying vec3 clipping_planes_dots; -varying vec4 model_pos; -varying vec4 world_pos; -struct SlopeDetection -{ - bool actived; - float normal_z; - mat3 volume_world_normal_matrix; -}; -uniform SlopeDetection slope; -void main() -{ - model_pos = gl_Vertex; - // Point in homogenous coordinates. - world_pos = volume_world_matrix * gl_Vertex; - - gl_Position = ftransform(); - // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. - clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); -} diff --git a/resources/shaders/options_110.fs b/resources/shaders/options_110.fs deleted file mode 100644 index ab656998d..000000000 --- a/resources/shaders/options_110.fs +++ /dev/null @@ -1,8 +0,0 @@ -#version 110 - -uniform vec4 uniform_color; - -void main() -{ - gl_FragColor = uniform_color; -} diff --git a/resources/shaders/options_110.vs b/resources/shaders/options_110.vs deleted file mode 100644 index 5f2ab2350..000000000 --- a/resources/shaders/options_110.vs +++ /dev/null @@ -1,22 +0,0 @@ -#version 110 - -uniform bool use_fixed_screen_size; -uniform float zoom; -uniform float point_size; -uniform float near_plane_height; - -float fixed_screen_size() -{ - return point_size; -} - -float fixed_world_size() -{ - return (gl_Position.w == 1.0) ? zoom * near_plane_height * point_size : near_plane_height * point_size / gl_Position.w; -} - -void main() -{ - gl_Position = ftransform(); - gl_PointSize = use_fixed_screen_size ? fixed_screen_size() : fixed_world_size(); -} diff --git a/resources/shaders/options_120.fs b/resources/shaders/options_120.fs deleted file mode 100644 index e9b61304f..000000000 --- a/resources/shaders/options_120.fs +++ /dev/null @@ -1,22 +0,0 @@ -// version 120 is needed for gl_PointCoord -#version 120 - -uniform vec4 uniform_color; -uniform float percent_outline_radius; -uniform float percent_center_radius; - -vec4 calc_color(float radius, vec4 color) -{ - return ((radius < percent_center_radius) || (radius > 1.0 - percent_outline_radius)) ? - vec4(0.5 * color.rgb, color.a) : color; -} - -void main() -{ - vec2 pos = (gl_PointCoord - 0.5) * 2.0; - float radius = length(pos); - if (radius > 1.0) - discard; - - gl_FragColor = calc_color(radius, uniform_color); -} diff --git a/resources/shaders/options_120.vs b/resources/shaders/options_120.vs deleted file mode 100644 index edb503fb2..000000000 --- a/resources/shaders/options_120.vs +++ /dev/null @@ -1,22 +0,0 @@ -#version 120 - -uniform bool use_fixed_screen_size; -uniform float zoom; -uniform float point_size; -uniform float near_plane_height; - -float fixed_screen_size() -{ - return point_size; -} - -float fixed_world_size() -{ - return (gl_Position.w == 1.0) ? zoom * near_plane_height * point_size : near_plane_height * point_size / gl_Position.w; -} - -void main() -{ - gl_Position = ftransform(); - gl_PointSize = use_fixed_screen_size ? fixed_screen_size() : fixed_world_size(); -} diff --git a/resources/shaders/outline.fs b/resources/shaders/outline.fs deleted file mode 100644 index f8f13853f..000000000 --- a/resources/shaders/outline.fs +++ /dev/null @@ -1,10 +0,0 @@ -#version 110 - -const vec3 ORANGE = vec3(0.8, 0.4, 0.0); -uniform vec4 uniform_color; - -void main() -{ - gl_FragColor = uniform_color; - //gl_FragColor = vec4(ORANGE, 1.0); -} \ No newline at end of file diff --git a/resources/shaders/outline.vs b/resources/shaders/outline.vs deleted file mode 100644 index fd6580b46..000000000 --- a/resources/shaders/outline.vs +++ /dev/null @@ -1,12 +0,0 @@ -#version 110 - -attribute vec4 v_position; -attribute vec2 v_tex_coords; - -varying vec2 tex_coords; - -void main() -{ - gl_Position = ftransform(); - tex_coords = v_tex_coords; -} diff --git a/resources/shaders/toolpaths_lines.vs b/resources/shaders/toolpaths_lines.vs deleted file mode 100644 index c008aedc6..000000000 --- a/resources/shaders/toolpaths_lines.vs +++ /dev/null @@ -1,9 +0,0 @@ -#version 110 - -varying vec3 eye_normal; - -void main() -{ - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - eye_normal = gl_NormalMatrix * gl_Normal; -} diff --git a/src/BambuStudio.cpp b/src/BambuStudio.cpp index 426cf146d..e517cbce3 100644 --- a/src/BambuStudio.cpp +++ b/src/BambuStudio.cpp @@ -5199,7 +5199,7 @@ int CLI::run(int argc, char **argv) //opengl related Slic3r::GUI::OpenGLManager opengl_mgr; - GLShaderProgram* shader = nullptr; + std::shared_ptr shader = nullptr; GLVolumeCollection glvolume_collection; bool opengl_valid = false; const ConfigOptionStrings* filament_color = dynamic_cast(m_print_config.option("filament_colour")); @@ -5883,6 +5883,7 @@ int CLI::run(int argc, char **argv) auto cli_generate_thumbnails = [&partplate_list, &model, &glvolume_collection, &colors_out, &shader, &opengl_mgr](const ThumbnailsParams& params) -> ThumbnailsList{ ThumbnailsList thumbnails; opengl_mgr.bind_vao(); + opengl_mgr.bind_shader(shader); for (const Vec2d& size : params.sizes) { thumbnails.push_back(ThumbnailData()); Point isize(size); // round to ints @@ -5912,6 +5913,7 @@ int CLI::run(int argc, char **argv) if (!thumbnails.back().is_valid()) thumbnails.pop_back(); } + opengl_mgr.unbind_shader(); opengl_mgr.unbind_vao(); return thumbnails; }; @@ -6423,6 +6425,7 @@ int CLI::run(int argc, char **argv) if (opengl_valid) { Model &model = m_models[0]; opengl_mgr.bind_vao(); + opengl_mgr.bind_shader(shader); for (int i = 0; i < partplate_list.get_plate_count(); i++) { Slic3r::GUI::PartPlate *part_plate = partplate_list.get_plate(i); PlateData *plate_data = plate_data_list[i]; @@ -6654,7 +6657,7 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("plate %1%: add thumbnail data for top and pick into group")%(i+1); } } - + opengl_mgr.unbind_shader(); opengl_mgr.unbind_vao(); } } diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 7ba149290..51682331f 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -201,6 +201,12 @@ void AppConfig::set_defaults() if (get("prefer_to_use_dgpu").empty()) set_bool("prefer_to_use_dgpu", false); + if (get("msaa_type").empty()) + set("msaa_type", "X4"); + + if (get("enable_advanced_antialiasing").empty()) + set_bool("enable_advanced_antialiasing", true); + if (get("show_3d_navigator").empty()) set_bool("show_3d_navigator", true); diff --git a/src/libslic3r/Frustum.cpp b/src/libslic3r/Frustum.cpp index 10fae9145..fcf278ac4 100644 --- a/src/libslic3r/Frustum.cpp +++ b/src/libslic3r/Frustum.cpp @@ -1,18 +1,76 @@ #include "Frustum.hpp" #include namespace Slic3r { + +void Frustum::Plane::set_abcd(float a, float b, float c, float d) +{ + m_abcd[0] = a; + m_abcd[1] = b; + m_abcd[2] = c; + m_abcd[3] = d; +} + +const Vec4f& Frustum::Plane::get_abcd() const +{ + return m_abcd; +} + +void Frustum::Plane::normailze() +{ + float mag; + mag = sqrt(m_abcd[0] * m_abcd[0] + m_abcd[1] * m_abcd[1] + m_abcd[2] * m_abcd[2]); + m_abcd[0] = m_abcd[0] / mag; + m_abcd[1] = m_abcd[1] / mag; + m_abcd[2] = m_abcd[2] / mag; + m_abcd[3] = m_abcd[3] / mag; +} + +float Frustum::Plane::distance(const Vec3f& pt) const +{ + float result = 0.0f; + for (int i = 0; i < 3; ++i) { + result += pt[i] * m_abcd[i]; + } + + result += m_abcd[3]; + + return result; +} + Frustum::Plane::PlaneIntersects Frustum::Plane::intersects(const BoundingBoxf3 &box) const { - Vec3f center = ((box.min + box.max) * 0.5f).cast(); - Vec3f extent = ((box.max - box.min) * 0.5f).cast(); - float d = distance(center); - float r = fabsf(extent.x() * normal_.x()) + fabsf(extent.y() * normal_.y()) + fabsf(extent.z() * normal_.z()); - if (d == r) { - return Plane::Intersects_Tangent; - } else if (std::abs(d) < r) { - return Plane::Intersects_Cross; + // see https://cgvr.cs.uni-bremen.de/teaching/cg_literatur/lighthouse3d_view_frustum_culling/index.html + + Vec3d positive_v = box.min; + if (m_abcd[0] > 0.f) + positive_v[0] = box.max.x(); + if (m_abcd[1] > 0.f) + positive_v[1] = box.max.y(); + if (m_abcd[2] > 0.f) + positive_v[2] = box.max.z(); + + float dis_positive = distance(positive_v.cast()); + if (dis_positive < 0.f) + { + return Frustum::Plane::PlaneIntersects::Intersects_Back; } - return (d > 0.0f) ? Plane::Intersects_Front : Plane::Intersects_Back; + + Vec3d negitive_v = box.max; + if (m_abcd[0] > 0.f) + negitive_v[0] = box.min.x(); + if (m_abcd[1] > 0.f) + negitive_v[1] = box.min.y(); + if (m_abcd[2] > 0.f) + negitive_v[2] = box.min.z(); + + float dis_negitive = distance(negitive_v.cast()); + + if (dis_negitive < 0.f) + { + return Frustum::Plane::PlaneIntersects::Intersects_Cross; + } + + return Frustum::Plane::PlaneIntersects::Intersects_Front; } Frustum::Plane::PlaneIntersects Frustum::Plane::intersects(const Vec3f &p0) const { @@ -51,19 +109,15 @@ Frustum::Plane::PlaneIntersects Frustum::Plane::intersects(const Vec3f &p0, cons return Plane::Intersects_Tangent; } -bool Frustum::intersects(const BoundingBoxf3 &box, bool is_perspective) const +bool Frustum::intersects(const BoundingBoxf3 &box) const { - if (is_perspective) { - for (auto &plane : planes) { - if (plane.intersects(box) == Plane::Intersects_Back) { - return false; - } + for (auto& plane : planes) { + const auto rt = plane.intersects(box); + if (Frustum::Plane::Intersects_Back == rt) { + return false; } } - // check box intersects - if (!bbox.intersects(box)) { - return false; - } + return true; } diff --git a/src/libslic3r/Frustum.hpp b/src/libslic3r/Frustum.hpp index 26b12e1dc..296333cee 100644 --- a/src/libslic3r/Frustum.hpp +++ b/src/libslic3r/Frustum.hpp @@ -13,17 +13,13 @@ public: class Plane { public: enum PlaneIntersects { Intersects_Cross = 0, Intersects_Tangent = 1, Intersects_Front = 2, Intersects_Back = 3 }; - void set(const Vec3f &n, const Vec3f &pt) - { - normal_ = n.normalized(); - center_ = pt; - d_ = -normal_.dot(pt); - } - float distance(const Vec3f &pt) const { return normal_.dot(pt) + d_; } + void set_abcd(float a, float b, float c, float d); + const Vec4f& get_abcd() const; + + void normailze(); + float distance(const Vec3f& pt) const; - inline const Vec3f &getNormal() const { return normal_; } - const Vec3f & getCenter() const { return center_; } Plane::PlaneIntersects intersects(const BoundingBoxf3 &box) const; //// check intersect with point (world space) Plane::PlaneIntersects intersects(const Vec3f &p0) const; @@ -32,12 +28,10 @@ public: // check intersect with triangle (world space) Plane::PlaneIntersects intersects(const Vec3f &p0, const Vec3f &p1, const Vec3f &p2) const; private: - Vec3f normal_; - Vec3f center_; - float d_ = 0; + Vec4f m_abcd; }; - bool intersects(const BoundingBoxf3 &box, bool is_perspective) const; + bool intersects(const BoundingBoxf3 &box) const; // check intersect with point (world space) bool intersects(const Vec3f &p0) const; // check intersect with line segment (world space) @@ -46,18 +40,6 @@ public: bool intersects(const Vec3f &p0, const Vec3f &p1, const Vec3f &p2) const; Plane planes[6]; - /* corners[0]: nearTopLeft; - * corners[1]: nearTopRight; - * corners[2]: nearBottomLeft; - * corners[3]: nearBottomRight; - * corners[4]: farTopLeft; - * corners[5]: farTopRight; - * corners[6]: farBottomLeft; - * corners[7]: farBottomRight; - */ - Vec3f corners[8]; - - BoundingBoxf3 bbox; }; enum FrustumClipMask { diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 5fc724ae5..748727d9a 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -152,38 +152,41 @@ void Bed3D::load_render_colors() void Bed3D::Axes::render() const { - auto render_axis = [this](const Transform3f& transform) { - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixf(transform.data())); - m_arrow.render(); - glsafe(::glPopMatrix()); + auto render_axis = [this](const Transform3d& transform, const std::shared_ptr& shader) { + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d view_matrix = camera.get_view_matrix(); + const Transform3d view_model_matrix = view_matrix * transform; + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_arrow.render_geometry(); }; if (!m_arrow.is_initialized()) const_cast(&m_arrow)->init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length)); - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; glsafe(::glEnable(GL_DEPTH_TEST)); - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("emission_factor", 0.0f); // x axis const_cast(&m_arrow)->set_color(-1, AXIS_X_COLOR); - render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }).cast()); + render_axis(Geometry::assemble_transform(m_origin, { 0.0, 0.5 * M_PI, 0.0 }), shader); // y axis const_cast(&m_arrow)->set_color(-1, AXIS_Y_COLOR); - render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }).cast()); + render_axis(Geometry::assemble_transform(m_origin, { -0.5 * M_PI, 0.0, 0.0 }), shader); // z axis const_cast(&m_arrow)->set_color(-1, AXIS_Z_COLOR); - render_axis(Geometry::assemble_transform(m_origin).cast()); + render_axis(Geometry::assemble_transform(m_origin), shader); - shader->stop_using(); + wxGetApp().unbind_shader(); glsafe(::glDisable(GL_DEPTH_TEST)); } @@ -548,9 +551,9 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const } if (m_triangles.get_vertices_count() > 0) { - GLShaderProgram* shader = wxGetApp().get_shader("printbed"); + const auto& shader = wxGetApp().get_shader("printbed"); if (shader != nullptr) { - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("transparent_background", bottom); shader->set_uniform("svg_source", boost::algorithm::iends_with(m_texture.get_source(), ".svg")); @@ -613,7 +616,7 @@ void Bed3D::render_system(GLCanvas3D& canvas, bool bottom) const if (bottom) glsafe(::glDepthMask(GL_TRUE)); - shader->stop_using(); + wxGetApp().unbind_shader(); } } }*/ @@ -689,9 +692,9 @@ void Bed3D::render_model() const const Camera & camera = wxGetApp().plater()->get_camera(); const Transform3d &view_matrix = camera.get_view_matrix(); const Transform3d &projection_matrix = camera.get_projection_matrix(); - GLShaderProgram* shader = wxGetApp().get_shader("hotbed"); + const auto& shader = wxGetApp().get_shader("hotbed"); if (shader != nullptr) { - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("emission_factor", 0.0f); const Transform3d model_matrix = Geometry::assemble_transform(m_model_offset); shader->set_uniform("volume_world_matrix", model_matrix); @@ -713,7 +716,7 @@ void Bed3D::render_model() const shader->set_uniform("print_volume.type", -1); } model->render_geometry(); - shader->stop_using(); + wxGetApp().unbind_shader(); } } } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index fc81fba1d..2f548a222 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -254,17 +254,26 @@ void GLIndexedVertexArray::release_geometry() this->clear(); } -void GLIndexedVertexArray::render() const +void GLIndexedVertexArray::render(const std::shared_ptr& shader) const { assert(this->vertices_and_normals_interleaved_VBO_id != 0); assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); - glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); - glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + int position_id = -1; + int normal_id = -1; + + position_id = shader->get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(::glEnableVertexAttribArray(position_id)); + } + normal_id = shader->get_attrib_location("v_normal"); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), nullptr)); + glsafe(::glEnableVertexAttribArray(normal_id)); + } // Render using the Vertex Buffer Objects. if (this->triangle_indices_size > 0) { @@ -278,30 +287,50 @@ void GLIndexedVertexArray::render() const glsafe(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (position_id != -1) { + glsafe(::glDisableVertexAttribArray(position_id)); + } + if (normal_id != -1) { + glsafe(::glDisableVertexAttribArray(normal_id)); + } glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } void GLIndexedVertexArray::render( + const std::shared_ptr& shader, const std::pair& tverts_range, const std::pair& qverts_range) const { - // this method has been called before calling finalize() ? - if (this->vertices_and_normals_interleaved_VBO_id == 0 && !this->vertices_and_normals_interleaved.empty()) + if (0 == vertices_and_normals_interleaved_VBO_id) { + if (!vertices_and_normals_interleaved.empty()) { + BOOST_LOG_TRIVIAL(info) << boost::format("finalize_geometry"); + const_cast(this)->finalize_geometry(true); + } + } + if (0 == vertices_and_normals_interleaved_VBO_id) { return; + } - assert(this->vertices_and_normals_interleaved_VBO_id != 0); - assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0); + if (0 == triangle_indices_VBO_id && 0 == quad_indices_VBO_id) { + return; + } // Render using the Vertex Buffer Objects. glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_and_normals_interleaved_VBO_id)); - glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); - glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), nullptr)); + int position_id = -1; + int normal_id = -1; - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + position_id = shader->get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(::glEnableVertexAttribArray(position_id)); + } + normal_id = shader->get_attrib_location("v_normal"); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), nullptr)); + glsafe(::glEnableVertexAttribArray(normal_id)); + } if (this->triangle_indices_size > 0) { glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->triangle_indices_VBO_id)); @@ -314,8 +343,12 @@ void GLIndexedVertexArray::render( glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (position_id != -1) { + glsafe(::glDisableVertexAttribArray(position_id)); + } + if (normal_id != -1) { + glsafe(::glDisableVertexAttribArray(normal_id)); + } glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } @@ -324,12 +357,21 @@ const float GLVolume::SinkingContours::HalfWidth = 0.25f; void GLVolume::SinkingContours::render() { + const auto& shader = GUI::wxGetApp().get_shader("flat"); + if (!shader) { + return; + } + + GUI::wxGetApp().bind_shader(shader); + update(); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(m_shift.x(), m_shift.y(), m_shift.z())); - m_model.render(); - glsafe(::glPopMatrix()); + const GUI::Camera& camera = GUI::wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::assemble_transform(m_shift)); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + m_model.render_geometry(); + + GUI::wxGetApp().unbind_shader(); } void GLVolume::SinkingContours::update() @@ -483,6 +525,7 @@ GLVolume::GLVolume(float r, float g, float b, float a, bool create_index_data) , force_native_color(false) , force_neutral_color(false) , force_sinking_contours(false) + , picking(false) , tverts_range(0, size_t(-1)) , qverts_range(0, size_t(-1)) , tverts_range_lod(0, size_t(-1)) @@ -777,7 +820,7 @@ void GLVolume::set_range(double min_z, double max_z) this->qverts_range.first = this->offsets[i * 2]; this->tverts_range.first = this->offsets[i * 2 + 1]; // Some layers are above $min_z. Which? - for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++ i); + for (; i < this->print_zs.size() && this->print_zs[i] <= max_z; ++ i); if (i < this->print_zs.size()) { this->qverts_range.second = this->offsets[i * 2]; this->tverts_range.second = this->offsets[i * 2 + 1]; @@ -789,7 +832,7 @@ void GLVolume::set_range(double min_z, double max_z) //BBS: add outline related logic //static unsigned char stencil_data[1284][2944]; -void GLVolume::render(bool with_outline, const std::array& body_color) const +void GLVolume::render(const Transform3d& view_matrix, bool with_outline, const std::array& body_color) const { if (!is_active) return; @@ -797,7 +840,6 @@ void GLVolume::render(bool with_outline, const std::array& body_color) if (this->is_left_handed()) glFrontFace(GL_CW); glsafe(::glCullFace(GL_BACK)); - glsafe(::glPushMatrix()); auto camera = GUI::wxGetApp().plater()->get_camera(); auto zoom = camera.get_zoom(); Transform3d vier_mat = camera.get_view_matrix(); @@ -845,8 +887,8 @@ void GLVolume::render(bool with_outline, const std::array& body_color) } } while (0); - if (color_volume) { - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); + const auto shader = GUI::wxGetApp().get_current_shader(); + if (color_volume && !picking) { std::vector> colors = GUI::wxGetApp().plater()->get_extruders_colors(); //when force_transparent, we need to keep the alpha @@ -854,7 +896,6 @@ void GLVolume::render(bool with_outline, const std::array& body_color) for (int index = 0; index < colors.size(); index ++) colors[index][3] = render_color[3]; } - glsafe(::glMultMatrixd(world_matrix().data())); for (int idx = 0; idx < mmuseg_ivas.size(); idx++) { GLIndexedVertexArray* iva = &mmuseg_ivas[idx]; if (iva->triangle_indices_size == 0 && iva->quad_indices_size == 0) @@ -886,7 +927,7 @@ void GLVolume::render(bool with_outline, const std::array& body_color) } } } - iva->render(this->tverts_range, this->qverts_range); + iva->render(shader, this->tverts_range, this->qverts_range); /*if (force_native_color && (render_color[3] < 1.0)) { BOOST_LOG_TRIVIAL(debug) << __FUNCTION__<< boost::format(", this %1%, name %2%, tverts_range {%3,%4}, qverts_range{%5%, %6%}") %this %this->name %this->tverts_range.first %this->tverts_range.second @@ -895,20 +936,18 @@ void GLVolume::render(bool with_outline, const std::array& body_color) } } else { - glsafe(::glMultMatrixd(world_matrix().data())); - auto render_which = [this](std::shared_ptr cur) { + auto render_which = [this](std::shared_ptr cur, const std::shared_ptr& shader) { if (cur->vertices_and_normals_interleaved_VBO_id > 0) { - cur->render(tverts_range_lod, qverts_range_lod); + cur->render(shader, tverts_range_lod, qverts_range_lod); } else {// if (cur->vertices_and_normals_interleaved_VBO_id == 0) if (cur->triangle_indices.size() > 0) { cur->finalize_geometry(true); - cur->render(tverts_range_lod, qverts_range_lod); + cur->render(shader, tverts_range_lod, qverts_range_lod); } else { - indexed_vertex_array->render(this->tverts_range, this->qverts_range); + indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range); } } }; - Transform3d world_tran = world_matrix(); m_lod_update_index++; if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY){ m_lod_update_index = 0; @@ -916,17 +955,17 @@ void GLVolume::render(bool with_outline, const std::array& body_color) m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]); } if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small) { - render_which(indexed_vertex_array_small); + render_which(indexed_vertex_array_small, shader); } else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle) { - render_which(indexed_vertex_array_middle); + render_which(indexed_vertex_array_middle, shader); } else { - this->indexed_vertex_array->render(this->tverts_range, this->qverts_range); + this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range); } } }; //BBS: add logic of outline rendering - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); + const auto shader = GUI::wxGetApp().get_current_shader(); //BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, with_outline %2%, shader %3%.")%__LINE__ %with_outline %shader; if (with_outline && shader != nullptr) { @@ -1031,13 +1070,11 @@ void GLVolume::render(bool with_outline, const std::array& body_color) shader->set_uniform("uniform_color", body_color); shader->set_uniform("is_outline", true); - glsafe(::glPopMatrix()); - glsafe(::glPushMatrix()); Transform3d matrix = world_matrix(); Transform3d world_tran = matrix; matrix.scale(scale); - glsafe(::glMultMatrixd(matrix.data())); + shader->set_uniform("view_model_matrix", view_matrix * matrix); m_lod_update_index++; if (abs(zoom - LAST_CAMERA_ZOOM_VALUE) > ZOOM_THRESHOLD || m_lod_update_index >= LOD_UPDATE_FREQUENCY) { m_lod_update_index = 0; @@ -1045,11 +1082,11 @@ void GLVolume::render(bool with_outline, const std::array& body_color) m_cur_lod_level = calc_volume_box_in_screen_bigger_than_threshold(transformed_bounding_box(), vier_proj_mat, viewport[2], viewport[3]); } if (m_cur_lod_level == LOD_LEVEL::SMALL && indexed_vertex_array_small && indexed_vertex_array_small->vertices_and_normals_interleaved_VBO_id > 0) { - this->indexed_vertex_array_small->render(this->tverts_range_lod, this->qverts_range_lod); + this->indexed_vertex_array_small->render(shader, this->tverts_range_lod, this->qverts_range_lod); } else if (m_cur_lod_level == LOD_LEVEL::MIDDLE && indexed_vertex_array_middle && indexed_vertex_array_middle->vertices_and_normals_interleaved_VBO_id > 0) { - this->indexed_vertex_array_middle->render(this->tverts_range_lod, this->qverts_range_lod); + this->indexed_vertex_array_middle->render(shader, this->tverts_range_lod, this->qverts_range_lod); } else { - this->indexed_vertex_array->render(this->tverts_range, this->qverts_range); + this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range); } //BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, outline render for body, shader name %2%")%__LINE__ %shader->get_name(); shader->set_uniform("is_outline", false); @@ -1066,18 +1103,16 @@ void GLVolume::render(bool with_outline, const std::array& body_color) render_body(); //BOOST_LOG_TRIVIAL(info) << boost::format(": %1%, normal render.")%__LINE__; } - glsafe(::glPopMatrix()); if (this->is_left_handed()) glFrontFace(GL_CCW); } //BBS add render for simple case -void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_objects, std::vector> &extruder_colors, bool ban_light) const +void GLVolume::simple_render(const std::shared_ptr& shader, ModelObjectPtrs &model_objects, std::vector> &extruder_colors, bool ban_light) const { if (this->is_left_handed()) glFrontFace(GL_CW); glsafe(::glCullFace(GL_BACK)); - glsafe(::glPushMatrix()); bool color_volume = false; ModelObject* model_object = nullptr; @@ -1108,8 +1143,7 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj } } while (0); - if (color_volume) { - glsafe(::glMultMatrixd(world_matrix().data())); + if (color_volume && !picking) { for (int idx = 0; idx < mmuseg_ivas.size(); idx++) { GLIndexedVertexArray& iva = mmuseg_ivas[idx]; if (iva.triangle_indices_size == 0 && iva.quad_indices_size == 0) @@ -1147,15 +1181,13 @@ void GLVolume::simple_render(GLShaderProgram *shader, ModelObjectPtrs &model_obj } } } - iva.render(this->tverts_range, this->qverts_range); + iva.render(shader, this->tverts_range, this->qverts_range); } } else { - glsafe(::glMultMatrixd(world_matrix().data())); - this->indexed_vertex_array->render(this->tverts_range, this->qverts_range); + this->indexed_vertex_array->render(shader, this->tverts_range, this->qverts_range); } - glsafe(::glPopMatrix()); if (this->is_left_handed()) glFrontFace(GL_CCW); } @@ -1195,7 +1227,7 @@ GLWipeTowerVolume::GLWipeTowerVolume(const std::vector>& co m_colors = colors; } -void GLWipeTowerVolume::render(bool with_outline,const std::array &body_color) const +void GLWipeTowerVolume::render(const Transform3d& view_matrix, bool with_outline,const std::array &body_color) const { if (!is_active) return; @@ -1203,22 +1235,28 @@ void GLWipeTowerVolume::render(bool with_outline,const std::array &bod if (m_colors.size() == 0 || m_colors.size() != iva_per_colors.size()) return; + const auto shader = GUI::wxGetApp().get_current_shader(); + if (!shader) { + return; + } + if (this->is_left_handed()) glFrontFace(GL_CW); glsafe(::glCullFace(GL_BACK)); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(world_matrix().data())); - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); for (int i = 0; i < m_colors.size(); i++) { - if (shader) { - std::array new_color = adjust_color_for_rendering(m_colors[i]); - shader->set_uniform("uniform_color", new_color); + if (!picking) { + ColorRGBA new_color = adjust_color_for_rendering(m_colors[i]); + std::array final_color; + final_color[0] = new_color.r(); + final_color[1] = new_color.g(); + final_color[2] = new_color.b(); + final_color[3] = new_color.a(); + shader->set_uniform("uniform_color", final_color); } - this->iva_per_colors[i].render(); + this->iva_per_colors[i].render(shader); } - glsafe(::glPopMatrix()); if (this->is_left_handed()) glFrontFace(GL_CCW); } @@ -1537,6 +1575,7 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d & view_matrix, + const Transform3d& projection_matrix, std::function filter_func, bool with_outline, const std::array & body_color, @@ -1547,7 +1586,7 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip if (to_render.empty()) return; - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); + const auto shader = GUI::wxGetApp().get_current_shader(); if (shader == nullptr) return; @@ -1563,7 +1602,7 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip auto camera = GUI::wxGetApp().plater()->get_camera(); for (GLVolumeWithIdAndZ& volume : to_render) { auto world_box = volume.first->transformed_bounding_box(); - if (!camera.getFrustum().intersects(world_box, camera.get_type_as_string() == "perspective")) { + if (!camera.getFrustum().intersects(world_box)) { continue; } #if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT @@ -1585,15 +1624,12 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip if (m_show_sinking_contours) if (volume.first->is_sinking() && !volume.first->is_below_printbed() && volume.first->hover == GLVolume::HS_None && !volume.first->force_sinking_contours) { - shader->stop_using(); + GUI::wxGetApp().unbind_shader(); volume.first->render_sinking_contours(); - shader->start_using(); + GUI::wxGetApp().bind_shader(shader); } } - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); - if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { shader->set_uniform("is_text_shape", volume.first->is_text_shape); shader->set_uniform("uniform_color", volume.first->render_color); @@ -1653,14 +1689,19 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip #endif // ENABLE_ENVIRONMENT_MAP glcheck(); + const Transform3d matrix = view_matrix * volume.first->world_matrix(); + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", projection_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + //BBS: add outline related logic auto red_color = std::array({ 1.0f, 0.0f, 0.0f, 1.0f });//slice_error - volume.first->render(with_outline&& volume.first->selected, volume.first->slice_error ? red_color : body_color); + volume.first->render(view_matrix, with_outline&& volume.first->selected, volume.first->slice_error ? red_color : body_color); } else { if (volume.first->selected) { shader->set_uniform("u_model_matrix", volume.first->world_matrix()); - volume.first->render(false, body_color); + volume.first->render(view_matrix, false, body_color); } } @@ -1671,9 +1712,6 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); } if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { @@ -1682,11 +1720,11 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip // render sinking contours of hovered/displaced volumes if (volume.first->is_sinking() && !volume.first->is_below_printbed() && (volume.first->hover != GLVolume::HS_None || volume.first->force_sinking_contours)) { - shader->stop_using(); + GUI::wxGetApp().unbind_shader(); glsafe(::glDepthFunc(GL_ALWAYS)); volume.first->render_sinking_contours(); glsafe(::glDepthFunc(GL_LESS)); - shader->start_using(); + GUI::wxGetApp().bind_shader(shader); } } } diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 5047c180c..ee7b21940 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -16,6 +16,7 @@ #include #include +#include #ifndef NDEBUG #define HAS_GLSAFE @@ -228,8 +229,8 @@ public: // Release the geometry data, release OpenGL VBOs. void release_geometry(); - void render() const; - void render(const std::pair& tverts_range, const std::pair& qverts_range) const; + void render(const std::shared_ptr& shader) const; + void render(const std::shared_ptr& shader, const std::pair& tverts_range, const std::pair& qverts_range) const; // Is there any geometry data stored? bool empty() const { return vertices_and_normals_interleaved_size == 0; } @@ -451,6 +452,7 @@ public: bool force_sinking_contours : 1; // slice error bool slice_error : 1; + bool picking : 1; }; // Is mouse or rectangle selection over this object to select/deselect it ? @@ -582,11 +584,12 @@ public: void set_range(double low, double high); //BBS: add outline related logic and add virtual specifier - virtual void render(bool with_outline = false, + virtual void render(const Transform3d& view_matrix, + bool with_outline = false, const std::array &body_color = {1.0f, 1.0f, 1.0f, 1.0f} ) const; //BBS: add simple render function for thumbnail - void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector>& extruder_colors,bool ban_light =false) const; + void simple_render(const std::shared_ptr& shader, ModelObjectPtrs& model_objects, std::vector>& extruder_colors,bool ban_light =false) const; void finalize_geometry(bool opengl_initialized) { this->indexed_vertex_array->finalize_geometry(opengl_initialized); } void release_geometry() { this->indexed_vertex_array->release_geometry(); } @@ -614,7 +617,7 @@ public: class GLWipeTowerVolume : public GLVolume { public: GLWipeTowerVolume(const std::vector>& colors); - virtual void render(bool with_outline = false, const std::array &body_color = {1.0f, 1.0f, 1.0f, 1.0f}) const; + void render(const Transform3d& view_matrix, bool with_outline = false, const std::array &body_color = {1.0f, 1.0f, 1.0f, 1.0f}) const override; std::vector iva_per_colors; bool IsTransparent(); @@ -727,6 +730,7 @@ public: ERenderType type, bool disable_cullface, const Transform3d & view_matrix, + const Transform3d& projection_matrix, std::function filter_func = std::function(), bool with_outline = true, const std::array & body_color = {1.0f, 1.0f, 1.0f, 1.0f}, diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index acda293f2..54b32e0f9 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -144,12 +144,27 @@ void Camera::select_view(ViewAngleType type) default: break; } } + +const Transform3d Camera::get_view_matrix_for_billboard() const +{ + Transform3d view_matrix_for_billboard{ Transform3d::Identity() }; + double gui_scale = get_gui_scale(); + view_matrix_for_billboard.data()[3 * 4 + 0] = 0.0f; + view_matrix_for_billboard.data()[3 * 4 + 1] = 0.0f; + view_matrix_for_billboard.data()[3 * 4 + 2] = -(get_near_z() + 0.10); + + view_matrix_for_billboard.data()[0 * 4 + 0] = gui_scale; + view_matrix_for_billboard.data()[1 * 4 + 1] = gui_scale; + view_matrix_for_billboard.data()[2 * 4 + 2] = 1.0f; + + return view_matrix_for_billboard; +} //how to use //BoundingBox bbox = mesh.aabb.transform(transform); //return camera_->getFrustum().intersects(bbox); void Camera::debug_frustum() { - ImGuiWrapper &imgui = *wxGetApp().imgui(); + /*ImGuiWrapper &imgui = *wxGetApp().imgui(); imgui.begin(std::string("Camera debug_frusm"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); Vec3f frustum_min = m_frustum.bbox.min.cast(); @@ -176,134 +191,63 @@ void Camera::debug_frustum() Vec3f center = m_frustum.planes[i].getCenter(); ImGui::InputFloat3(name.c_str(), center.data(), "%.6f", ImGuiInputTextFlags_ReadOnly); } - imgui.end(); + imgui.end();*/ } void Camera::update_frustum() { - Vec3f eye_ = get_position().cast(); - Vec3f center_ = get_target().cast(); - Vec3f up_ = get_dir_up().cast(); - float near_ = m_frustrum_zs.first; - float far_ = m_frustrum_zs.second; - float aspect_ = m_viewport[2] / (double)m_viewport[3]; - float fov_ = (float) Geometry::deg2rad(get_fov()); - float eps = 0.01; - if (m_last_eye.isApprox(eye_) && m_last_center.isApprox(center_) && m_last_up.isApprox(up_) - && abs(m_last_near - near_) < eps && abs(m_last_far - far_) < eps && - abs(m_last_aspect - aspect_) < eps && abs(m_last_fov - fov_) < eps && abs(m_last_zoom - m_zoom) < eps) { - return; - } - m_last_eye = eye_; - m_last_center = center_; - m_last_up = up_; - m_last_near = near_; - m_last_far = far_; - m_last_aspect = aspect_; - m_last_fov = fov_; - m_last_zoom = m_zoom; - Vec3f forward((center_ - eye_).normalized()); - Vec3f side((forward.cross(up_)).normalized()); - Vec3f up((side.cross(forward)).normalized()); + // see https://www8.cs.umu.se/kurser/5DV051/HT12/lab/plane_extraction.pdf + const auto vp = m_projection_matrix.matrix() * m_view_matrix.matrix(); + const auto& vp_matrix = vp.eval(); - float nearHeightHalf = near_ * std::tan(fov_ / 2.f); - float farHeightHalf = far_ * std::tan(fov_ / 2.f); - float nearWidthHalf = nearHeightHalf * aspect_; - float farWidthHalf = farHeightHalf * aspect_; + const auto vp_data = vp_matrix.data(); + // left + float a = vp_data[0 * 4 + 3] + vp_data[0 * 4 + 0]; + float b = vp_data[1 * 4 + 3] + vp_data[1 * 4 + 0]; + float c = vp_data[2 * 4 + 3] + vp_data[2 * 4 + 0]; + float d = vp_data[3 * 4 + 3] + vp_data[3 * 4 + 0]; + m_frustum.planes[0].set_abcd(a, b, c, d); + m_frustum.planes[0].normailze(); - // near plane - Vec3f nearCenter = eye_ + forward * near_; - Vec3f nearNormal = forward; - m_frustum.planes[0].set(nearNormal, nearCenter); + // right + a = vp_data[0 * 4 + 3] - vp_data[0 * 4 + 0]; + b = vp_data[1 * 4 + 3] - vp_data[1 * 4 + 0]; + c = vp_data[2 * 4 + 3] - vp_data[2 * 4 + 0]; + d = vp_data[3 * 4 + 3] - vp_data[3 * 4 + 0]; + m_frustum.planes[1].set_abcd(a, b, c, d); + m_frustum.planes[1].normailze(); - // far plane - Vec3f farCenter = eye_ + forward * far_; - Vec3f farNormal = -forward; - m_frustum.planes[1].set(farNormal, farCenter); - if (m_type == EType::Ortho) { - double right = 1.0 / m_projection_matrix.matrix()(0, 0) - 0.5 * m_projection_matrix.matrix()(0, 0) * m_projection_matrix.matrix()(0, 3); - double top = 1.0 / m_projection_matrix.matrix()(1, 1) - 0.5 * m_projection_matrix.matrix()(1, 1) * m_projection_matrix.matrix()(1, 3); - auto dz = (far_ - near_) / 2.0; - Vec3f center = eye_ + forward * (far_ + near_) /2.0f; - m_frustum.bbox.reset(); - Vec3f corner = farCenter + up * top + side * right; - m_frustum.bbox.merge(corner.cast()); + // bottom + a = vp_data[0 * 4 + 3] + vp_data[0 * 4 + 1]; + b = vp_data[1 * 4 + 3] + vp_data[1 * 4 + 1]; + c = vp_data[2 * 4 + 3] + vp_data[2 * 4 + 1]; + d = vp_data[3 * 4 + 3] + vp_data[3 * 4 + 1]; + m_frustum.planes[2].set_abcd(a, b, c, d); + m_frustum.planes[2].normailze(); - corner = farCenter - up * top + side * right; - m_frustum.bbox.merge(corner.cast()); + // top + a = vp_data[0 * 4 + 3] - vp_data[0 * 4 + 1]; + b = vp_data[1 * 4 + 3] - vp_data[1 * 4 + 1]; + c = vp_data[2 * 4 + 3] - vp_data[2 * 4 + 1]; + d = vp_data[3 * 4 + 3] - vp_data[3 * 4 + 1]; + m_frustum.planes[3].set_abcd(a, b, c, d); + m_frustum.planes[3].normailze(); - corner = farCenter + up * top - side * right; - m_frustum.bbox.merge(corner.cast()); + // near + a = vp_data[0 * 4 + 3] + vp_data[0 * 4 + 2]; + b = vp_data[1 * 4 + 3] + vp_data[1 * 4 + 2]; + c = vp_data[2 * 4 + 3] + vp_data[2 * 4 + 2]; + d = vp_data[3 * 4 + 3] + vp_data[3 * 4 + 2]; + m_frustum.planes[4].set_abcd(a, b, c, d); + m_frustum.planes[4].normailze(); - corner = farCenter - up * top - side * right; - m_frustum.bbox.merge(corner.cast()); - //nearCenter - corner = nearCenter + up * top + side * right; - m_frustum.bbox.merge(corner.cast()); - - corner = nearCenter - up * top + side * right; - m_frustum.bbox.merge(corner.cast()); - - corner = nearCenter + up * top - side * right; - m_frustum.bbox.merge(corner.cast()); - - corner = nearCenter - up * top - side * right; - m_frustum.bbox.merge(corner.cast()); - return; - } - // top plane - Vec3f topCenter = nearCenter + up * nearHeightHalf; - Vec3f topNormal = (topCenter - eye_).normalized().cross(side); - m_frustum.planes[2].set(topNormal, topCenter); - - // bottom plane - Vec3f bottomCenter = nearCenter - up * nearHeightHalf; - Vec3f bottomNormal = side.cross((bottomCenter - eye_).normalized()); - m_frustum.planes[3].set(bottomNormal, bottomCenter); - - // left plane - Vec3f leftCenter = nearCenter - side * nearWidthHalf; - Vec3f leftNormal = (leftCenter - eye_).normalized().cross(up); - m_frustum.planes[4].set(leftNormal, leftCenter); - - // right plane - Vec3f rightCenter = nearCenter + side * nearWidthHalf; - Vec3f rightNormal = up.cross((rightCenter - eye_).normalized()); - m_frustum.planes[5].set(rightNormal, rightCenter); - - //// 8 corners - Vec3f nearTopLeft = nearCenter + up * nearHeightHalf - side * nearWidthHalf; - Vec3f nearTopRight = nearCenter + up * nearHeightHalf + side * nearWidthHalf; - Vec3f nearBottomLeft = nearCenter - up * nearHeightHalf - side * nearWidthHalf; - Vec3f nearBottomRight = nearCenter - up * nearHeightHalf + side * nearWidthHalf; - - Vec3f farTopLeft = farCenter + up * farHeightHalf - side * farWidthHalf; - Vec3f farTopRight = farCenter + up * farHeightHalf + side * farWidthHalf; - Vec3f farBottomLeft = farCenter - up * farHeightHalf - side * farWidthHalf; - Vec3f farBottomRight = farCenter - up * farHeightHalf + side * farWidthHalf; - - m_frustum.corners[0] = nearTopLeft; - m_frustum.corners[1] = nearTopRight; - m_frustum.corners[2] = nearBottomLeft; - m_frustum.corners[3] = nearBottomRight; - m_frustum.corners[4] = farTopLeft; - m_frustum.corners[5] = farTopRight; - m_frustum.corners[6] = farBottomLeft; - m_frustum.corners[7] = farBottomRight; - // bounding box - auto double_min = std::numeric_limits::min(); - auto double_max = std::numeric_limits::max(); - m_frustum.bbox.min = Vec3d(double_max, double_max, double_max); - m_frustum.bbox.max = Vec3d(double_min, double_min, double_min); - for (auto &corner : m_frustum.corners) { - m_frustum.bbox.min[0] = std::min((float)m_frustum.bbox.min.x(), corner.x()); - m_frustum.bbox.min[1] = std::min((float)m_frustum.bbox.min.y(), corner.y()); - m_frustum.bbox.min[2] = std::min((float)m_frustum.bbox.min.z(), corner.z()); - - m_frustum.bbox.max[0] = std::max((float)m_frustum.bbox.max.x(), corner.x()); - m_frustum.bbox.max[1] = std::max((float)m_frustum.bbox.max.y(), corner.y()); - m_frustum.bbox.max[2] = std::max((float)m_frustum.bbox.max.z(), corner.z()); - } + // far + a = vp_data[0 * 4 + 3] - vp_data[0 * 4 + 2]; + b = vp_data[1 * 4 + 3] - vp_data[1 * 4 + 2]; + c = vp_data[2 * 4 + 3] - vp_data[2 * 4 + 2]; + d = vp_data[3 * 4 + 3] - vp_data[3 * 4 + 2]; + m_frustum.planes[5].set_abcd(a, b, c, d); + m_frustum.planes[5].normailze(); } double Camera::get_fov() const @@ -320,15 +264,11 @@ double Camera::get_fov() const void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h) { - glsafe(::glViewport(0, 0, w, h)); - glsafe(::glGetIntegerv(GL_VIEWPORT, m_viewport.data())); -} - -void Camera::apply_view_matrix() -{ - glsafe(::glMatrixMode(GL_MODELVIEW)); - glsafe(::glLoadIdentity()); - glsafe(::glMultMatrixd(m_view_matrix.data())); + glsafe(::glViewport(x, y, w, h)); + m_viewport[0] = x; + m_viewport[1] = y; + m_viewport[2] = w; + m_viewport[3] = h; } void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double far_z) @@ -336,11 +276,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa double w = 0.0; double h = 0.0; - const double old_distance = m_distance; m_frustrum_zs = calc_tight_frustrum_zs_around(box); - if (m_distance != old_distance) - // the camera has been moved re-apply view matrix - apply_view_matrix(); if (near_z > 0.0) m_frustrum_zs.first = std::max(std::min(m_frustrum_zs.first, near_z), FrustrumMinNearZ); @@ -374,26 +310,55 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa } } - glsafe(::glMatrixMode(GL_PROJECTION)); - glsafe(::glLoadIdentity()); - switch (m_type) { default: case EType::Ortho: { - glsafe(::glOrtho(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second)); + // see https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml + //glsafe(::glOrtho(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second)); + m_projection_matrix(0, 0) = 2.0f / (w - (-w)); + m_projection_matrix(0, 1) = 0.0f; + m_projection_matrix(0, 2) = 0.0f; + m_projection_matrix(0, 3) = -(w + (-w)) / (w - (-w)); + m_projection_matrix(1, 0) = 0.0f; + m_projection_matrix(1, 1) = 2.0f / (h - (-h)); + m_projection_matrix(1, 2) = 0.0f; + m_projection_matrix(1, 3) = -(h + (-h)) / (h - (-h)); + m_projection_matrix(2, 0) = 0.0f; + m_projection_matrix(2, 1) = 0.0f; + m_projection_matrix(2, 2) = -2.0f / (m_frustrum_zs.second - m_frustrum_zs.first); + m_projection_matrix(2, 3) = -(m_frustrum_zs.second + m_frustrum_zs.first) / (m_frustrum_zs.second - m_frustrum_zs.first); + m_projection_matrix(3, 0) = 0.0f; + m_projection_matrix(3, 1) = 0.0f; + m_projection_matrix(3, 2) = 0.0f; + m_projection_matrix(3, 3) = 1.0f; break; } case EType::Perspective: { - glsafe(::glFrustum(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second)); + // see https://registry.khronos.org/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml + //glsafe(::glFrustum(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second)); + m_projection_matrix(0, 0) = 2.0f * m_frustrum_zs.first / (w - (-w)); + m_projection_matrix(0, 1) = 0.0f; + m_projection_matrix(0, 2) = (w + (-w)) / (w - (-w)); + m_projection_matrix(0, 3) = 0.0f; + m_projection_matrix(1, 0) = 0.0f; + m_projection_matrix(1, 1) = 2.0f * m_frustrum_zs.first / (h - (-h)); + m_projection_matrix(1, 2) = (h + (-h)) / (h - (-h)); + m_projection_matrix(1, 3) = 0.0f; + m_projection_matrix(2, 0) = 0.0f; + m_projection_matrix(2, 1) = 0.0f; + m_projection_matrix(2, 2) = -(m_frustrum_zs.second + m_frustrum_zs.first) / (m_frustrum_zs.second - m_frustrum_zs.first); + m_projection_matrix(2, 3) = -2.0f * m_frustrum_zs.second * m_frustrum_zs.first / (m_frustrum_zs.second - m_frustrum_zs.first); + + m_projection_matrix(3, 0) = 0.0f; + m_projection_matrix(3, 1) = 0.0f; + m_projection_matrix(3, 2) = -1.0f; + m_projection_matrix(3, 3) = 0.0f; break; } } - - glsafe(::glGetDoublev(GL_PROJECTION_MATRIX, m_projection_matrix.data())); - glsafe(::glMatrixMode(GL_MODELVIEW)); } void Camera::zoom_to_box(const BoundingBoxf3& box, double margin_factor) diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index 239283ada..119b7e37f 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -109,6 +109,7 @@ public: const std::array& get_viewport() const { return m_viewport; } const Transform3d& get_view_matrix() const { return m_view_matrix; } const Transform3d& get_projection_matrix() const { return m_projection_matrix; } + const Transform3d get_view_matrix_for_billboard() const; //BBS const Eigen::Quaterniond& get_view_rotation() const {return m_view_rotation; } @@ -127,7 +128,6 @@ public: double get_fov() const; void apply_viewport(int x, int y, unsigned int w, unsigned int h); - void apply_view_matrix(); // Calculates and applies the projection matrix tighting the frustrum z range around the given box. // If larger z span is needed, pass the desired values of near and far z (negative values are ignored) void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index af62dc25d..e0bb102a8 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -362,24 +362,25 @@ void GCodeViewer::SequentialView::Marker::render(int canvas_width, int canvas_he if (!m_visible) return; - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("emission_factor", 0.0f); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixf(m_world_transform.data())); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d matrix = camera.get_view_matrix() * m_world_transform.cast(); + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); - m_model.render(); + m_model.render_geometry(); - glsafe(::glPopMatrix()); - - shader->stop_using(); + wxGetApp().unbind_shader(); glsafe(::glDisable(GL_BLEND)); @@ -911,11 +912,6 @@ void GCodeViewer::init(ConfigOptionMode mode, PresetBundle* preset_bundle) m_sequential_view.marker.init(filename); - // initializes point sizes - std::array point_sizes; - ::glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, point_sizes.data()); - m_detected_point_sizes = { static_cast(point_sizes[0]), static_cast(point_sizes[1]) }; - // BBS initialzed view_type items m_user_mode = mode; update_by_mode(m_user_mode); @@ -1395,7 +1391,6 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai camera.set_type(Camera::EType::Ortho); camera.set_target(center); camera.select_view("top"); - camera.apply_view_matrix(); camera.zoom_to_box(plate_box, 1.0f); camera.apply_projection(plate_box); @@ -1442,9 +1437,9 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai }; #if ENABLE_GCODE_VIEWER_STATISTICS - auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader) { + auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader, int position_id, int normal_id) { #else - auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader) { + auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader, int position_id, int normal_id) { #endif // ENABLE_GCODE_VIEWER_STATISTICS struct Range @@ -1460,12 +1455,16 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai const IBuffer& i_buffer = buffer.indices[j]; buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance; glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); - glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, buffer.vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); + glsafe(::glEnableVertexAttribArray(position_id)); + } bool has_normals = buffer.vertices.normal_size_floats() > 0; if (has_normals) { - glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, buffer.vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); + glsafe(::glEnableVertexAttribArray(normal_id)); + } } glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); @@ -1489,10 +1488,11 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - if (has_normals) - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (normal_id != -1) + glsafe(::glDisableVertexAttribArray(normal_id)); + if (position_id != -1) + glsafe(::glDisableVertexAttribArray(position_id)); - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); buffer_range.first = buffer_range.last; @@ -1508,9 +1508,16 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai if (!buffer.visible || !buffer.has_data()) continue; - GLShaderProgram* shader = opengl_manager.get_shader("cali"); + const auto& shader = opengl_manager.get_shader("flat"); if (shader != nullptr) { - shader->start_using(); + opengl_manager.bind_shader(shader); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + shader->set_uniform("view_model_matrix", view_matrix); + shader->set_uniform("projection_matrix", proj_matrix); + + int position_id = shader->get_attrib_location("v_position"); + int normal_id = shader->get_attrib_location("v_normal"); if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { //shader->set_uniform("emission_factor", 0.25f); @@ -1519,7 +1526,7 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai } else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { //shader->set_uniform("emission_factor", 0.25f); - render_as_batched_model(buffer, *shader); + render_as_batched_model(buffer, *shader, position_id, normal_id); //shader->set_uniform("emission_factor", 0.0f); } else { @@ -1537,12 +1544,17 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai continue; glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); - glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, buffer.vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); + glsafe(::glEnableVertexAttribArray(position_id)); + } bool has_normals = false;// buffer.vertices.normal_size_floats() > 0; if (has_normals) { - glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, buffer.vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); + glsafe(::glEnableVertexAttribArray(normal_id)); + } } glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); @@ -1559,15 +1571,16 @@ void GCodeViewer::_render_calibration_thumbnail_internal(ThumbnailData& thumbnai glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - if (has_normals) - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (normal_id != -1) + glsafe(::glDisableVertexAttribArray(normal_id)); + if (position_id != -1) + glsafe(::glDisableVertexAttribArray(position_id)); - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } } - shader->stop_using(); + opengl_manager.unbind_shader(); } else { BOOST_LOG_TRIVIAL(info) << boost::format("render_calibration_thumbnail: can not find shader"); @@ -4004,17 +4017,30 @@ void GCodeViewer::render_toolpaths() }; Range buffer_range = { 0, 0 }; size_t indices_per_instance = buffer.model.data.indices_count(); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d& view_matrix = camera.get_view_matrix(); + shader.set_uniform("view_model_matrix", view_matrix); + shader.set_uniform("projection_matrix", camera.get_projection_matrix()); + shader.set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); for (size_t j = 0; j < buffer.indices.size(); ++j) { const IBuffer& i_buffer = buffer.indices[j]; buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance; glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); - glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + + const int position_id = shader.get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, buffer.vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); + glsafe(::glEnableVertexAttribArray(position_id)); + } bool has_normals = buffer.vertices.normal_size_floats() > 0; + int normal_id = -1; if (has_normals) { - glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + normal_id = shader.get_attrib_location("v_normal"); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, buffer.vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); + glsafe(::glEnableVertexAttribArray(normal_id)); + } } glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); @@ -4038,10 +4064,11 @@ void GCodeViewer::render_toolpaths() glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - if (has_normals) - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (normal_id != -1) + glsafe(::glDisableVertexAttribArray(normal_id)); + if (position_id != -1) + glsafe(::glDisableVertexAttribArray(position_id)); - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); buffer_range.first = buffer_range.last; @@ -4056,14 +4083,18 @@ void GCodeViewer::render_toolpaths() unsigned char end_id = buffer_id(EMoveType::Count); //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":begin_id %1%, end_id %2% ")%(int)begin_id %(int)end_id; + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); for (unsigned char i = begin_id; i < end_id; ++i) { TBuffer& buffer = m_buffers[i]; if (!buffer.visible || !buffer.has_data()) continue; - - GLShaderProgram* shader = wxGetApp().get_shader(buffer.shader.c_str()); + const auto& shader = wxGetApp().get_shader(buffer.shader.c_str()); if (shader != nullptr) { - shader->start_using(); + wxGetApp().bind_shader(shader); + const Transform3d& view_matrix = camera.get_view_matrix(); + shader->set_uniform("view_model_matrix", view_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { shader->set_uniform("emission_factor", 0.25f); @@ -4095,12 +4126,20 @@ void GCodeViewer::render_toolpaths() continue; glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); - glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + + const int position_id = shader->get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, buffer.vertices.position_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); + glsafe(::glEnableVertexAttribArray(position_id)); + } bool has_normals = buffer.vertices.normal_size_floats() > 0; + int normal_id = -1; if (has_normals) { - glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + normal_id = shader->get_attrib_location("v_normal"); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, buffer.vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); + glsafe(::glEnableVertexAttribArray(normal_id)); + } } glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); @@ -4113,7 +4152,7 @@ void GCodeViewer::render_toolpaths() break; } case TBuffer::ERenderPrimitiveType::Line: { - glsafe(::glLineWidth(static_cast(line_width(zoom)))); + p_ogl_manager->set_line_width(static_cast(line_width(zoom))); render_as_lines(it_path, buffer.render_paths.rend(), *shader, uniform_color); break; } @@ -4126,15 +4165,16 @@ void GCodeViewer::render_toolpaths() glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - if (has_normals) - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (normal_id != -1) + glsafe(::glDisableVertexAttribArray(normal_id)); + if (position_id != -1) + glsafe(::glDisableVertexAttribArray(position_id)); - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } } - shader->stop_using(); + wxGetApp().unbind_shader(); } } @@ -4144,17 +4184,29 @@ void GCodeViewer::render_toolpaths() auto render_sequential_range_cap = [] #endif // ENABLE_GCODE_VIEWER_STATISTICS (const SequentialRangeCap& cap) { - GLShaderProgram* shader = wxGetApp().get_shader(cap.buffer->shader.c_str()); + const auto& shader = wxGetApp().get_shader(cap.buffer->shader.c_str()); if (shader != nullptr) { - shader->start_using(); + wxGetApp().bind_shader(shader); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d& view_matrix = camera.get_view_matrix(); + shader->set_uniform("view_model_matrix", view_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, cap.vbo)); - glsafe(::glVertexPointer(cap.buffer->vertices.position_size_floats(), GL_FLOAT, cap.buffer->vertices.vertex_size_bytes(), (const void*)cap.buffer->vertices.position_offset_bytes())); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + const int position_id = shader->get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, cap.buffer->vertices.position_size_floats(), GL_FLOAT, GL_FALSE, cap.buffer->vertices.vertex_size_bytes(), (const void*)cap.buffer->vertices.position_offset_bytes())); + glsafe(::glEnableVertexAttribArray(position_id)); + } bool has_normals = cap.buffer->vertices.normal_size_floats() > 0; + int normal_id = -1; if (has_normals) { - glsafe(::glNormalPointer(GL_FLOAT, cap.buffer->vertices.vertex_size_bytes(), (const void*)cap.buffer->vertices.normal_offset_bytes())); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + normal_id = shader->get_attrib_location("v_normal"); + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, cap.buffer->vertices.normal_size_floats(), GL_FLOAT, GL_FALSE, cap.buffer->vertices.vertex_size_bytes(), (const void*)cap.buffer->vertices.normal_offset_bytes())); + glsafe(::glEnableVertexAttribArray(normal_id)); + } } shader->set_uniform("uniform_color", cap.color); @@ -4167,13 +4219,14 @@ void GCodeViewer::render_toolpaths() ++m_statistics.gl_triangles_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS - if (has_normals) - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + if (normal_id != -1) + glsafe(::glDisableVertexAttribArray(normal_id)); + if (position_id != -1) + glsafe(::glDisableVertexAttribArray(position_id)); - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - shader->stop_using(); + wxGetApp().unbind_shader(); } }; @@ -4190,7 +4243,7 @@ void GCodeViewer::render_shells() //if (!m_shells.visible || m_shells.volumes.empty()) return; - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; @@ -4203,10 +4256,13 @@ void GCodeViewer::render_shells() } glsafe(::glDepthMask(GL_FALSE)); - shader->start_using(); + wxGetApp().bind_shader(shader); //BBS: reopen cul faces - m_shells.volumes.render(GUI::ERenderPipelineStage::Normal, GLVolumeCollection::ERenderType::Transparent, false, wxGetApp().plater()->get_camera().get_view_matrix()); - shader->stop_using(); + const auto& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); + m_shells.volumes.render(GUI::ERenderPipelineStage::Normal, GLVolumeCollection::ERenderType::Transparent, false, view_matrix, projection_matrix); + wxGetApp().unbind_shader(); glsafe(::glDepthMask(GL_TRUE)); } diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 73786c4be..af22b5d1e 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -806,7 +806,6 @@ private: #if ENABLE_GCODE_VIEWER_STATISTICS Statistics m_statistics; #endif // ENABLE_GCODE_VIEWER_STATISTICS - std::array m_detected_point_sizes = { 0.0f, 0.0f }; GCodeProcessorResult::SettingsIds m_settings_ids; std::array m_sequential_range_caps; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 3497bb88f..c34b604f2 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -165,16 +165,23 @@ GLCanvas3D::LayersEditing::~LayersEditing() m_z_texture_id = 0; } delete m_slicing_parameters; + + m_background.reset(); + m_baseline.reset(); + m_profile_curve.reset(); } const float GLCanvas3D::LayersEditing::THICKNESS_BAR_WIDTH = 70.0f; void GLCanvas3D::LayersEditing::init() { + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + const auto& gl_info = p_ogl_manager->get_gl_info(); + const auto formated_gl_version = gl_info.get_formated_gl_version(); glsafe(::glGenTextures(1, (GLuint*)&m_z_texture_id)); glsafe(::glBindTexture(GL_TEXTURE_2D, m_z_texture_id)); - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)); - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, formated_gl_version >= 30 ? GL_CLAMP_TO_EDGE : GL_CLAMP)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, formated_gl_version >= 30 ? GL_CLAMP_TO_EDGE : GL_CLAMP)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST)); glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1)); @@ -206,6 +213,7 @@ void GLCanvas3D::LayersEditing::select_object(const Model& model, int object_id) this->last_object_id = object_id; m_model_object = model_object_new; m_object_max_z = new_max_z; + m_profile_dirty = true; } } @@ -370,8 +378,8 @@ void GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(const GLCanv void GLCanvas3D::LayersEditing::render_overlay(const GLCanvas3D& canvas) { render_variable_layer_height_dialog(canvas); + render_background_texture(canvas); const Rect& bar_rect = get_bar_rect_viewport(canvas); - render_background_texture(canvas, bar_rect); render_curve(bar_rect); } @@ -446,16 +454,24 @@ std::string GLCanvas3D::LayersEditing::get_tooltip(const GLCanvas3D& canvas) con return ret; } -void GLCanvas3D::LayersEditing::render_background_texture(const GLCanvas3D& canvas, const Rect& bar_rect) +void GLCanvas3D::LayersEditing::render_background_texture(const GLCanvas3D& canvas) { if (!m_enabled) return; - GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height"); + const Size cnv_size = canvas.get_canvas_size(); + const int cnv_width = cnv_size.get_width(); + const int cnv_height = cnv_size.get_height(); + if (cnv_width == 0 || cnv_height == 0) + return; + + const float cnv_inv_width = 1.0f / static_cast(cnv_width); + + const auto& shader = wxGetApp().get_shader("variable_layer_height"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("z_to_texture_row", float(m_layers_texture.cells - 1) / (float(m_layers_texture.width) * m_object_max_z)); shader->set_uniform("z_texture_row_to_normalized", 1.0f / (float)m_layers_texture.height); @@ -463,26 +479,67 @@ void GLCanvas3D::LayersEditing::render_background_texture(const GLCanvas3D& canv shader->set_uniform("z_cursor_band_width", band_width); shader->set_uniform("object_max_z", m_object_max_z); + const auto thickness = thickness_bar_width(canvas) * cnv_inv_width; + if (abs(thickness - m_cached_background_thickness) > 1e-6f) + { + const float l = 1.0f - 2.0f * thickness; + const float r = 1.0f; + const float t = 1.0f; + const float b = -1.0f; + + const float center_x = (l + r) * 0.5f; + const float center_y = (t + b) * 0.5f; + const float center_z = 0.0f; + const float scale_x = r - l; + const float scale_y = t - b; + const float scale_z = 0.0f; + + m_model_matrix_for_background = Transform3d::Identity(); + m_model_matrix_for_background.data()[3 * 4 + 0] = center_x; + m_model_matrix_for_background.data()[3 * 4 + 1] = center_y; + m_model_matrix_for_background.data()[3 * 4 + 2] = center_z; + + m_model_matrix_for_background.data()[0 * 4 + 0] = scale_x; + m_model_matrix_for_background.data()[1 * 4 + 1] = scale_y; + m_model_matrix_for_background.data()[2 * 4 + 2] = scale_z; + + m_normal_matrix_for_background = (Matrix3d)m_model_matrix_for_background.matrix().block(0, 0, 3, 3).inverse().transpose(); + + m_cached_background_thickness = thickness; + } + + shader->set_uniform("view_model_matrix", m_model_matrix_for_background); + shader->set_uniform("projection_matrix", Transform3d::Identity()); + shader->set_uniform("normal_matrix", m_normal_matrix_for_background); + glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1)); glsafe(::glBindTexture(GL_TEXTURE_2D, m_z_texture_id)); // Render the color bar - const float l = bar_rect.get_left(); - const float r = bar_rect.get_right(); - const float t = bar_rect.get_top(); - const float b = bar_rect.get_bottom(); + if (!m_background.is_initialized()) { + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P2T2 }; + init_data.reserve_vertices(4); + init_data.reserve_indices(6); - ::glBegin(GL_QUADS); - ::glNormal3f(0.0f, 0.0f, 1.0f); - ::glTexCoord2f(0.0f, 0.0f); ::glVertex2f(l, b); - ::glTexCoord2f(1.0f, 0.0f); ::glVertex2f(r, b); - ::glTexCoord2f(1.0f, 1.0f); ::glVertex2f(r, t); - ::glTexCoord2f(0.0f, 1.0f); ::glVertex2f(l, t); - glsafe(::glEnd()); + // vertices + init_data.add_vertex(Vec2f(-0.5f, -0.5f), Vec2f(0.0f, 0.0f)); + init_data.add_vertex(Vec2f(0.5f, -0.5f), Vec2f(1.0f, 0.0f)); + init_data.add_vertex(Vec2f(0.5f, 0.5f), Vec2f(1.0f, 1.0f)); + init_data.add_vertex(Vec2f(-0.5f, 0.5f), Vec2f(0.0f, 1.0f)); + + // indices + init_data.add_triangle(0, 1, 2); + init_data.add_triangle(2, 3, 0); + + m_background.init_from(std::move(init_data)); + } + + m_background.render_geometry(); glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); - shader->stop_using(); + wxGetApp().unbind_shader(); } void GLCanvas3D::LayersEditing::render_curve(const Rect & bar_rect) @@ -494,24 +551,78 @@ void GLCanvas3D::LayersEditing::render_curve(const Rect & bar_rect) if (!m_slicing_parameters) return; + const auto& shader = wxGetApp().get_shader("flat"); + if (!shader) { + return; + } + + wxGetApp().bind_shader(shader); // Make the vertical bar a bit wider so the layer height curve does not touch the edge of the bar region. const float scale_x = bar_rect.get_width() / float(1.12 * m_slicing_parameters->max_layer_height); const float scale_y = bar_rect.get_height() / m_object_max_z; const float x = bar_rect.get_left() + float(m_slicing_parameters->layer_height) * scale_x; - // Baseline - glsafe(::glColor3f(0.0f, 0.0f, 0.0f)); - ::glBegin(GL_LINE_STRIP); - ::glVertex2f(x, bar_rect.get_bottom()); - ::glVertex2f(x, bar_rect.get_top()); - glsafe(::glEnd()); + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d view_matrix = camera.get_view_matrix_for_billboard(); + + Transform3d model_matrix{ Transform3d::Identity() }; + model_matrix.data()[3 * 4 + 0] = x; + model_matrix.data()[3 * 4 + 1] = (bar_rect.get_top() + bar_rect.get_bottom()) * 0.5f; + model_matrix.data()[0 * 4 + 0] = 0.0f; + model_matrix.data()[1 * 4 + 1] = (bar_rect.get_top() - bar_rect.get_bottom()); + + const auto& projection_matrix = camera.get_projection_matrix(); + shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + shader->set_uniform("projection_matrix", projection_matrix); + + if (!m_baseline.is_initialized()) { + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(2); + init_data.reserve_indices(2); + + // vertices + init_data.add_vertex(Vec3f(0.0f, -0.5f, 0.0f)); + init_data.add_vertex(Vec3f(0.0f, 0.5f, 0.0f)); + + // indices + init_data.add_line(0, 1); + + m_baseline.init_from(std::move(init_data)); + } + m_baseline.set_color({ 0.0f, 0.0f, 0.0f , 1.0f}); + m_baseline.render_geometry(); // Curve - glsafe(::glColor3f(0.0f, 0.0f, 1.0f)); - ::glBegin(GL_LINE_STRIP); - for (unsigned int i = 0; i < m_layer_height_profile.size(); i += 2) - ::glVertex2f(bar_rect.get_left() + (float)m_layer_height_profile[i + 1] * scale_x, bar_rect.get_bottom() + (float)m_layer_height_profile[i] * scale_y); - glsafe(::glEnd()); + + Transform3d model_matrix_curve{ Transform3d::Identity() }; + model_matrix_curve.data()[3 * 4 + 0] = bar_rect.get_left(); + model_matrix_curve.data()[3 * 4 + 1] = bar_rect.get_bottom(); + model_matrix_curve.data()[0 * 4 + 0] = scale_x; + model_matrix_curve.data()[1 * 4 + 1] = scale_y; + shader->set_uniform("view_model_matrix", view_matrix * model_matrix_curve); + + if (!m_profile_curve.is_initialized() || m_profile_dirty) { + m_profile_curve.reset(); + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(m_layer_height_profile.size() / 2); + init_data.reserve_indices(m_layer_height_profile.size() / 2); + + // vertices + for (unsigned int i = 0; i < m_layer_height_profile.size(); i += 2) { + init_data.add_vertex(Vec3f((float)m_layer_height_profile[i + 1], (float)m_layer_height_profile[i], 0.0f)); + init_data.add_index(i / 2); + } + + m_profile_curve.init_from(std::move(init_data)); + + m_profile_dirty = false; + } + m_profile_curve.set_color({ 0.0f, 0.0f, 1.0f , 1.0f }); + m_profile_curve.render_geometry(); + + wxGetApp().unbind_shader(); } void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const GLVolumeCollection & volumes)//render volume and layer height texture (has mapping relation with each other) @@ -519,16 +630,16 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const assert(this->is_allowed()); assert(this->last_object_id != -1); - GLShaderProgram* current_shader = wxGetApp().get_current_shader(); - ScopeGuard guard([current_shader]() { if (current_shader != nullptr) current_shader->start_using(); }); + const auto& current_shader = wxGetApp().get_current_shader(); + ScopeGuard guard([current_shader]() { if (current_shader != nullptr) wxGetApp().bind_shader(current_shader); }); if (current_shader != nullptr) - current_shader->stop_using(); + wxGetApp().unbind_shader(); - GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height"); + const auto& shader = wxGetApp().get_shader("variable_layer_height"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); generate_layer_height_texture(); @@ -538,6 +649,11 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const shader->set_uniform("z_cursor", float(m_object_max_z) * float(this->get_cursor_z_relative(canvas))); shader->set_uniform("z_cursor_band_width", float(this->band_width)); + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); + shader->set_uniform("projection_matrix", projection_matrix); + // Initialize the layer height texture mapping. const GLsizei w = (GLsizei)m_layers_texture.width; const GLsizei h = (GLsizei)m_layers_texture.height; @@ -557,7 +673,11 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D & canvas, const shader->set_uniform("volume_world_matrix", glvolume->world_matrix()); shader->set_uniform("object_max_z", 0.0f); - glvolume->render(); + const Transform3d view_model_matrix = view_matrix * glvolume->world_matrix(); + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + + glvolume->render(view_matrix); } // Revert back to the previous shader. glBindTexture(GL_TEXTURE_2D, 0); @@ -569,6 +689,7 @@ void GLCanvas3D::LayersEditing::adjust_layer_height_profile() PrintObject::update_layer_height_profile(*m_model_object, *m_slicing_parameters, m_layer_height_profile); Slic3r::adjust_layer_height_profile(*m_slicing_parameters, m_layer_height_profile, this->last_z, this->strength, this->band_width, this->last_action); m_layers_texture.valid = false; + m_profile_dirty = true; } void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D & canvas) @@ -578,6 +699,7 @@ void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D & canvas) m_layers_texture.valid = false; canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); wxGetApp().obj_list()->update_info_items(last_object_id); + m_profile_dirty = true; } void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D & canvas, float quality_factor) @@ -588,6 +710,7 @@ void GLCanvas3D::LayersEditing::adaptive_layer_height_profile(GLCanvas3D & canva m_layers_texture.valid = false; canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); wxGetApp().obj_list()->update_info_items(last_object_id); + m_profile_dirty = true; } void GLCanvas3D::LayersEditing::smooth_layer_height_profile(GLCanvas3D & canvas, const HeightProfileSmoothingParams & smoothing_params) @@ -598,6 +721,7 @@ void GLCanvas3D::LayersEditing::smooth_layer_height_profile(GLCanvas3D & canvas, m_layers_texture.valid = false; canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); wxGetApp().obj_list()->update_info_items(last_object_id); + m_profile_dirty = true; } void GLCanvas3D::LayersEditing::generate_layer_height_texture() @@ -906,6 +1030,12 @@ void GLCanvas3D::Tooltip::render(const Vec2d& mouse_position, GLCanvas3D& canvas } //BBS: add height limit logic + +GLCanvas3D::SequentialPrintClearance::~SequentialPrintClearance() +{ + reset(); +} + void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons, const std::vector>& height_polygons) { //BBS: add height limit logic @@ -918,50 +1048,29 @@ void GLCanvas3D::SequentialPrintClearance::set_polygons(const Polygons& polygons const size_t vertices_count = 3 * triangles_count; if (m_render_fill) { - GLModel::InitializationData fill_data; - GLModel::InitializationData::Entity entity; - entity.type = GLModel::PrimitiveType::Triangles; - entity.color = {0.8f, 0.8f, 1.0f, 0.5f}; - entity.positions.reserve(vertices_count); - entity.normals.reserve(vertices_count); - entity.indices.reserve(vertices_count); + GLModel::Geometry fill_data; + fill_data.format = {GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3}; + fill_data.color = {0.8f, 0.8f, 1.0f, 0.5f}; - const ExPolygons polygons_union = union_ex(polygons); + // vertices + indices + const ExPolygons polygons_union = union_ex(polygons); + unsigned int vertices_counter = 0; for (const ExPolygon &poly : polygons_union) { const std::vector triangulation = triangulate_expolygon_3d(poly); + fill_data.reserve_vertices(fill_data.vertices_count() + triangulation.size()); + fill_data.reserve_indices(fill_data.indices_count() + triangulation.size()); for (const Vec3d &v : triangulation) { - entity.positions.emplace_back(v.cast() + Vec3f(0.0f, 0.0f, 0.0125f)); // add a small positive z to avoid z-fighting - entity.normals.emplace_back(Vec3f::UnitZ()); - const size_t positions_count = entity.positions.size(); - if (positions_count % 3 == 0) { - entity.indices.emplace_back(positions_count - 3); - entity.indices.emplace_back(positions_count - 2); - entity.indices.emplace_back(positions_count - 1); - } + fill_data.add_vertex((Vec3f) (v.cast() + 0.0125f * Vec3f::UnitZ())); // add a small positive z to avoid z-fighting + ++vertices_counter; + if (vertices_counter % 3 == 0) + fill_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); } } + m_fill.init_from(std::move(fill_data)); - fill_data.entities.emplace_back(entity); - m_fill.init_from(fill_data); } - GLModel::InitializationData perimeter_data; - for (const Polygon &poly : polygons) { - GLModel::InitializationData::Entity ent; - ent.type = GLModel::PrimitiveType::LineLoop; - ent.positions.reserve(poly.points.size()); - ent.indices.reserve(poly.points.size()); - unsigned int id_count = 0; - for (const Point &p : poly.points) { - ent.positions.emplace_back(unscale(p.x()), unscale(p.y()), 0.025f); // add a small positive z to avoid z-fighting - ent.normals.emplace_back(Vec3f::UnitZ()); - ent.indices.emplace_back(id_count++); - } - - perimeter_data.entities.emplace_back(ent); - } - - m_perimeter.init_from(perimeter_data); + m_perimeter.init_model_from_polygon(polygons, 0.025f); } //BBS: add the height limit compute logic @@ -1004,11 +1113,15 @@ void GLCanvas3D::SequentialPrintClearance::render() std::array FILL_COLOR = { 0.7f, 0.7f, 1.0f, 0.5f }; std::array NO_FILL_COLOR = { 0.75f, 0.75f, 0.75f, 0.75f }; - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader("flat"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); + + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix()); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_CULL_FACE)); @@ -1016,17 +1129,24 @@ void GLCanvas3D::SequentialPrintClearance::render() glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); m_perimeter.set_color(-1, m_render_fill ? FILL_COLOR : NO_FILL_COLOR); - m_perimeter.render(); - m_fill.render(); + m_perimeter.render_geometry(); + m_fill.render_geometry(); //BBS: add height limit m_height_limit.set_color(-1, m_render_fill ? FILL_COLOR : NO_FILL_COLOR); - m_height_limit.render(); + m_height_limit.render_geometry(); glsafe(::glDisable(GL_BLEND)); glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glDisable(GL_DEPTH_TEST)); - shader->stop_using(); + wxGetApp().unbind_shader(); +} + +void GLCanvas3D::SequentialPrintClearance::reset() +{ + m_height_limit.reset(); + m_fill.reset(); + m_perimeter.reset(); } wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent); @@ -1224,6 +1344,29 @@ GLCanvas3D::~GLCanvas3D() m_sel_plate_toolbar.del_all_item(); m_sel_plate_toolbar.del_stats_item(); + + m_full_screen_mesh.reset(); + m_unit_cube.reset(); +#if ENABLE_SHOW_CAMERA_TARGET + m_camera_target_mark.reset(); +#endif // ENABLE_SHOW_CAMERA_TARGET + + m_sequential_print_clearance.reset(); +} + +void GLCanvas3D::set_context(wxGLContext* context) +{ + if (context != m_context) { + m_context = context; + m_dirty_context = true; + } +} + +void GLCanvas3D::set_type(ECanvasType type) +{ + if (type != m_canvas_type) { + m_canvas_type = type; + } } void GLCanvas3D::post_event(wxEvent &&event) @@ -1258,32 +1401,6 @@ bool GLCanvas3D::init() glsafe(::glDisable(GL_LINE_SMOOTH)); glsafe(::glDisable(GL_POLYGON_SMOOTH)); - // ambient lighting - GLfloat ambient[4] = { 0.3f, 0.3f, 0.3f, 1.0f }; - glsafe(::glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient)); - - glsafe(::glEnable(GL_LIGHT0)); - glsafe(::glEnable(GL_LIGHT1)); - - // light from camera - GLfloat specular_cam[4] = { 0.3f, 0.3f, 0.3f, 1.0f }; - glsafe(::glLightfv(GL_LIGHT1, GL_SPECULAR, specular_cam)); - GLfloat diffuse_cam[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; - glsafe(::glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse_cam)); - - // light from above - GLfloat specular_top[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; - glsafe(::glLightfv(GL_LIGHT0, GL_SPECULAR, specular_top)); - GLfloat diffuse_top[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; - glsafe(::glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_top)); - - // Enables Smooth Color Shading; try GL_FLAT for (lack of) fun. - glsafe(::glShadeModel(GL_SMOOTH)); - - // A handy trick -- have surface material mirror the color. - glsafe(::glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)); - glsafe(::glEnable(GL_COLOR_MATERIAL)); - if (m_multisample_allowed) glsafe(::glEnable(GL_MULTISAMPLE)); @@ -1397,7 +1514,7 @@ void GLCanvas3D::reset_volumes() if (m_volumes.empty()) return; - _set_current(); + _set_current(true); m_selection.clear(); m_volumes.clear(); @@ -1980,7 +2097,12 @@ float GLCanvas3D::get_collapse_toolbar_height() } bool GLCanvas3D::make_current_for_postinit() { - return _set_current(); + return _set_current(true); +} + +void GLCanvas3D::mark_context_dirty() +{ + m_dirty_context = true; } void GLCanvas3D::render(bool only_init) @@ -2003,7 +2125,7 @@ void GLCanvas3D::render(bool only_init) return; // ensures this canvas is current and initialized - if (!_is_shown_on_screen() || !_set_current() || !wxGetApp().init_opengl()) + if (!_is_shown_on_screen() || !_set_current(true) || !wxGetApp().init_opengl()) return; if (!is_initialized() && !init()) @@ -2056,13 +2178,10 @@ void GLCanvas3D::render(bool only_init) camera.requires_zoom_to_volumes = false; } - camera.apply_view_matrix(); camera.apply_projection(_max_bounding_box(true, true, true)); + camera.update_frustum(); - GLfloat position_cam[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; - glsafe(::glLightfv(GL_LIGHT1, GL_POSITION, position_cam)); - GLfloat position_top[4] = { -0.5f, -0.5f, 1.0f, 0.0f }; - glsafe(::glLightfv(GL_LIGHT0, GL_POSITION, position_top)); + m_frame_callback_list.clear(); const std::array& viewport = camera.get_viewport(); const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); @@ -2087,6 +2206,26 @@ void GLCanvas3D::render(bool only_init) // regular picking pass _picking_pass(); } + glsafe(::glViewport(viewport[0], viewport[1], viewport[2], viewport[3])); + EPickingEffect picking_effect = wxGetApp().get_picking_effect(); + if (EPickingEffect::Disabled != picking_effect) { + if (!ogl_manager.are_framebuffers_supported()) { + picking_effect = EPickingEffect::StencilOutline; // use stencil outline as framebuffer not supported yet. + } + } + + const bool off_screen_rendering_enabled = ogl_manager.is_fxaa_enabled(); + + if (m_picking_enabled && EPickingEffect::Silhouette == picking_effect) { + _render_silhouette_effect(); + } + + if (off_screen_rendering_enabled) { + OpenGLManager::FrameBufferModifier main_frame(ogl_manager, "mainframe", ogl_manager.get_msaa_type()); + } + else { + OpenGLManager::FrameBufferModifier main_frame(ogl_manager, OpenGLManager::s_back_frame); + } #if ENABLE_RENDER_PICKING_PASS if (!m_picking_enabled || !m_show_picking_texture) { @@ -2114,13 +2253,7 @@ void GLCanvas3D::render(bool only_init) show_grid = false; /* view3D render*/ - int hover_id = (m_hover_plate_idxs.size() > 0)?m_hover_plate_idxs.front():-1; - EPickingEffect picking_effect = wxGetApp().get_picking_effect(); - if (EPickingEffect::Disabled != picking_effect) { - if (!ogl_manager.are_framebuffers_supported()) { - picking_effect = EPickingEffect::StencilOutline; // use stencil outline as framebuffer not supported yet. - } - } + int hover_id = (m_hover_plate_idxs.size() > 0) ? m_hover_plate_idxs.front() : -1; bool b_with_stencil_outline = !m_gizmos.is_running() && (EPickingEffect::StencilOutline == picking_effect); if (m_canvas_type == ECanvasType::CanvasView3D) { //BBS: add outline logic @@ -2158,25 +2291,22 @@ void GLCanvas3D::render(bool only_init) _render_objects(GLVolumeCollection::ERenderType::Transparent, b_with_stencil_outline); } - if (EPickingEffect::Silhouette == picking_effect) { - _render_silhouette_effect(); - } + if (m_picking_enabled && EPickingEffect::Silhouette == picking_effect) { + _composite_silhouette_effect(); + } _render_sequential_clearance(); #if ENABLE_RENDER_SELECTION_CENTER _render_selection_center(); #endif // ENABLE_RENDER_SELECTION_CENTER - // we need to set the mouse's scene position here because the depth buffer - // could be invalidated by the following gizmo render methods - // this position is used later into on_mouse() to drag the objects - if (m_picking_enabled) - m_mouse.scene_position = _mouse_to_3d(m_mouse.position.cast()); - // sidebar hints need to be rendered before the gizmos because the depth buffer // could be invalidated by the following gizmo render methods _render_selection_sidebar_hints(); _render_current_gizmo(); + + _composite_main_frame(off_screen_rendering_enabled); + #if ENABLE_RENDER_PICKING_PASS } #endif // ENABLE_RENDER_PICKING_PASS @@ -2184,7 +2314,6 @@ void GLCanvas3D::render(bool only_init) #if ENABLE_SHOW_CAMERA_TARGET _render_camera_target(); #endif // ENABLE_SHOW_CAMERA_TARGET - camera.update_frustum(); if (m_picking_enabled && m_rectangle_selection.is_dragging()) m_rectangle_selection.render(*this); @@ -2275,6 +2404,11 @@ void GLCanvas3D::render(bool only_init) ogl_manager.unbind_vao(); ogl_manager.clear_dirty(); m_canvas->SwapBuffers(); + + for (const auto& cb : m_frame_callback_list) { + cb(); + } + m_render_stats.increment_fps_counter(); } @@ -2287,13 +2421,21 @@ void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data, bool for_picking, bool ban_light) { + const auto& shader = wxGetApp().get_shader("thumbnail"); + if (!shader) { + return; + } const auto& ogl_manager = wxGetApp().get_opengl_manager(); if (!ogl_manager) { return; } ogl_manager->bind_vao(); + ogl_manager->bind_shader(shader); + ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects; render_thumbnail(thumbnail_data, w, h, thumbnail_params, model_objects, m_volumes, camera_type, camera_view_angle_type, for_picking, ban_light); + + ogl_manager->unbind_shader(); ogl_manager->unbind_vao(); } @@ -2308,7 +2450,15 @@ void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data, bool for_picking, bool ban_light) { - GLShaderProgram* shader = wxGetApp().get_shader("thumbnail"); + const auto& shader = wxGetApp().get_shader("thumbnail"); + if (!shader) { + return; + } + + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->bind_vao(); + p_ogl_manager->bind_shader(shader); + std::vector> colors = wxGetApp().plater()->get_extruders_colors(); const auto fb_type = Slic3r::GUI::OpenGLManager::get_framebuffers_type(); BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: %1%") % Slic3r::GUI::OpenGLManager::framebuffer_type_to_string(fb_type).c_str(); @@ -2331,6 +2481,9 @@ void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data, break; } } + + p_ogl_manager->unbind_shader(); + p_ogl_manager->unbind_vao(); } void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data, @@ -2345,7 +2498,15 @@ void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_d bool for_picking, bool ban_light) { - GLShaderProgram *shader = wxGetApp().get_shader("thumbnail"); + const auto& shader = wxGetApp().get_shader("thumbnail"); + if (!shader) { + return; + } + + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->bind_vao(); + p_ogl_manager->bind_shader(shader); + const auto fb_type = Slic3r::GUI::OpenGLManager::get_framebuffers_type(); BOOST_LOG_TRIVIAL(info) << boost::format("framebuffer_type: %1%") % Slic3r::GUI::OpenGLManager::framebuffer_type_to_string(fb_type).c_str(); switch (fb_type){ @@ -2365,6 +2526,9 @@ void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_d break; } } + + p_ogl_manager->unbind_shader(); + p_ogl_manager->unbind_vao(); } void GLCanvas3D::render_calibration_thumbnail(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params) @@ -2546,7 +2710,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (!m_initialized) return; - _set_current(); + _set_current(true); m_hover_volume_idxs.clear(); @@ -3187,7 +3351,7 @@ void GLCanvas3D::load_sla_preview() { const SLAPrint* print = sla_print(); if (m_canvas != nullptr && print != nullptr) { - _set_current(); + _set_current(true); // Release OpenGL data before generating new data. reset_volumes(); _load_sla_shells(); @@ -4112,8 +4276,9 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) } else { auto cnv_size = get_canvas_size(); - auto screen_center_3d_pos = _mouse_to_3d({ cnv_size.get_width() * 0.5, cnv_size.get_height() * 0.5 }); - auto mouse_3d_pos = _mouse_to_3d({evt.GetX(), evt.GetY()}); + const Camera& camera = wxGetApp().plater()->get_camera(); + auto screen_center_3d_pos = _mouse_to_3d(camera, { cnv_size.get_width() * 0.5, cnv_size.get_height() * 0.5 }); + auto mouse_3d_pos = _mouse_to_3d(camera, {evt.GetX(), evt.GetY()}); Vec3d displacement = mouse_3d_pos - screen_center_3d_pos; wxGetApp().plater()->get_camera().translate(displacement); auto origin_zoom = wxGetApp().plater()->get_camera().get_zoom(); @@ -4223,7 +4388,7 @@ std::string format_mouse_event_debug_message(const wxMouseEvent &evt) void GLCanvas3D::on_gesture(wxGestureEvent &evt) { - if (!m_initialized || !_set_current()) + if (!m_initialized || !_set_current(true)) return; auto & camera = wxGetApp().plater()->get_camera(); @@ -4231,8 +4396,8 @@ void GLCanvas3D::on_gesture(wxGestureEvent &evt) auto p = evt.GetPosition(); auto d = static_cast(evt).GetDelta(); float z = 0; - const Vec3d &p2 = _mouse_to_3d({p.x, p.y}, &z); - const Vec3d &p1 = _mouse_to_3d({p.x - d.x, p.y - d.y}, &z); + const Vec3d &p2 = _mouse_to_3d(camera, {p.x, p.y}, &z); + const Vec3d &p1 = _mouse_to_3d(camera, {p.x - d.x, p.y - d.y}, &z); camera.set_target(camera.get_target() + p1 - p2); } else if (evt.GetEventType() == wxEVT_GESTURE_ZOOM) { static float zoom_start = 1; @@ -4257,7 +4422,7 @@ void GLCanvas3D::on_gesture(wxGestureEvent &evt) void GLCanvas3D::on_mouse(wxMouseEvent& evt) { - if (!m_initialized || !_set_current()) + if (!m_initialized || !_set_current(true)) return; // BBS: single snapshot @@ -4540,17 +4705,21 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (!m_hover_volume_idxs.empty()) { if (evt.LeftDown() && m_moving_enabled && m_mouse.drag.move_volume_idx == -1) { // Only accept the initial position, if it is inside the volume bounding box. - int volume_idx = get_first_hover_volume_idx(); - BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box(); - volume_bbox.offset(1.0); - if ((!any_gizmo_active || !evt.CmdDown()) && volume_bbox.contains(m_mouse.scene_position) && !m_selection.is_any_connector()) { - m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None; - // The dragging operation is initiated. - m_mouse.drag.move_volume_idx = volume_idx; - m_selection.start_dragging(); - m_mouse.drag.start_position_3D = m_mouse.scene_position; - m_sequential_print_clearance_first_displacement = true; - m_moving = true; + if (!any_gizmo_active || !evt.CmdDown()) { + int volume_idx = get_first_hover_volume_idx(); + BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box(); + volume_bbox.offset(1.0); + const Camera& camera = wxGetApp().plater()->get_picking_camera(); + m_mouse.scene_position = _mouse_to_3d(camera, { 0, 1 }, nullptr, OpenGLManager::s_picking_frame); + if (volume_bbox.contains(m_mouse.scene_position) && !m_selection.is_any_connector()) { + m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None; + // The dragging operation is initiated. + m_mouse.drag.move_volume_idx = volume_idx; + m_selection.start_dragging(); + m_mouse.drag.start_position_3D = m_mouse.scene_position; + m_sequential_print_clearance_first_displacement = true; + m_moving = true; + } } } } @@ -4594,7 +4763,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // Get new position at the same Z of the initial click point. float z0 = 0.0f; float z1 = 1.0f; - cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)); + cur_pos = Linef3(_mouse_to_3d(camera, pos, &z0), _mouse_to_3d(camera, pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)); } } TransformationType trafo_type; @@ -4673,7 +4842,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) auto canvas_h = float(get_canvas_size().get_height()); Point screen_center(canvas_w/2, canvas_h/2); //camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, wxGetApp().plater()->get_partplate_list().get_bounding_box().center()); - m_rotation_center = _mouse_to_3d(screen_center); + m_rotation_center = _mouse_to_3d(camera, screen_center); m_rotation_center(2) = 0.f; } camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, m_rotation_center); @@ -4692,16 +4861,20 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } + if (m_mouse.is_move_threshold_met(pos)) { + m_mouse.rotating = true; + } m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0); + m_mouse.drag.move_start_threshold_position_2D = pos; } else if (evt.MiddleIsDown() || evt.RightIsDown()) { // If dragging over blank area with right button, pan. if (m_mouse.is_start_position_2D_defined()) { // get point in model space at Z = 0 float z = 0.0f; - const Vec3d& cur_pos = _mouse_to_3d(pos, &z); - Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); Camera& camera = wxGetApp().plater()->get_camera(); + const Vec3d& cur_pos = _mouse_to_3d(camera, pos, &z); + Vec3d orig = _mouse_to_3d(camera, m_mouse.drag.start_position_2D, &z); #ifdef SUPPORT_FREE_CAMERA if (this->m_canvas_type != ECanvasType::CanvasAssembleView) { if (wxGetApp().app_config->get("use_free_camera") != "1") @@ -4717,11 +4890,15 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; m_mouse.ignore_right_up = true; } - + if (m_mouse.is_move_threshold_met(pos)) { + m_mouse.panning = true; + } m_mouse.drag.start_position_2D = pos; + m_mouse.drag.move_start_threshold_position_2D = pos; } } else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) { + if (evt.LeftUp()) { m_selection.stop_dragging(); m_rotation_center(0) = m_rotation_center(1) = m_rotation_center(2) = 0.f; @@ -4756,7 +4933,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) deselect_all(); } //BBS Select plate in this 3D canvas. - else if (evt.LeftUp() && !m_mouse.dragging && m_picking_enabled && !m_hover_plate_idxs.empty() && (m_canvas_type == CanvasView3D) && !is_layers_editing_enabled()) + else if (evt.LeftUp() && !m_mouse.rotating && !m_mouse.panning && m_picking_enabled && !m_hover_plate_idxs.empty() && (m_canvas_type == CanvasView3D) && !is_layers_editing_enabled()) { int hover_idx = m_hover_plate_idxs.front(); wxGetApp().plater()->select_plate_by_hover_id(hover_idx); @@ -5434,7 +5611,8 @@ Linef3 GLCanvas3D::mouse_ray(const Point& mouse_pos) { float z0 = 0.0f; float z1 = 1.0f; - return Linef3(_mouse_to_3d(mouse_pos, &z0), _mouse_to_3d(mouse_pos, &z1)); + const Camera& camera = wxGetApp().plater()->get_camera(); + return Linef3(_mouse_to_3d(camera, mouse_pos, &z0), _mouse_to_3d(camera, mouse_pos, &z1)); } double GLCanvas3D::get_size_proportional_to_max_bed_size(double factor) const @@ -5543,6 +5721,8 @@ void GLCanvas3D::mouse_up_cleanup() m_mouse.set_start_position_3D_as_invalid(); m_mouse.set_start_position_2D_as_invalid(); m_mouse.dragging = false; + m_mouse.rotating = false; + m_mouse.panning = false; m_mouse.ignore_left_up = false; m_mouse.ignore_right_up = false; m_dirty = true; @@ -6131,7 +6311,7 @@ static void debug_output_thumbnail(const ThumbnailData& thumbnail_data) void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, - GLShaderProgram * shader, + const std::shared_ptr& shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type, bool for_picking, @@ -6180,7 +6360,7 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const } } BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: plate_idx %1% volumes size %2%, shader %3%, use_top_view=%4%, for_picking=%5%") % plate_idx % - visible_volumes.size() % shader % (int)camera_view_angle_type % for_picking; + visible_volumes.size() % shader.get() % (int)camera_view_angle_type % for_picking; } else { visible_volumes = volumes.volumes; } @@ -6244,7 +6424,6 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const camera.zoom_to_box(volumes_box); } - camera.apply_view_matrix(); if (thumbnail_params.use_plate_box) { camera.apply_projection(plate_build_volume); } @@ -6256,8 +6435,8 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const //camera.apply_projection(volumes_box, near_z, far_z); //GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); - if (!for_picking && (shader == nullptr)) { - BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with no picking: shader is null, return directly"); + if (!shader) { + BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with invalid shader"); return; } @@ -6279,6 +6458,10 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const if (ban_light) { glsafe(::glDisable(GL_BLEND)); } + + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); + shader->set_uniform("ban_light", ban_light); if (for_picking) { //if (OpenGLManager::can_multisample()) // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. @@ -6291,9 +6474,6 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const // do not cull backfaces to show broken geometry, if any glsafe(::glDisable(GL_CULL_FACE)); - //glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - //glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); - for (GLVolume* vol : visible_volumes) { // Object picking mode. Render the object with a color encoding the object index. // we reserve color = (0,0,0) for occluders (as the printbed) @@ -6305,31 +6485,28 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const unsigned int g = (id & (0x000000FF << 8)) >> 8; unsigned int b = (id & (0x000000FF << 16)) >> 16; unsigned int a = 0xFF; - glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255)); - /*curr_color[0] = (GLfloat)r * INV_255; - curr_color[1] = (GLfloat)g * INV_255; - curr_color[2] = (GLfloat)b * INV_255; - curr_color[3] = (GLfloat)a * INV_255; - shader->set_uniform("uniform_color", curr_color);*/ + + const std::array color{ (GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255 }; + shader->set_uniform("uniform_color", color); bool is_active = vol->is_active; vol->is_active = true; - vol->simple_render(nullptr, model_objects, extruder_colors); + + const Transform3d matrix = view_matrix * vol->world_matrix(); + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", projection_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + shader->set_uniform("volume_world_matrix", vol->world_matrix()); + vol->simple_render(shader, model_objects, extruder_colors); vol->is_active = is_active; } - - //glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - //glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glEnable(GL_CULL_FACE)); //if (OpenGLManager::can_multisample()) // glsafe(::glEnable(GL_MULTISAMPLE)); } else { - shader->start_using(); shader->set_uniform("emission_factor", 0.1f); - shader->set_uniform("ban_light", ban_light); for (GLVolume* vol : visible_volumes) { //BBS set render color for thumbnails curr_color[0] = vol->color[0]; @@ -6354,10 +6531,13 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const // the volume may have been deactivated by an active gizmo bool is_active = vol->is_active; vol->is_active = true; + const Transform3d matrix = view_matrix * vol->world_matrix(); + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", projection_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); vol->simple_render(shader, model_objects, extruder_colors, ban_light); vol->is_active = is_active; } - shader->stop_using(); } glsafe(::glDisable(GL_DEPTH_TEST)); @@ -6373,7 +6553,7 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, - GLShaderProgram * shader, + const std::shared_ptr& shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type, bool for_picking, @@ -6486,7 +6666,7 @@ void GLCanvas3D::render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, uns void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, - GLShaderProgram * shader, + const std::shared_ptr& shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type, bool for_picking, @@ -6593,7 +6773,7 @@ void GLCanvas3D::render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, // glsafe(::glDisable(GL_MULTISAMPLE)); } -void GLCanvas3D::render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, GLShaderProgram* shader, Camera::EType camera_type, +void GLCanvas3D::render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, const std::shared_ptr& shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type, bool for_picking, bool ban_light) @@ -7061,9 +7241,19 @@ bool GLCanvas3D::_init_collapse_toolbar() return wxGetApp().plater()->init_collapse_toolbar(); } -bool GLCanvas3D::_set_current() +bool GLCanvas3D::_set_current(bool force_update) { - return m_context != nullptr && m_canvas->SetCurrent(*m_context); + if (!m_context || !m_canvas) { + return false; + } + if (m_dirty_context || force_update) { + const auto rt = m_canvas->SetCurrent(*m_context); + if (rt) { + m_dirty_context = false; + } + return rt; + } + return true; } void GLCanvas3D::_resize(unsigned int w, unsigned int h) @@ -7108,7 +7298,7 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h) this->request_extra_frame(); // ensures that this canvas is current - _set_current(); + _set_current(true); } BoundingBoxf3 GLCanvas3D::_max_bounding_box(bool include_gizmos, bool include_bed_model, bool include_plates) const @@ -7171,20 +7361,28 @@ void GLCanvas3D::_refresh_if_shown_on_screen() void GLCanvas3D::_picking_pass() { - std::vector* hover_volume_idxs = const_cast*>(&m_hover_volume_idxs); - std::vector* hover_plate_idxs = const_cast*>(&m_hover_plate_idxs); - if (m_picking_enabled && !m_mouse.dragging && m_mouse.position != Vec2d(DBL_MAX, DBL_MAX)) { - hover_volume_idxs->clear(); - hover_plate_idxs->clear(); // Render the object for picking. - // FIXME This cannot possibly work in a multi - sampled context as the color gets mangled by the anti - aliasing. - // Better to use software ray - casting on a bounding - box hierarchy. + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + { + OpenGLManager::FrameBufferModifier picking_frame(*p_ogl_manager, "pickingframe", EMSAAType::Disabled); + } - if (m_multisample_allowed) - // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. - glsafe(::glDisable(GL_MULTISAMPLE)); + auto& picking_camera = wxGetApp().plater()->get_picking_camera(); + picking_camera.set_type(Camera::EType::Ortho); + picking_camera.apply_viewport(0, 0, 1, 1); + + float pick_eye_z = 0.0f; + const Camera& camera = wxGetApp().plater()->get_camera(); + Vec3d pick_eye = _mouse_to_3d(camera, { m_mouse.position(0), m_mouse.position(1) }, &pick_eye_z); + + float pick_target_z = 1.0f; + Vec3d pick_target = _mouse_to_3d(camera, { m_mouse.position(0), m_mouse.position(1) }, &pick_target_z); + picking_camera.look_at(pick_eye, pick_target, Vec3d::UnitY()); + picking_camera.apply_projection(_max_bounding_box(true, true, true)); + + picking_camera.update_frustum(); glsafe(::glDisable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); @@ -7200,65 +7398,69 @@ void GLCanvas3D::_picking_pass() } m_camera_clipping_plane = m_gizmos.get_clipping_plane(); - if (m_camera_clipping_plane.is_active()) { - ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data()); - ::glEnable(GL_CLIP_PLANE0); - } _render_volumes_for_picking(); - if (m_camera_clipping_plane.is_active()) - ::glDisable(GL_CLIP_PLANE0); //BBS: remove the bed picking logic //_render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward()); m_gizmos.render_current_gizmo_for_picking_pass(); - if (m_multisample_allowed) - glsafe(::glEnable(GL_MULTISAMPLE)); + const auto gpu_picking_callback = [this]()->void { + std::vector* hover_volume_idxs = const_cast*>(&m_hover_volume_idxs); + std::vector* hover_plate_idxs = const_cast*>(&m_hover_plate_idxs); - int volume_id = -1; - int gizmo_id = -1; + hover_volume_idxs->clear(); + hover_plate_idxs->clear(); - GLubyte color[4] = { 0, 0, 0, 0 }; - const Size& cnv_size = get_canvas_size(); - bool inside = 0 <= m_mouse.position(0) && m_mouse.position(0) < cnv_size.get_width() && 0 <= m_mouse.position(1) && m_mouse.position(1) < cnv_size.get_height(); - if (inside) { - glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color)); - if (picking_checksum_alpha_channel(color[0], color[1], color[2]) == color[3]) { - // Only non-interpolated colors are valid, those have their lowest three bits zeroed. - // we reserve color = (0,0,0) for occluders (as the printbed) - // volumes' id are shifted by 1 - // see: _render_volumes_for_picking() - //BBS: remove the bed picking logic - //volume_id = color[0] + (color[1] << 8) + (color[2] << 16) - 1; - volume_id = color[0] + (color[1] << 8) + (color[2] << 16); - // gizmos' id are instead properly encoded by the color - gizmo_id = color[0] + (color[1] << 8) + (color[2] << 16); - } - } - else - m_gizmos.set_hover_id(inside && (unsigned int)gizmo_id <= GLGizmoBase::BASE_ID ? ((int)GLGizmoBase::BASE_ID - gizmo_id) : -1); + // Render the object for picking. + const Size& cnv_size = get_canvas_size(); - //BBS: add plate picking logic - int plate_hover_id = PartPlate::PLATE_BASE_ID - volume_id; - if (plate_hover_id >= 0 && plate_hover_id < PartPlateList::MAX_PLATES_COUNT * PartPlate::GRABBER_COUNT) { - wxGetApp().plater()->get_partplate_list().set_hover_id(plate_hover_id); - hover_plate_idxs->emplace_back(plate_hover_id); - const_cast(&m_gizmos)->set_hover_id(-1); - } - else { - wxGetApp().plater()->get_partplate_list().reset_hover_id(); - if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) { - // do not add the volume id if any gizmo is active and CTRL is pressed - if (m_gizmos.get_current_type() == GLGizmosManager::EType::Undefined || !wxGetKeyState(WXK_CONTROL)) - hover_volume_idxs->emplace_back(volume_id); - const_cast(&m_gizmos)->set_hover_id(-1); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + + int volume_id = -1; + int gizmo_id = -1; + + GLubyte color[4] = { 0, 0, 0, 0 }; + bool inside = 0 <= m_mouse.position(0) && m_mouse.position(0) < cnv_size.get_width() && 0 <= m_mouse.position(1) && m_mouse.position(1) < cnv_size.get_height(); + if (inside) { + p_ogl_manager->read_pixel(OpenGLManager::s_picking_frame, 0, 0, 1, 1, EPixelFormat::RGBA, EPixelDataType::UByte, (void*)color); + if (picking_checksum_alpha_channel(color[0], color[1], color[2]) == color[3]) { + // Only non-interpolated colors are valid, those have their lowest three bits zeroed. + // we reserve color = (0,0,0) for occluders (as the printbed) + // volumes' id are shifted by 1 + // see: _render_volumes_for_picking() + //BBS: remove the bed picking logic + //volume_id = color[0] + (color[1] << 8) + (color[2] << 16) - 1; + volume_id = color[0] + (color[1] << 8) + (color[2] << 16); + // gizmos' id are instead properly encoded by the color + gizmo_id = color[0] + (color[1] << 8) + (color[2] << 16); + } } else - const_cast(&m_gizmos)->set_hover_id(inside && (unsigned int)volume_id <= GLGizmoBase::BASE_ID ? ((int)GLGizmoBase::BASE_ID - volume_id) : -1); - } + m_gizmos.set_hover_id(inside && (unsigned int)gizmo_id <= GLGizmoBase::BASE_ID ? ((int)GLGizmoBase::BASE_ID - gizmo_id) : -1); - _update_volumes_hover_state(); + //BBS: add plate picking logic + int plate_hover_id = PartPlate::PLATE_BASE_ID - volume_id; + if (plate_hover_id >= 0 && plate_hover_id < PartPlateList::MAX_PLATES_COUNT * PartPlate::GRABBER_COUNT) { + wxGetApp().plater()->get_partplate_list().set_hover_id(plate_hover_id); + hover_plate_idxs->emplace_back(plate_hover_id); + const_cast(&m_gizmos)->set_hover_id(-1); + } + else { + wxGetApp().plater()->get_partplate_list().reset_hover_id(); + if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) { + // do not add the volume id if any gizmo is active and CTRL is pressed + if (m_gizmos.get_current_type() == GLGizmosManager::EType::Undefined || !wxGetKeyState(WXK_CONTROL)) + hover_volume_idxs->emplace_back(volume_id); + const_cast(&m_gizmos)->set_hover_id(-1); + } + else + const_cast(&m_gizmos)->set_hover_id(inside && (unsigned int)volume_id <= GLGizmoBase::BASE_ID ? ((int)GLGizmoBase::BASE_ID - volume_id) : -1); + } + _update_volumes_hover_state(); + }; + + _append_to_frame_callback(gpu_picking_callback); } } @@ -7266,12 +7468,57 @@ void GLCanvas3D::_rectangular_selection_picking_pass() { m_gizmos.set_hover_id(-1); - std::set idxs; - + int viewport_width = 0; + int viewport_height = 0; if (m_picking_enabled) { - if (m_multisample_allowed) - // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. - glsafe(::glDisable(GL_MULTISAMPLE)); + + Vec2f center; + center.x() = (m_rectangle_selection.get_left() + m_rectangle_selection.get_right()) * 0.5f; + center.y() = (m_rectangle_selection.get_bottom() + m_rectangle_selection.get_top()) * 0.5f; + + const int viewport_x = static_cast(m_rectangle_selection.get_left()); + const int viewport_y = static_cast(get_canvas_size().get_height() - m_rectangle_selection.get_top()); + viewport_width = static_cast(m_rectangle_selection.get_width()); + viewport_width = viewport_width > 1 ? viewport_width : 1; + viewport_width = viewport_width; + viewport_height = static_cast(m_rectangle_selection.get_height()); + viewport_height = viewport_height > 1 ? viewport_height : 1; + viewport_height = viewport_height; + + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + { + OpenGLManager::FrameBufferModifier picking_frame(*p_ogl_manager, "rectangular_selection_pickingframe", EMSAAType::Disabled); + } + + const auto camera = wxGetApp().plater()->get_camera(); + const auto main_camera_type = camera.get_type(); + + auto& picking_camera = wxGetApp().plater()->get_picking_camera(); + if (main_camera_type == Camera::EType::Ortho) { + + picking_camera.set_zoom(camera.get_zoom()); + + float pick_eye_z = 0.0f; + const Camera& camera = wxGetApp().plater()->get_camera(); + Vec3d pick_eye = _mouse_to_3d(camera, { center.x(), center.y() }, &pick_eye_z); + float pick_target_z = 1.0f; + Vec3d pick_target = _mouse_to_3d(camera, { center.x(), center.y() }, &pick_target_z); + picking_camera.look_at(pick_eye, pick_target, camera.get_dir_up()); + + picking_camera.apply_viewport(viewport_x, viewport_y, viewport_width, viewport_height); + picking_camera.set_type(Camera::EType::Ortho); + + picking_camera.apply_projection(_max_bounding_box(true, true, true)); + + picking_camera.update_frustum(); + } + else { + picking_camera = camera; + picking_camera.enable_update_config_on_type_change(false); + } + + glsafe(::glEnable(GL_SCISSOR_TEST)); + glsafe(::glScissor(viewport_x, viewport_y, viewport_width, viewport_height)); glsafe(::glDisable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); @@ -7282,64 +7529,69 @@ void GLCanvas3D::_rectangular_selection_picking_pass() //BBS: remove the bed picking logic //_render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward()); - if (m_multisample_allowed) - glsafe(::glEnable(GL_MULTISAMPLE)); - - int width = std::max((int)m_rectangle_selection.get_width(), 1); - int height = std::max((int)m_rectangle_selection.get_height(), 1); - int px_count = width * height; - - int left = (int)m_rectangle_selection.get_left(); - int top = get_canvas_size().get_height() - (int)m_rectangle_selection.get_top(); - if (left >= 0 && top >= 0) { -#define USE_PARALLEL 1 -#if USE_PARALLEL - struct Pixel - { - std::array data; - // Only non-interpolated colors are valid, those have their lowest three bits zeroed. - bool valid() const { return picking_checksum_alpha_channel(data[0], data[1], data[2]) == data[3]; } - // we reserve color = (0,0,0) for occluders (as the printbed) - // volumes' id are shifted by 1 - // see: _render_volumes_for_picking() - //BBS: remove the bed picking logic - int id() const { return data[0] + (data[1] << 8) + (data[2] << 16); } - //int id() const { return data[0] + (data[1] << 8) + (data[2] << 16) - 1; } - }; - - std::vector frame(px_count); - glsafe(::glReadPixels(left, top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)frame.data())); - - tbb::spin_mutex mutex; - tbb::parallel_for(tbb::blocked_range(0, frame.size(), (size_t)width), - [this, &frame, &idxs, &mutex](const tbb::blocked_range& range) { - for (size_t i = range.begin(); i < range.end(); ++i) - if (frame[i].valid()) { - int volume_id = frame[i].id(); - if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) { - mutex.lock(); - idxs.insert(volume_id); - mutex.unlock(); - } - } - }); -#else - std::vector frame(4 * px_count); - glsafe(::glReadPixels(left, top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)frame.data())); - - for (int i = 0; i < px_count; ++i) - { - int px_id = 4 * i; - int volume_id = frame[px_id] + (frame[px_id + 1] << 8) + (frame[px_id + 2] << 16); - if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) - idxs.insert(volume_id); - } -#endif // USE_PARALLEL - } + glsafe(::glDisable(GL_SCISSOR_TEST)); } - m_hover_volume_idxs.assign(idxs.begin(), idxs.end()); - _update_volumes_hover_state(); + const auto gpu_picking_callback = [this, viewport_width, viewport_height]()->void { + std::set idxs; + + if (m_picking_enabled) { + int px_count = viewport_width * viewport_height; + + int left = (int)m_rectangle_selection.get_left(); + int top = get_canvas_size().get_height() - (int)m_rectangle_selection.get_top(); + if (left >= 0 && top >= 0 && px_count) { +#define USE_PARALLEL 1 +#if USE_PARALLEL + struct Pixel + { + std::array data; + // Only non-interpolated colors are valid, those have their lowest three bits zeroed. + bool valid() const { return picking_checksum_alpha_channel(data[0], data[1], data[2]) == data[3]; } + // we reserve color = (0,0,0) for occluders (as the printbed) + // volumes' id are shifted by 1 + // see: _render_volumes_for_picking() + //BBS: remove the bed picking logic + int id() const { return data[0] + (data[1] << 8) + (data[2] << 16); } + //int id() const { return data[0] + (data[1] << 8) + (data[2] << 16) - 1; } + }; + + std::vector frame(px_count); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->read_pixel("rectangular_selection_pickingframe", left, top, viewport_width, viewport_height, EPixelFormat::RGBA, EPixelDataType::UByte, (void*)frame.data()); + tbb::spin_mutex mutex; + tbb::parallel_for(tbb::blocked_range(0, frame.size(), (size_t)viewport_width), + [this, &frame, &idxs, &mutex](const tbb::blocked_range& range) { + for (size_t i = range.begin(); i < range.end(); ++i) + if (frame[i].valid()) { + int volume_id = frame[i].id(); + if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) { + mutex.lock(); + idxs.insert(volume_id); + mutex.unlock(); + } + } + }); +#else + std::vector frame(4 * px_count); + p_ogl_manager->read_pixel(left, top, viewport_width, viewport_height, EPixelFormat::RGBA, EPixelDataType::UByte, (void*)frame.data()); + + for (int i = 0; i < px_count; ++i) + { + int px_id = 4 * i; + int volume_id = frame[px_id] + (frame[px_id + 1] << 8) + (frame[px_id + 2] << 16); + if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) + idxs.insert(volume_id); + } +#endif // USE_PARALLEL + } + } + + m_hover_volume_idxs.assign(idxs.begin(), idxs.end()); + _update_volumes_hover_state(); + }; + + _append_to_frame_callback(gpu_picking_callback); } void GLCanvas3D::_render_background() const @@ -7365,42 +7617,31 @@ void GLCanvas3D::_render_background() const } } - glsafe(::glPushMatrix()); - glsafe(::glLoadIdentity()); - glsafe(::glMatrixMode(GL_PROJECTION)); - glsafe(::glPushMatrix()); - glsafe(::glLoadIdentity()); - // Draws a bottom to top gradient over the complete screen. glsafe(::glDisable(GL_DEPTH_TEST)); - ::glBegin(GL_QUADS); + _init_fullscreen_mesh(); float* background_color = m_is_dark ? DEFAULT_BG_LIGHT_COLOR_DARK : DEFAULT_BG_LIGHT_COLOR; float* error_background_color = m_is_dark ? ERROR_BG_LIGHT_COLOR_DARK : ERROR_BG_LIGHT_COLOR; - if (use_error_color) - ::glColor3fv(error_background_color); - else - ::glColor3fv(background_color); + const auto final_bg_color = use_error_color ? error_background_color : background_color; - ::glVertex2f(-1.0f, -1.0f); - ::glVertex2f(1.0f, -1.0f); + const auto& p_background_shader = wxGetApp().get_shader("background"); + if (!p_background_shader) + { + BOOST_LOG_TRIVIAL(error) << "Invalid Shader: background"; + return; + } + wxGetApp().bind_shader(p_background_shader); - if (use_error_color) - ::glColor3fv(error_background_color); - else - ::glColor3fv(background_color); + m_full_screen_mesh.set_color({ final_bg_color[0], final_bg_color[1], final_bg_color[2], 1.0f}); - ::glVertex2f(1.0f, 1.0f); - ::glVertex2f(-1.0f, 1.0f); - glsafe(::glEnd()); + m_full_screen_mesh.render_geometry(); + + wxGetApp().unbind_shader(); glsafe(::glEnable(GL_DEPTH_TEST)); - - glsafe(::glPopMatrix()); - glsafe(::glMatrixMode(GL_MODELVIEW)); - glsafe(::glPopMatrix()); } void GLCanvas3D::_render_bed(bool bottom, bool show_axes) @@ -7515,7 +7756,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with else m_volumes.set_show_sinking_contours(!m_gizmos.is_hiding_instances()); - GLShaderProgram* shader = wxGetApp().get_shader("gouraud"); + const auto& shader = wxGetApp().get_shader("gouraud"); ECanvasType canvas_type = this->m_canvas_type; std::array body_color = canvas_type == ECanvasType::CanvasAssembleView ? std::array({1.0f, 1.0f, 0.0f, 1.0f}) ://yellow std::array({1.0f, 1.0f, 1.0f, 1.0f});//white @@ -7523,10 +7764,13 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with auto printable_height_option = GUI::wxGetApp().preset_bundle->printers.get_edited_preset().config.option("extruder_printable_height"); const GUI::ERenderPipelineStage render_pipeline_stage = _get_current_render_stage(); + const auto& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); if ((GUI::ERenderPipelineStage::Silhouette == render_pipeline_stage) || shader != nullptr) { if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { - shader->start_using(); + wxGetApp().bind_shader(shader); } switch (type) { @@ -7538,7 +7782,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with { if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f) && GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { int object_id = m_layers_editing.last_object_id; - m_volumes.render(render_pipeline_stage, type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [object_id](const GLVolume& volume) { + m_volumes.render(render_pipeline_stage, type, false, view_matrix, projection_matrix, [object_id](const GLVolume& volume) { // Which volume to paint without the layer height profile shader? return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); }); @@ -7553,7 +7797,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with }*/ //BBS:add assemble view related logic // do not cull backfaces to show broken geometry, if any - m_volumes.render(render_pipeline_stage, type, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { + m_volumes.render(render_pipeline_stage, type, m_picking_enabled, view_matrix, projection_matrix, [this, canvas_type](const GLVolume& volume) { if (canvas_type == ECanvasType::CanvasAssembleView) { return !volume.is_modifier && !volume.is_wipe_tower; } @@ -7570,9 +7814,9 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with // visible when inside modifier meshes etc. // GLGizmosManager::EType type = gm.get_current_type(); if (dynamic_cast(gm.get_current())) { - shader->stop_using(); + wxGetApp().unbind_shader(); gm.render_painter_gizmo(); - shader->start_using(); + wxGetApp().bind_shader(shader); } } @@ -7587,7 +7831,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with shader->set_uniform("show_wireframe", false); }*/ //BBS:add assemble view related logic - m_volumes.render(render_pipeline_stage, type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [this, canvas_type](const GLVolume& volume) { + m_volumes.render(render_pipeline_stage, type, false, view_matrix, projection_matrix, [this, canvas_type](const GLVolume& volume) { if (canvas_type == ECanvasType::CanvasAssembleView) { return !volume.is_modifier; } @@ -7598,9 +7842,9 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with with_outline, body_color, partly_inside_enable, printable_height_option ? &printable_height_option->values : nullptr); if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0 && GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { const GLGizmosManager& gm = get_gizmos_manager(); - shader->stop_using(); + wxGetApp().unbind_shader(); gm.render_painter_assemble_view(); - shader->start_using(); + wxGetApp().bind_shader(shader); } break; } @@ -7611,7 +7855,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with }*/ if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { - shader->stop_using(); + wxGetApp().unbind_shader(); } } @@ -7776,19 +8020,11 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale() void GLCanvas3D::_render_overlays() { glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glPushMatrix()); - glsafe(::glLoadIdentity()); - // ensure that the textures are renderered inside the frustrum - const Camera& camera = wxGetApp().plater()->get_camera(); - glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.10))); - // ensure that the overlay fits the frustrum near z plane - double gui_scale = camera.get_gui_scale(); - glsafe(::glScaled(gui_scale, gui_scale, 1.0)); - _check_and_update_toolbar_icon_scale(); + _check_and_update_toolbar_icon_scale(); - _render_assemble_control(); - _render_assemble_info(); + _render_assemble_control(); + _render_assemble_info(); // main toolbar and undoredo toolbar need to be both updated before rendering because both their sizes are needed // to correctly place them @@ -7856,8 +8092,7 @@ void GLCanvas3D::_render_overlays() } m_labels.render(sorted_instances); _render_3d_navigator(); - - glsafe(::glPopMatrix()); + _render_fit_camera_toolbar(); } void GLCanvas3D::_render_style_editor() @@ -7955,19 +8190,29 @@ void GLCanvas3D::_render_style_editor() void GLCanvas3D::_render_volumes_for_picking() const { + const auto& shader = wxGetApp().get_shader("flat"); + if (!shader) + return; + + wxGetApp().bind_shader(shader); + static const GLfloat INV_255 = 1.0f / 255.0f; // do not cull backfaces to show broken geometry, if any glsafe(::glDisable(GL_CULL_FACE)); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); - - const Transform3d& view_matrix = wxGetApp().plater()->get_camera().get_view_matrix(); + const Camera& camera = wxGetApp().plater()->get_picking_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + shader->set_uniform("projection_matrix", proj_matrix); for (size_t type = 0; type < 2; ++ type) { GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::ERenderType::Opaque : GLVolumeCollection::ERenderType::Transparent, view_matrix); for (const GLVolumeWithIdAndZ& volume : to_render) if (!volume.first->disabled && (volume.first->composite_id.volume_id >= 0 || m_render_sla_auxiliaries)) { + auto world_box = volume.first->transformed_bounding_box(); + if (!camera.getFrustum().intersects(world_box)) { + continue; + } // Object picking mode. Render the object with a color encoding the object index. // we reserve color = (0,0,0) for occluders (as the printbed) // so we shift volumes' id by 1 to get the proper color @@ -7978,13 +8223,16 @@ void GLCanvas3D::_render_volumes_for_picking() const unsigned int g = (id & (0x000000FF << 8)) >> 8; unsigned int b = (id & (0x000000FF << 16)) >> 16; unsigned int a = picking_checksum_alpha_channel(r, g, b); - glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255)); - volume.first->render(); - } - } + shader->set_uniform("view_model_matrix", view_matrix * volume.first->world_matrix()); + std::array t_color{ (GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255 }; + shader->set_uniform("uniform_color", t_color); + volume.first->picking = true; + volume.first->render(view_matrix); + volume.first->picking = false; + } + } - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + wxGetApp().unbind_shader(); glsafe(::glEnable(GL_CULL_FACE)); } @@ -9005,26 +9253,70 @@ void GLCanvas3D::_render_assemble_info() const #if ENABLE_SHOW_CAMERA_TARGET void GLCanvas3D::_render_camera_target() const { + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) + return; + double half_length = 5.0; + if (!m_camera_target_mark.is_initialized()) { + GLModel::Geometry geo; + geo.format.type = GLModel::PrimitiveType::Lines; + geo.format.vertex_layout = GLModel::Geometry::EVertexLayout::P3; + + // x + geo.add_vertex(Vec3f{ -0.5f, 0.0f, 0.0f }); + geo.add_vertex(Vec3f{ 0.5f, 0.0f, 0.0f }); + + geo.add_line(0, 1); + + m_camera_target_mark.init_from(std::move(geo)); + } + + wxGetApp().bind_shader(p_flat_shader); + + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glLineWidth(2.0f)); - ::glBegin(GL_LINES); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager.set_line_width(2.0f); + const Vec3d& target = wxGetApp().plater()->get_camera().get_target(); - // draw line for x axis - ::glColor3f(1.0f, 0.0f, 0.0f); - ::glVertex3d(target(0) - half_length, target(1), target(2)); - ::glVertex3d(target(0) + half_length, target(1), target(2)); - // draw line for y axis - ::glColor3f(0.0f, 1.0f, 0.0f); - ::glVertex3d(target(0), target(1) - half_length, target(2)); - ::glVertex3d(target(0), target(1) + half_length, target(2)); - // draw line for z axis - ::glColor3f(0.0f, 0.0f, 1.0f); - ::glVertex3d(target(0), target(1), target(2) - half_length); - ::glVertex3d(target(0), target(1), target(2) + half_length); - glsafe(::glEnd()); + + const float scale = 2.0f * half_length; + Transform3d model_matrix{ Transform3d::Identity() }; + model_matrix.data()[3 * 4 + 0] = target.x(); + model_matrix.data()[3 * 4 + 1] = target.y(); + model_matrix.data()[3 * 4 + 2] = target.z(); + model_matrix.data()[0 * 4 + 0] = scale; + model_matrix.data()[1 * 4 + 1] = 1.0f; + model_matrix.data()[2 * 4 + 2] = 1.0f; + + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); + m_camera_target_mark.set_color({ 1.0f, 0.0f, 0.0f, 1.0f }); + m_camera_target_mark.render_geometry(); + + model_matrix = Geometry::translation_transform(target.cast()) + * Geometry::rotation_transform({ 0.0f, 0.0f, 0.5 * PI }) + * Geometry::scale_transform({ scale, 1.0f, 1.0f }); + + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + m_camera_target_mark.set_color({ 0.0f, 1.0f, 0.0f, 1.0f }); + m_camera_target_mark.render_geometry(); + + model_matrix = Geometry::translation_transform(target.cast()) + * Geometry::rotation_transform({ 0.0f, -0.5 * PI, 0.0f }) + * Geometry::scale_transform({ scale, 1.0f, 1.0f }); + + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + m_camera_target_mark.set_color({ 0.0f, 0.0f, 1.0f, 1.0f }); + m_camera_target_mark.render_geometry(); + + wxGetApp().unbind_shader(); } #endif // ENABLE_SHOW_CAMERA_TARGET @@ -9033,12 +9325,19 @@ void GLCanvas3D::_render_sla_slices() if (!m_use_clipping_planes || current_printer_technology() != ptSLA) return; + const auto& shader = wxGetApp().get_shader("flat"); + if (!shader) { + return; + } + const SLAPrint* print = this->sla_print(); const PrintObjects& print_objects = print->objects(); if (print_objects.empty()) // nothing to render, return return; + wxGetApp().bind_shader(shader); + double clip_min_z = -m_clipping_planes[0].get_data()[3]; double clip_max_z = m_clipping_planes[1].get_data()[3]; for (unsigned int i = 0; i < (unsigned int)print_objects.size(); ++i) { @@ -9047,43 +9346,62 @@ void GLCanvas3D::_render_sla_slices() if (!obj->is_step_done(slaposSliceSupports)) continue; - SlaCap::ObjectIdToTrianglesMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i); - SlaCap::ObjectIdToTrianglesMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i); + SlaCap::ObjectIdToModelsMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i); + SlaCap::ObjectIdToModelsMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i); { if (it_caps_bottom == m_sla_caps[0].triangles.end()) it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first; if (!m_sla_caps[0].matches(clip_min_z)) { m_sla_caps[0].z = clip_min_z; - it_caps_bottom->second.object.clear(); - it_caps_bottom->second.supports.clear(); + it_caps_bottom->second.object.reset(); + it_caps_bottom->second.supports.reset(); } if (it_caps_top == m_sla_caps[1].triangles.end()) it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first; if (!m_sla_caps[1].matches(clip_max_z)) { m_sla_caps[1].z = clip_max_z; - it_caps_top->second.object.clear(); - it_caps_top->second.supports.clear(); + it_caps_top->second.object.reset(); + it_caps_top->second.supports.reset(); } } - Pointf3s &bottom_obj_triangles = it_caps_bottom->second.object; - Pointf3s &bottom_sup_triangles = it_caps_bottom->second.supports; - Pointf3s &top_obj_triangles = it_caps_top->second.object; - Pointf3s &top_sup_triangles = it_caps_top->second.supports; + GLModel& bottom_obj_triangles = it_caps_bottom->second.object; + GLModel& bottom_sup_triangles = it_caps_bottom->second.supports; + GLModel& top_obj_triangles = it_caps_top->second.object; + GLModel& top_sup_triangles = it_caps_top->second.supports; - if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && - !obj->get_slice_index().empty()) - { - double layer_height = print->default_object_config().layer_height.value; + auto init_model = [](GLModel& model, const Pointf3s& triangles, const ColorRGBA& color) { + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(triangles.size()); + init_data.reserve_indices(triangles.size() / 3); + init_data.color = color; + + unsigned int vertices_count = 0; + for (const Vec3d& v : triangles) { + init_data.add_vertex((Vec3f)v.cast()); + ++vertices_count; + if (vertices_count % 3 == 0) { + init_data.add_triangle(vertices_count - 3, vertices_count - 2, vertices_count - 1); + } + } + + if (!init_data.is_empty()) + model.init_from(std::move(init_data)); + }; + + if ((!bottom_obj_triangles.is_initialized() || !bottom_sup_triangles.is_initialized() || + !top_obj_triangles.is_initialized() || !top_sup_triangles.is_initialized()) && !obj->get_slice_index().empty()) { + double layer_height = print->default_object_config().layer_height.value; double initial_layer_height = print->material_config().initial_layer_height.value; - bool left_handed = obj->is_left_handed(); + bool left_handed = obj->is_left_handed(); coord_t key_zero = obj->get_slice_index().front().print_level(); // Slice at the center of the slab starting at clip_min_z will be rendered for the lower plane. - coord_t key_low = coord_t((clip_min_z - initial_layer_height + layer_height) / SCALING_FACTOR) + key_zero; + coord_t key_low = coord_t((clip_min_z - initial_layer_height + layer_height) / SCALING_FACTOR) + key_zero; // Slice at the center of the slab ending at clip_max_z will be rendered for the upper plane. coord_t key_high = coord_t((clip_max_z - initial_layer_height) / SCALING_FACTOR) + key_zero; - const SliceRecord& slice_low = obj->closest_slice_to_print_level(key_low, coord_t(SCALED_EPSILON)); + const SliceRecord& slice_low = obj->closest_slice_to_print_level(key_low, coord_t(SCALED_EPSILON)); const SliceRecord& slice_high = obj->closest_slice_to_print_level(key_high, coord_t(SCALED_EPSILON)); // Offset to avoid OpenGL Z fighting between the object's horizontal surfaces and the triangluated surfaces of the cuts. @@ -9093,57 +9411,46 @@ void GLCanvas3D::_render_sla_slices() const ExPolygons& obj_bottom = slice_low.get_slice(soModel); const ExPolygons& sup_bottom = slice_low.get_slice(soSupport); // calculate model bottom cap - if (bottom_obj_triangles.empty() && !obj_bottom.empty()) - bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z - plane_shift_z, ! left_handed); + // calculate model bottom cap + if (!bottom_obj_triangles.is_initialized() && !obj_bottom.empty()) + init_model(bottom_obj_triangles, triangulate_expolygons_3d(obj_bottom, clip_min_z - plane_shift_z, !left_handed), { 1.0f, 0.37f, 0.0f, 1.0f }); // calculate support bottom cap - if (bottom_sup_triangles.empty() && !sup_bottom.empty()) - bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z - plane_shift_z, ! left_handed); + if (!bottom_sup_triangles.is_initialized() && !sup_bottom.empty()) + init_model(bottom_sup_triangles, triangulate_expolygons_3d(sup_bottom, clip_min_z - plane_shift_z, !left_handed), { 1.0f, 0.0f, 0.37f, 1.0f }); } if (slice_high.is_valid()) { const ExPolygons& obj_top = slice_high.get_slice(soModel); const ExPolygons& sup_top = slice_high.get_slice(soSupport); // calculate model top cap - if (top_obj_triangles.empty() && !obj_top.empty()) - top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z + plane_shift_z, left_handed); + // calculate model top cap + if (!top_obj_triangles.is_initialized() && !obj_top.empty()) + init_model(top_obj_triangles, triangulate_expolygons_3d(obj_top, clip_max_z + plane_shift_z, left_handed), { 1.0f, 0.37f, 0.0f, 1.0f }); // calculate support top cap - if (top_sup_triangles.empty() && !sup_top.empty()) - top_sup_triangles = triangulate_expolygons_3d(sup_top, clip_max_z + plane_shift_z, left_handed); + if (!top_sup_triangles.is_initialized() && !sup_top.empty()) + init_model(top_sup_triangles, triangulate_expolygons_3d(sup_top, clip_max_z + plane_shift_z, left_handed), { 1.0f, 0.0f, 0.37f, 1.0f }); } } - if (!bottom_obj_triangles.empty() || !top_obj_triangles.empty() || !bottom_sup_triangles.empty() || !top_sup_triangles.empty()) { - for (const SLAPrintObject::Instance& inst : obj->instances()) { - glsafe(::glPushMatrix()); - glsafe(::glTranslated(unscale(inst.shift.x()), unscale(inst.shift.y()), 0)); - glsafe(::glRotatef(Geometry::rad2deg(inst.rotation), 0.0, 0.0, 1.0)); - if (obj->is_left_handed()) - // The polygons are mirrored by X. - glsafe(::glScalef(-1.0, 1.0, 1.0)); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - glsafe(::glColor3f(1.0f, 0.37f, 0.0f)); - if (!bottom_obj_triangles.empty()) { - glsafe(::glVertexPointer(3, GL_DOUBLE, 0, (GLdouble*)bottom_obj_triangles.front().data())); - glsafe(::glDrawArrays(GL_TRIANGLES, 0, bottom_obj_triangles.size())); - } - if (! top_obj_triangles.empty()) { - glsafe(::glVertexPointer(3, GL_DOUBLE, 0, (GLdouble*)top_obj_triangles.front().data())); - glsafe(::glDrawArrays(GL_TRIANGLES, 0, top_obj_triangles.size())); - } - glsafe(::glColor3f(1.0f, 0.0f, 0.37f)); - if (! bottom_sup_triangles.empty()) { - glsafe(::glVertexPointer(3, GL_DOUBLE, 0, (GLdouble*)bottom_sup_triangles.front().data())); - glsafe(::glDrawArrays(GL_TRIANGLES, 0, bottom_sup_triangles.size())); - } - if (! top_sup_triangles.empty()) { - glsafe(::glVertexPointer(3, GL_DOUBLE, 0, (GLdouble*)top_sup_triangles.front().data())); - glsafe(::glDrawArrays(GL_TRIANGLES, 0, top_sup_triangles.size())); - } - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glPopMatrix()); - } + for (const SLAPrintObject::Instance& inst : obj->instances()) { + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d view_model_matrix = camera.get_view_matrix() * + Geometry::assemble_transform(Vec3d(unscale(inst.shift.x()), unscale(inst.shift.y()), 0.0), + inst.rotation * Vec3d::UnitZ(), Vec3d::Ones(), + obj->is_left_handed() ? Vec3d(-1.0f, 1.0f, 1.0f) : Vec3d::Ones()); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + + bottom_obj_triangles.render_geometry(); + top_obj_triangles.render_geometry(); + bottom_sup_triangles.render_geometry(); + top_sup_triangles.render_geometry(); + } } + + wxGetApp().unbind_shader(); } void GLCanvas3D::_render_selection_sidebar_hints() const @@ -9251,23 +9558,21 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt) _start_timer(); } -Vec3d GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) +Vec3d GLCanvas3D::_mouse_to_3d(const Camera& camera, const Point& mouse_pos, float* z, const std::string& frame_name) { if (m_canvas == nullptr) return Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); - - const Camera& camera = wxGetApp().plater()->get_camera(); Matrix4d modelview = camera.get_view_matrix().matrix(); - Matrix4d projection= camera.get_projection_matrix().matrix(); + Matrix4d projection = camera.get_projection_matrix().matrix(); Vec4i viewport(camera.get_viewport().data()); - GLint y = viewport[3] - (GLint)mouse_pos(1); GLfloat mouse_z; - if (z == nullptr) - glsafe(::glReadPixels((GLint)mouse_pos(0), y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, (void*)&mouse_z)); + if (z == nullptr) { + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->read_pixel(frame_name, (GLint)mouse_pos(0), y, 1, 1, EPixelFormat::DepthComponent, EPixelDataType::Float, (void*)&mouse_z); + } else mouse_z = *z; - Vec3d out; igl::unproject(Vec3d(mouse_pos(0), y, mouse_z), modelview, projection, viewport, out); return out; @@ -9871,7 +10176,7 @@ void GLCanvas3D::_update_sla_shells_outside_state() void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning) { - _set_current(); + _set_current(true); bool show = false; if (!m_volumes.empty()) { show = _is_any_volume_outside(); @@ -9941,7 +10246,7 @@ ERenderPipelineStage GLCanvas3D::_get_current_render_stage() const } void GLCanvas3D::_render_silhouette_effect() -{; +{ RenderPipelineStageModifier render_pipeline_stage_modifier(*this, ERenderPipelineStage::Silhouette); const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); @@ -9950,65 +10255,145 @@ void GLCanvas3D::_render_silhouette_effect() } auto& ogl_manager = *p_ogl_manager; + float t_viewport_scale = 0.5f; + uint32_t viewport_width = 0; + uint32_t viewport_height = 0; + ogl_manager.get_viewport_size(viewport_width, viewport_height); + viewport_width = viewport_width * t_viewport_scale; + viewport_height = viewport_height * t_viewport_scale; { - // BBS: render silhouette - OpenGLManager::FrameBufferModifier frame_buffer_modifier(ogl_manager, "silhouette"); - - glsafe(::glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); - glsafe(::glClearDepth(1.0f)); - glsafe(::glEnable(GL_DEPTH_TEST)); - glsafe(::glDisable(GL_BLEND)); - glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); - - GLShaderProgram* p_silhouette_shader = wxGetApp().get_shader("silhouette"); - if (!p_silhouette_shader) - { - BOOST_LOG_TRIVIAL(error) << "Invalid shader: silhouette. Failed to render highlight effect."; - return; - } - - p_silhouette_shader->start_using(); - - std::array picking_color{ 1.0f, 0.36f, 0.0f, 1.0f }; - if (m_canvas_type == ECanvasType::CanvasAssembleView) { - picking_color[0] = 1.0f; - picking_color[1] = 1.0f; - picking_color[2] = 0.0f; - picking_color[3] = 1.0f; - } - else { - picking_color[0] = 1.0f; - picking_color[1] = 1.0f; - picking_color[2] = 1.0f; - picking_color[3] = 1.0f; - } - p_silhouette_shader->set_uniform("u_base_color", picking_color); - - const Camera& camera = wxGetApp().plater()->get_camera(); - const Transform3d& view_matrix = camera.get_view_matrix(); - const Transform3d& projection_matrix = camera.get_projection_matrix(); - const Matrix4d view_proj = projection_matrix.matrix() * view_matrix.matrix(); - p_silhouette_shader->set_uniform("u_view_projection_matrix", view_proj); - _render_objects(GLVolumeCollection::ERenderType::Opaque, false); - _render_objects(GLVolumeCollection::ERenderType::Transparent, false); - - p_silhouette_shader->stop_using(); - - // BBS: end render silhouette + OpenGLManager::FrameBufferModifier frame_buffer_modifier(ogl_manager, "silhouette", EMSAAType::X4); + frame_buffer_modifier.set_width(viewport_width) + .set_height(viewport_height); + } + // BBS: render silhouette + glViewport(0, 0, viewport_width, viewport_height); + glsafe(::glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); + glsafe(::glClearDepth(1.0f)); + glsafe(::glEnable(GL_DEPTH_TEST)); + glsafe(::glDisable(GL_BLEND)); + glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); + const auto& p_silhouette_shader = wxGetApp().get_shader("silhouette"); + if (!p_silhouette_shader) + { + BOOST_LOG_TRIVIAL(error) << "Invalid shader: silhouette. Failed to render highlight effect."; + return; } - // BBS: composite silhouette + wxGetApp().bind_shader(p_silhouette_shader); - const auto& p_frame_buffer = ogl_manager.get_frame_buffer("silhouette"); + std::array picking_color{ 1.0f, 0.36f, 0.0f, 1.0f }; + if (m_canvas_type == ECanvasType::CanvasAssembleView) { + picking_color[0] = 1.0f; + picking_color[1] = 1.0f; + picking_color[2] = 0.0f; + picking_color[3] = 1.0f; + } + else { + picking_color[0] = 1.0f; + picking_color[1] = 1.0f; + picking_color[2] = 1.0f; + picking_color[3] = 1.0f; + } + p_silhouette_shader->set_uniform("u_base_color", picking_color); + + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d& view_matrix = camera.get_view_matrix(); + const Transform3d& projection_matrix = camera.get_projection_matrix(); + const Matrix4d view_proj = projection_matrix.matrix() * view_matrix.matrix(); + p_silhouette_shader->set_uniform("u_view_projection_matrix", view_proj); + _render_objects(GLVolumeCollection::ERenderType::Opaque, false); + _render_objects(GLVolumeCollection::ERenderType::Transparent, false); + + wxGetApp().unbind_shader(); + + // BBS: end render silhouette + + std::string input_fb_name = "silhouette"; + const auto& p_frame_buffer = ogl_manager.get_frame_buffer(input_fb_name); if (!p_frame_buffer) { + BOOST_LOG_TRIVIAL(error) << "Invalid framebuffer. Failed to render highlight effect."; + return; + } + + int stage = 0; + + const std::array viewport_size{ static_cast(viewport_width), static_cast(viewport_height) }; + + { + glViewport(0, 0, viewport_width, viewport_height); + glsafe(::glDisable(GL_DEPTH_TEST)); + _init_fullscreen_mesh(); + // BBS: gaussian blur + { + OpenGLManager::FrameBufferModifier frame_buffer_gaussian_blur33(ogl_manager, "silhouette_gaussian_blur33", EMSAAType::Disabled); + frame_buffer_gaussian_blur33.set_width(viewport_width) + .set_height(viewport_height); + } + const auto& p_gaussian_blur33_shader = wxGetApp().get_shader("gaussian_blur33"); + if (!p_gaussian_blur33_shader) + { + BOOST_LOG_TRIVIAL(error) << "Invalid gaussian_blur33 shader. Failed to render highlight effect."; + return; + } + wxGetApp().bind_shader(p_gaussian_blur33_shader); + + p_gaussian_blur33_shader->set_uniform("u_viewport_size", viewport_size); + + Matrix3f gaussian_blur33_convolution_matrix; + // https://lodev.org/cgtutor/filtering.html#Gaussian_Blur_ + gaussian_blur33_convolution_matrix.data()[3 * 0 + 0] = 0.077847; + gaussian_blur33_convolution_matrix.data()[3 * 0 + 1] = 0.123317; + gaussian_blur33_convolution_matrix.data()[3 * 0 + 2] = 0.077847; + gaussian_blur33_convolution_matrix.data()[3 * 1 + 0] = 0.123317; + gaussian_blur33_convolution_matrix.data()[3 * 1 + 1] = 0.195346; + gaussian_blur33_convolution_matrix.data()[3 * 1 + 2] = 0.123317; + gaussian_blur33_convolution_matrix.data()[3 * 2 + 0] = 0.077847; + gaussian_blur33_convolution_matrix.data()[3 * 2 + 1] = 0.123317; + gaussian_blur33_convolution_matrix.data()[3 * 2 + 2] = 0.077847; + p_gaussian_blur33_shader->set_uniform("u_convolution_matrix", gaussian_blur33_convolution_matrix); + + const auto color_texture_id = p_frame_buffer->get_color_texture(); + if (!p_frame_buffer->is_texture_valid(color_texture_id)) + { + BOOST_LOG_TRIVIAL(error) << "Invalid silhouette texture. Failed to render highlight effect."; + return; + } + int stage = 0; + p_gaussian_blur33_shader->set_uniform("u_sampler", stage); + glsafe(::glActiveTexture(GL_TEXTURE0 + stage)); + glsafe(::glBindTexture(GL_TEXTURE_2D, color_texture_id)); + + m_full_screen_mesh.render_geometry(); + + wxGetApp().unbind_shader(); + glsafe(::glEnable(GL_DEPTH_TEST)); + // BBS: end gaussian blur + } + ogl_manager.get_viewport_size(viewport_width, viewport_height); + glViewport(0, 0, viewport_width, viewport_height); +} + +void GLCanvas3D::_composite_silhouette_effect() +{ + // BBS: composite silhouette + + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + if (!p_ogl_manager) { + return; + } + const auto& p_frame_buffer = p_ogl_manager->get_frame_buffer("silhouette_gaussian_blur33"); + if (!p_frame_buffer) + { + BOOST_LOG_TRIVIAL(error) << "Invalid framebuffer. Failed to render highlight effect."; return; } const auto color_texture_id = p_frame_buffer->get_color_texture(); if (!p_frame_buffer->is_texture_valid(color_texture_id)) { - BOOST_LOG_TRIVIAL(error) << "Invalid framebuffer. Failed to render highlight effect."; + BOOST_LOG_TRIVIAL(error) << "Invalid silhouette texture. Failed to render highlight effect."; return; } @@ -10016,18 +10401,18 @@ void GLCanvas3D::_render_silhouette_effect() glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - GLShaderProgram* p_silhouette_composite_shader = wxGetApp().get_shader("silhouette_composite"); + const auto& p_silhouette_composite_shader = wxGetApp().get_shader("silhouette_composite"); if (!p_silhouette_composite_shader) { - BOOST_LOG_TRIVIAL(error) << "Invalid silhouette texture. Failed to render highlight effect."; + BOOST_LOG_TRIVIAL(error) << "Invalid silhouette shader. Failed to render highlight effect."; return; } - p_silhouette_composite_shader->start_using(); + wxGetApp().bind_shader(p_silhouette_composite_shader); uint32_t viewport_width = 0; uint32_t viewport_height = 0; - ogl_manager.get_viewport_size(viewport_width, viewport_height); - const std::array viewport_size{ static_cast(viewport_width), static_cast(viewport_height)}; + p_ogl_manager->get_viewport_size(viewport_width, viewport_height); + const std::array viewport_size{ static_cast(viewport_width), static_cast(viewport_height) }; p_silhouette_composite_shader->set_uniform("u_viewport_size", viewport_size); Matrix3f convolution_matrix; @@ -10049,28 +10434,276 @@ void GLCanvas3D::_render_silhouette_effect() glsafe(::glActiveTexture(GL_TEXTURE0 + stage)); glsafe(::glBindTexture(GL_TEXTURE_2D, color_texture_id)); - if (!m_full_screen_mesh.is_initialized()) { - GLModel::Geometry geo; - geo.format.type = GLModel::PrimitiveType::Triangles; - geo.format.vertex_layout = GLModel::Geometry::EVertexLayout::P3T2; - - geo.add_vertex(Vec3f{ -1.0f, -1.0f, 0.0f }, Vec2f{ 0.0f, 0.0f }); - geo.add_vertex(Vec3f{ 3.0f, -1.0f, 0.0f }, Vec2f{ 2.0f, 0.0f }); - geo.add_vertex(Vec3f{ -1.0f, 3.0f, 0.0f }, Vec2f{ 0.0f, 2.0f }); - - geo.add_triangle(0, 1, 2); - - m_full_screen_mesh.init_from(std::move(geo)); - } + _init_fullscreen_mesh(); m_full_screen_mesh.render_geometry(); - p_silhouette_composite_shader->stop_using(); + wxGetApp().unbind_shader(); glsafe(::glDisable(GL_BLEND)); // BBS: end composite silhouette } +void GLCanvas3D::_init_fullscreen_mesh() const +{ + if (m_full_screen_mesh.is_initialized()) { + return; + } + GLModel::Geometry geo; + geo.format.type = GLModel::PrimitiveType::Triangles; + geo.format.vertex_layout = GLModel::Geometry::EVertexLayout::P3T2; + + geo.add_vertex(Vec3f{ -1.0f, -1.0f, 0.0f }, Vec2f{ 0.0f, 0.0f }); + geo.add_vertex(Vec3f{ 3.0f, -1.0f, 0.0f }, Vec2f{ 2.0f, 0.0f }); + geo.add_vertex(Vec3f{ -1.0f, 3.0f, 0.0f }, Vec2f{ 0.0f, 2.0f }); + + geo.add_triangle(0, 1, 2); + + m_full_screen_mesh.init_from(std::move(geo)); +} + +void GLCanvas3D::_composite_main_frame(bool off_screen_rendering_enabled) const +{ + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + + if (!off_screen_rendering_enabled && !p_ogl_manager->is_fxaa_enabled()) { + return; + } + + _init_fullscreen_mesh(); + + uint32_t output_texture_id = UINT32_MAX; + if (p_ogl_manager->is_fxaa_enabled()) { + if (!off_screen_rendering_enabled) { + { + OpenGLManager::FrameBufferModifier fxaa_frame(*p_ogl_manager, "fxaaframe_temp", EMSAAType::Disabled); + } + + p_ogl_manager->blit_framebuffer(OpenGLManager::s_back_frame, "fxaaframe_temp"); + } + + { + OpenGLManager::FrameBufferModifier fxaa_frame(*p_ogl_manager, "fxaaframe", EMSAAType::Disabled); + } + + // BBS: composite main frame + glsafe(::glDisable(GL_DEPTH_TEST)); + glsafe(::glDisable(GL_BLEND)); + + const auto& p_main_frame_buffer = p_ogl_manager->get_frame_buffer(off_screen_rendering_enabled ? "mainframe" : "fxaaframe_temp"); + if (p_main_frame_buffer) { + output_texture_id = p_main_frame_buffer->get_color_texture(); + if (p_main_frame_buffer->is_texture_valid(output_texture_id)) { + const auto& p_fxaa_shader = wxGetApp().get_shader("fxaa"); + if (p_fxaa_shader) { + wxGetApp().bind_shader(p_fxaa_shader); + + const int stage = 0; + p_fxaa_shader->set_uniform("u_sampler", stage); + glsafe(::glActiveTexture(GL_TEXTURE0 + stage)); + glsafe(::glBindTexture(GL_TEXTURE_2D, output_texture_id)); + + uint32_t viewport_width = 0; + uint32_t viewport_height = 0; + p_ogl_manager->get_viewport_size(viewport_width, viewport_height); + const std::array viewport_size{ static_cast(viewport_width), static_cast(viewport_height), 1.0f / viewport_width, 1.0f / viewport_height }; + p_fxaa_shader->set_uniform("u_viewport_size", viewport_size); + + m_full_screen_mesh.render_geometry(); + + wxGetApp().unbind_shader(); + + const auto& p_fxaa_frame_buffer = p_ogl_manager->get_frame_buffer("fxaaframe"); + if (p_fxaa_frame_buffer) { + output_texture_id = p_fxaa_frame_buffer->get_color_texture(); + if (!p_fxaa_frame_buffer->is_texture_valid(output_texture_id)) { + BOOST_LOG_TRIVIAL(error) << "Invalid fxaa texture."; + } + } + else { + BOOST_LOG_TRIVIAL(error) << "Invalid fxaa framebuffer."; + } + } + else { + BOOST_LOG_TRIVIAL(error) << "Invalid fxaa shader."; + } + } + else { + BOOST_LOG_TRIVIAL(error) << "Invalid main frame texture. Failed to composite main frame."; + } + } + } + else if (off_screen_rendering_enabled) { + const auto& p_main_frame_buffer = p_ogl_manager->get_frame_buffer("mainframe"); + if (p_main_frame_buffer) { + output_texture_id = p_main_frame_buffer->get_color_texture(); + } + } + + { + OpenGLManager::FrameBufferModifier fxaa_frame(*p_ogl_manager, OpenGLManager::s_back_frame); + } + + const auto& p_mainframe_composite_shader = wxGetApp().get_shader("mainframe_composite"); + if (!p_mainframe_composite_shader) + { + BOOST_LOG_TRIVIAL(error) << "Invalid mainframe composite shader. Failed to composite main frame."; + return; + } + wxGetApp().bind_shader(p_mainframe_composite_shader); + + const int stage = 0; + p_mainframe_composite_shader->set_uniform("u_sampler", stage); + glsafe(::glActiveTexture(GL_TEXTURE0 + stage)); + glsafe(::glBindTexture(GL_TEXTURE_2D, output_texture_id)); + + m_full_screen_mesh.render_geometry(); + + wxGetApp().unbind_shader(); + + // BBS: end composite mainframe +} + +void GLCanvas3D::_debug_draw_camera(const Camera& t_camera) +{ + if (!m_unit_cube.is_initialized()) { + _init_unit_cube(); + } + + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (p_flat_shader) { + glsafe(::glDisable(GL_DEPTH_TEST)); + glsafe(::glLineWidth(2.0f)); + + Transform3d final_model_matrix{ Transform3d::Identity() }; + final_model_matrix.data()[0 * 4 + 0] = 2.0f; + final_model_matrix.data()[1 * 4 + 1] = 2.0f; + final_model_matrix.data()[2 * 4 + 2] = 2.0f; + + auto vp_matrix = t_camera.get_projection_matrix().matrix() * t_camera.get_view_matrix().matrix(); + auto inv_vp_matrix = vp_matrix.inverse(); + auto m_inv_vp = inv_vp_matrix * final_model_matrix.matrix(); + final_model_matrix = m_inv_vp.eval(); + + wxGetApp().bind_shader(p_flat_shader); + + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + auto mv = view_matrix.matrix() * final_model_matrix.matrix(); + Matrix4d final_mv = mv.eval(); + p_flat_shader->set_uniform("view_model_matrix", final_mv); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); + + m_unit_cube.set_color({ 1.0f, 0.0f, 0.0f, 1.0f }); + m_unit_cube.render_geometry(); + + wxGetApp().unbind_shader(); + } +} + +void GLCanvas3D::_debug_draw_aabb() +{ + if (!m_unit_cube.is_initialized()) { + _init_unit_cube(); + } + + std::vector bbox_list; + + const auto& partplate_list = wxGetApp().plater()->get_partplate_list().get_plate_list(); + for (int i = 0; i < partplate_list.size(); ++i) { + const auto& bbox = partplate_list[i]->get_bounding_box(true); + bbox_list.emplace_back(bbox); + } + + if (m_gizmos.is_running()) { + const auto t_aabb = m_gizmos.get_bounding_box(); + if (t_aabb.defined) { + bbox_list.emplace_back(t_aabb); + } + } + + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (p_flat_shader) { + glsafe(::glDisable(GL_DEPTH_TEST)); + glsafe(::glLineWidth(2.0f)); + wxGetApp().bind_shader(p_flat_shader); + + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); + m_unit_cube.set_color({ 1.0f, 0.0f, 0.0f, 1.0f }); + + for (int i = 0; i < bbox_list.size(); ++i) { + const auto& bbox = bbox_list[i]; + Vec3f b_min = bbox.min.cast(); + Vec3f b_max = bbox.max.cast(); + Vec3f size = bbox.size().cast(); + const auto& center = bbox.center(); + + Transform3d final_model_matrix{ Transform3d::Identity() }; + final_model_matrix.data()[3 * 4 + 0] = center(0); + final_model_matrix.data()[3 * 4 + 1] = center(1); + final_model_matrix.data()[3 * 4 + 2] = center(2); + final_model_matrix.data()[0 * 4 + 0] = size(0); + final_model_matrix.data()[1 * 4 + 1] = size(1); + final_model_matrix.data()[2 * 4 + 2] = size(2); + + p_flat_shader->set_uniform("view_model_matrix", view_matrix * final_model_matrix); + + m_unit_cube.render_geometry(); + } + + wxGetApp().unbind_shader(); + } +} + +void GLCanvas3D::_init_unit_cube() +{ + GLModel::Geometry geo; + geo.format.type = GLModel::PrimitiveType::Lines; + geo.format.vertex_layout = GLModel::Geometry::EVertexLayout::P3; + + const float size = 1.0f; + Vec3f b_min{ -0.5f, -0.5f, -0.5f }; + Vec3f b_max{ 0.5f, 0.5f, 0.5f }; + geo.add_vertex(Vec3f{ b_min(0), b_min(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_min(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_max(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_max(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_min(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_min(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_max(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_max(1), b_max(2) }); + + geo.add_line(0, 1); + geo.add_line(0, 3); + geo.add_line(0, 4); + + geo.add_line(1, 2); + geo.add_line(1, 5); + + geo.add_line(2, 3); + geo.add_line(2, 6); + + geo.add_line(3, 7); + + geo.add_line(4, 5); + geo.add_line(4, 7); + + geo.add_line(5, 6); + + geo.add_line(6, 7); + + m_unit_cube.init_from(std::move(geo)); +} + +void GLCanvas3D::_append_to_frame_callback(const FrameCallback& cb) +{ + m_frame_callback_list.emplace_back(cb); +} + void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) { using NotificationLevel = NotificationManager::NotificationLevel; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index efd4af616..29b3f56d3 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "GLToolbar.hpp" #include "Event.hpp" @@ -20,6 +21,7 @@ #include "IMToolbar.hpp" #include "slic3r/GUI/3DBed.hpp" #include "libslic3r/Slicing.hpp" +#include "libslic3r/Point.hpp" #include "GLEnums.hpp" #include @@ -263,6 +265,15 @@ class GLCanvas3D }; LayersTexture m_layers_texture; + mutable GLModel m_background; + mutable float m_cached_background_thickness{ 0.0f }; + mutable Transform3d m_model_matrix_for_background{ Transform3d::Identity() }; + mutable Matrix3d m_normal_matrix_for_background{ Matrix3d::Identity() }; + + mutable GLModel m_baseline; + mutable GLModel m_profile_curve; + mutable bool m_profile_dirty{ true }; + public: EState state{ Unknown }; float band_width{ 2.0f }; @@ -309,7 +320,7 @@ class GLCanvas3D bool is_initialized() const; void generate_layer_height_texture(); - void render_background_texture(const GLCanvas3D& canvas, const Rect& bar_rect); + void render_background_texture(const GLCanvas3D& canvas); void render_curve(const Rect& bar_rect); void update_slicing_parameters(); @@ -341,6 +352,8 @@ class GLCanvas3D Drag drag; bool ignore_left_up; bool ignore_right_up; + bool rotating{ false }; + bool panning{ false }; Mouse(); @@ -361,12 +374,12 @@ class GLCanvas3D { struct Triangles { - Pointf3s object; - Pointf3s supports; + GLModel object; + GLModel supports; }; - typedef std::map ObjectIdToTrianglesMap; + typedef std::map ObjectIdToModelsMap; double z; - ObjectIdToTrianglesMap triangles; + ObjectIdToModelsMap triangles; SlaCap() { reset(); } void reset() { z = DBL_MAX; triangles.clear(); } @@ -550,6 +563,7 @@ private: bool m_is_dark = false; wxGLCanvas* m_canvas; wxGLContext* m_context; + bool m_dirty_context{ true }; Bed3D &m_bed; std::map m_assembly_view_desc; #if ENABLE_RETINA_GL @@ -666,7 +680,14 @@ private: int assembly_view_count = 0; std::stack m_render_pipeline_stage_stack; - GLModel m_full_screen_mesh; + mutable GLModel m_full_screen_mesh; + + using FrameCallback = std::function; + std::vector m_frame_callback_list; + +#if ENABLE_SHOW_CAMERA_TARGET + mutable GLModel m_camera_target_mark; +#endif // ENABLE_SHOW_CAMERA_TARGET public: OrientSettings& get_orient_settings() @@ -702,10 +723,12 @@ public: public: //BBS: add the height logic + ~SequentialPrintClearance(); void set_polygons(const Polygons& polygons, const std::vector>& height_polygons); void set_render_fill(bool render_fill) { m_render_fill = render_fill; } void set_visible(bool visible) { m_visible = visible; } void render(); + void reset(); friend class GLCanvas3D; }; @@ -746,14 +769,17 @@ public: m_gizmo_highlighter; bool m_can_show_navigator = true; + // for debug draw + GLModel m_unit_cube; + public: explicit GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed); ~GLCanvas3D(); bool is_initialized() const { return m_initialized; } - void set_context(wxGLContext* context) { m_context = context; } - void set_type(ECanvasType type) { m_canvas_type = type; } + void set_context(wxGLContext* context); + void set_type(ECanvasType type); ECanvasType get_canvas_type() { return m_canvas_type; } wxGLCanvas* get_wxglcanvas() { return m_canvas; } @@ -925,7 +951,7 @@ public: bool ban_light = false); static void render_thumbnail_internal(ThumbnailData& thumbnail_data, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, - GLShaderProgram * shader, + const std::shared_ptr& shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso, bool for_picking = false, @@ -933,7 +959,7 @@ public: // render thumbnail using an off-screen framebuffer static void render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, - GLShaderProgram * shader, + const std::shared_ptr& shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso, bool for_picking = false, @@ -941,7 +967,7 @@ public: // render thumbnail using an off-screen framebuffer when GLEW_EXT_framebuffer_object is supported static void render_thumbnail_framebuffer_ext(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, PartPlateList& partplate_list, ModelObjectPtrs& model_objects, const GLVolumeCollection& volumes, std::vector>& extruder_colors, - GLShaderProgram * shader, + const std::shared_ptr& shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso, bool for_picking = false, @@ -956,7 +982,7 @@ public: ModelObjectPtrs & model_objects, const GLVolumeCollection & volumes, std::vector> &extruder_colors, - GLShaderProgram * shader, + const std::shared_ptr& shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso, bool for_picking = false, @@ -1169,10 +1195,12 @@ public: // Convert the screen space coordinate to an object space coordinate. // If the Z screen space coordinate is not provided, a depth buffer value is substituted. - Vec3d _mouse_to_3d(const Point& mouse_pos, float* z = nullptr); + Vec3d _mouse_to_3d(const Camera& camera, const Point& mouse_pos, float* z = nullptr, const std::string& frame_name = ""); bool make_current_for_postinit(); + void mark_context_dirty(); + private: bool _is_shown_on_screen() const; @@ -1188,7 +1216,7 @@ private: //bool _init_view_toolbar(); bool _init_collapse_toolbar(); - bool _set_current(); + bool _set_current(bool force_update = false); void _resize(unsigned int w, unsigned int h); //BBS: add part plate related logic @@ -1300,6 +1328,19 @@ private: ERenderPipelineStage _get_current_render_stage() const; void _render_silhouette_effect(); + void _composite_silhouette_effect(); + + void _init_fullscreen_mesh() const; + + void _composite_main_frame(bool off_screen_rendering_enabled) const; + + void _debug_draw_camera(const Camera& t_camera); + + void _debug_draw_aabb(); + + void _init_unit_cube(); + + void _append_to_frame_callback(const FrameCallback& cb); }; const ModelVolume *get_model_volume(const GLVolume &v, const Model &model); diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 7e538497c..33cc0e6c9 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -493,16 +493,17 @@ void GLModel::init_from(Geometry &&data, bool generate_mesh) m_render_data.back().color = data.color.get_data(); if (generate_mesh) { if (!mesh) { mesh = new TriangleMesh(); } - mesh->its = std::move(data.get_as_indexed_triangle_set()); + mesh->its = data.get_as_indexed_triangle_set(); } m_render_data.back().geometry = std::move(data); + const auto& geometry = m_render_data.back().geometry; // update bounding box - for (size_t i = 0; i < data.vertices_count(); ++i) { - const size_t position_stride = Geometry::position_stride_floats(data.format); + for (size_t i = 0; i < geometry.vertices_count(); ++i) { + const size_t position_stride = Geometry::position_stride_floats(geometry.format); if (position_stride == 3) - m_bounding_box.merge(m_render_data.back().geometry.extract_position_3(i).cast()); + m_bounding_box.merge(geometry.extract_position_3(i).cast()); else if (position_stride == 2) { - const Vec2f position = m_render_data.back().geometry.extract_position_2(i); + const Vec2f position = geometry.extract_position_2(i); m_bounding_box.merge(Vec3f(position.x(), position.y(), 0.0f).cast()); } } @@ -522,6 +523,8 @@ void GLModel::init_from(const InitializationData& data) RenderData rdata; rdata.type = entity.type; rdata.color = entity.color; + rdata.geometry.color = entity.color; + rdata.geometry.format.type = entity.type; // vertices/normals data std::vector vertices(6 * entity.positions.size()); @@ -638,6 +641,42 @@ bool GLModel::init_from_file(const std::string& filename) return true; } +void GLModel::init_model_from_polygon(const Polygons &polygons, float z) +{ + if (polygons.empty()) { + assert(false); + return; + } + + GLModel::Geometry data; + data.format = {PrimitiveType::Lines, Geometry::EVertexLayout::P3}; + + size_t segments_count = 0; + for (const Polygon &polygon : polygons) { segments_count += polygon.points.size(); } + + data.reserve_vertices(2 * segments_count); + data.reserve_indices(2 * segments_count); + + // vertices + indices + unsigned int vertices_counter = 0; + for (const Polygon &poly : polygons) { + for (size_t i = 0; i < poly.points.size(); ++i) { + const Point &p0 = poly.points[i]; + const Point &p1 = (i == poly.points.size() - 1) ? poly.points.front() : poly.points[i + 1]; + data.add_vertex(Vec3f(unscale(p0.x()), unscale(p0.y()), z)); + data.add_vertex(Vec3f(unscale(p1.x()), unscale(p1.y()), z)); + vertices_counter += 2; + data.add_line(vertices_counter - 2, vertices_counter - 1); + } + } + + // update bounding box + for (size_t i = 0; i < data.vertices_count(); ++i) { + m_bounding_box.merge(data.extract_position_3(i).cast()); + } + init_from(std::move(data), false); +} + bool GLModel::init_model_from_poly(const std::vector &triangles, float z, bool generate_mesh) { if (triangles.empty() || triangles.size() % 3 != 0) @@ -803,77 +842,23 @@ static GLenum get_index_type(const GLModel::Geometry &data) } } -void GLModel::render() const -{ - GLShaderProgram* shader = wxGetApp().get_current_shader(); - - for (const RenderData& data : m_render_data) { - // sends data to gpu if not done yet - if (data.vbo_id == 0 || data.ibo_id == 0) { - auto origin_data = const_cast(&data); - if (data.geometry.vertices_count() > 0 && data.geometry.indices_count() > 0 - && !send_to_gpu(*origin_data, data.geometry.vertices, data.geometry.indices)) - continue; - } - bool has_normal = true; - if (data.geometry.vertices_count() > 0) { - has_normal = Geometry::has_normal(data.geometry.format); - } - - GLenum mode; - switch (data.type) - { - default: - case PrimitiveType::Triangles: { mode = GL_TRIANGLES; break; } - case PrimitiveType::Lines: { mode = GL_LINES; break; } - case PrimitiveType::LineStrip: { mode = GL_LINE_STRIP; break; } - case PrimitiveType::LineLoop: { mode = GL_LINE_LOOP; break; } - } - - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id)); - if (has_normal) { - glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void *) 0)); - glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), (const void *) (3 * sizeof(float)))); - - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); - } else { - glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void *) 0)); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - } - - if (shader != nullptr) - shader->set_uniform("uniform_color", data.color); - else - glsafe(::glColor4fv(data.color.data())); - - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id)); - glsafe(::glDrawElements(mode, static_cast(data.indices_count), GL_UNSIGNED_INT, (const void*)0)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - } -} - -void GLModel::render_geometry() { +void GLModel::render_geometry() const { render_geometry(0,std::make_pair(0, get_indices_count())); } -void GLModel::render_geometry(int i,const std::pair &range) +void GLModel::render_geometry(int i,const std::pair &range) const { if (range.second == range.first) return; - GLShaderProgram *shader = wxGetApp().get_current_shader(); + const auto shader = wxGetApp().get_current_shader(); if (shader == nullptr) return; auto &render_data = m_render_data[i]; // sends data to gpu if not done yet if (render_data.vbo_id == 0 || render_data.ibo_id == 0) { + auto origin_data = const_cast(&render_data); if (render_data.geometry.vertices_count() > 0 && render_data.geometry.indices_count() > 0 && - !send_to_gpu(render_data, render_data.geometry.vertices, render_data.geometry.indices)) + !send_to_gpu(*origin_data, render_data.geometry.vertices, render_data.geometry.indices)) return; } const Geometry &data = render_data.geometry; @@ -942,36 +927,40 @@ void GLModel::create_or_update_mats_vbo(unsigned int &vbo, const std::vector()); } - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); + glsafe(::glGenBuffers(1, &vbo)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, vbo)); auto one_mat_all_size = sizeof(float) * 16; - glBufferData(GL_ARRAY_BUFFER, mats.size() * one_mat_all_size, out_mats.data(), GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glsafe(::glBufferData(GL_ARRAY_BUFFER, mats.size() * one_mat_all_size, out_mats.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -void GLModel::bind_mats_vbo(unsigned int instance_mats_vbo, unsigned int instances_count, int location) +void GLModel::bind_mats_vbo(unsigned int instance_mats_vbo, unsigned int instances_count, const std::vector& locations) { if (instance_mats_vbo == 0 || instances_count == 0) { return; } + if (locations.size() < 4) { + return; + } auto one_mat_all_size = sizeof(float) * 16; auto one_mat_col_size = sizeof(float) * 4; glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instance_mats_vbo)); - for (unsigned int i = 0; i < instances_count; i++) { // set attribute pointers for matrix (4 times vec4) - glsafe(glEnableVertexAttribArray(location)); - glsafe(glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) 0)); - glsafe(glEnableVertexAttribArray(location + 1)); - glsafe(glVertexAttribPointer(location + 1, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (one_mat_col_size))); - glsafe(glEnableVertexAttribArray(location + 2)); - glsafe(glVertexAttribPointer(location + 2, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (2 * one_mat_col_size))); - glsafe(glEnableVertexAttribArray(location + 3)); - glsafe(glVertexAttribPointer(location + 3, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (3 * one_mat_col_size))); - // Update the matrix every time after an object is drawn//useful - glsafe(glVertexAttribDivisor(location, 1)); - glsafe(glVertexAttribDivisor(location + 1, 1)); - glsafe(glVertexAttribDivisor(location + 2, 1)); - glsafe(glVertexAttribDivisor(location + 3, 1)); - } + + glsafe(glEnableVertexAttribArray(locations[0])); + glsafe(glVertexAttribPointer(locations[0], 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void*)0)); + glsafe(glEnableVertexAttribArray(locations[1])); + glsafe(glVertexAttribPointer(locations[1], 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void*)(one_mat_col_size))); + glsafe(glEnableVertexAttribArray(locations[2])); + glsafe(glVertexAttribPointer(locations[2], 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void*)(2 * one_mat_col_size))); + glsafe(glEnableVertexAttribArray(locations[3])); + glsafe(glVertexAttribPointer(locations[3], 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void*)(3 * one_mat_col_size))); + // Update the matrix every time after an object is drawn//useful + glsafe(glVertexAttribDivisor(locations[0], 1)); + glsafe(glVertexAttribDivisor(locations[1], 1)); + glsafe(glVertexAttribDivisor(locations[2], 1)); + glsafe(glVertexAttribDivisor(locations[3], 1)); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count) @@ -985,7 +974,7 @@ void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned return; } if (m_render_data.size() != 1) { return; } - GLShaderProgram *shader = wxGetApp().get_current_shader(); + const auto shader = wxGetApp().get_current_shader(); if (shader == nullptr) return; auto &render_data = m_render_data[0]; @@ -1012,7 +1001,6 @@ void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned int position_id = -1; int normal_id = -1; int tex_coord_id = -1; - int instace_mats_id = -1; if (position) { position_id = shader->get_attrib_location("v_position"); if (position_id != -1) { @@ -1037,12 +1025,19 @@ void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned glsafe(::glEnableVertexAttribArray(tex_coord_id)); } } + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); //glBindAttribLocation(shader->get_id(), 2, "instanceMatrix"); //glBindAttribLocation(2, "instanceMatrix"); //shader->bind(shaderProgram, 0, 'position'); - instace_mats_id = shader->get_attrib_location("instanceMatrix"); - if (instace_mats_id != -1) { - bind_mats_vbo(instance_mats_vbo, instances_count, instace_mats_id); + const int i_loc0 = shader->get_attrib_location("i_data0"); + const int i_loc1 = shader->get_attrib_location("i_data1"); + const int i_loc2 = shader->get_attrib_location("i_data2"); + const int i_loc3 = shader->get_attrib_location("i_data3"); + + const bool has_instancing_attributes = (i_loc0 != -1 && i_loc1 != -1 && i_loc2 != -1 && i_loc3 != -1); + if (has_instancing_attributes) { + bind_mats_vbo(instance_mats_vbo, instances_count, { i_loc0, i_loc1, i_loc2, i_loc3}); } else { return; @@ -1053,13 +1048,19 @@ void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned glsafe(::glDrawElementsInstanced(mode, range.second - range.first, index_type, (const void *) (range.first * Geometry::index_stride_bytes(data)), instances_count)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - if (instace_mats_id != -1) glsafe(::glDisableVertexAttribArray(instace_mats_id)); + if (has_instancing_attributes && instance_mats_vbo > 0) { + glsafe(::glVertexAttribDivisor(i_loc0, 0)); + glsafe(::glVertexAttribDivisor(i_loc1, 0)); + glsafe(::glVertexAttribDivisor(i_loc2, 0)); + glsafe(::glVertexAttribDivisor(i_loc3, 0)); + glsafe(::glDisableVertexAttribArray(i_loc0)); + glsafe(::glDisableVertexAttribArray(i_loc1)); + glsafe(::glDisableVertexAttribArray(i_loc2)); + glsafe(::glDisableVertexAttribArray(i_loc3)); + } if (tex_coord_id != -1) glsafe(::glDisableVertexAttribArray(tex_coord_id)); if (normal_id != -1) glsafe(::glDisableVertexAttribArray(normal_id)); if (position_id != -1) glsafe(::glDisableVertexAttribArray(position_id)); - - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const @@ -1067,7 +1068,7 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance if (instances_vbo == 0) return; - GLShaderProgram* shader = wxGetApp().get_current_shader(); + const auto shader = wxGetApp().get_current_shader(); assert(shader == nullptr || boost::algorithm::iends_with(shader->get_name(), "_instanced")); // vertex attributes diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 79e53c9d8..49a58479a 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -181,6 +181,7 @@ namespace GUI { void init_from(const indexed_triangle_set& its); void init_from(const Polygons& polygons, float z); bool init_from_file(const std::string& filename); + void init_model_from_polygon(const Polygons &polygons, float z); bool init_model_from_poly(const std::vector &triangles, float z, bool generate_mesh = false); bool init_model_from_lines(const Lines &lines, float z, bool generate_mesh = false); bool init_model_from_lines(const Lines3 &lines, bool generate_mesh = false); @@ -190,11 +191,10 @@ namespace GUI { void set_color(const ColorRGBA &color); void reset(); - void render() const; - void render_geometry(); - void render_geometry(int i,const std::pair &range); + void render_geometry() const; + void render_geometry(int i,const std::pair &range) const; static void create_or_update_mats_vbo(unsigned int &vbo, const std::vector &mats); - void bind_mats_vbo(unsigned int instance_mats_vbo, unsigned int instances_count, int location); + void bind_mats_vbo(unsigned int instance_mats_vbo, unsigned int instances_count, const std::vector& locations); void render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count); void render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count, const std::pair &range); void render_instanced(unsigned int instances_vbo, unsigned int instances_count) const; diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index f6dfbe10f..ddb088cac 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -4,6 +4,7 @@ #include "GLCanvas3D.hpp" #include "GUI_App.hpp" #include "Plater.hpp" +#include "OpenGLManager.hpp" #include #include @@ -75,13 +76,18 @@ namespace GUI { return; const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix_for_billboard(); + const auto& proj_matrix = camera.get_projection_matrix(); float inv_zoom = (float)camera.get_inv_zoom(); Size cnv_size = canvas.get_canvas_size(); - float cnv_half_width = 0.5f * (float)cnv_size.get_width(); - float cnv_half_height = 0.5f * (float)cnv_size.get_height(); - if ((cnv_half_width == 0.0f) || (cnv_half_height == 0.0f)) + const int cnv_width = cnv_size.get_width(); + const int cnv_height = cnv_size.get_height(); + if (0 == cnv_width || 0 == cnv_height) { return; + } + float cnv_half_width = 0.5f * static_cast(cnv_width); + float cnv_half_height = 0.5f * static_cast(cnv_height); Vec2d start(m_start_corner(0) - cnv_half_width, cnv_half_height - m_start_corner(1)); Vec2d end(m_end_corner(0) - cnv_half_width, cnv_half_height - m_end_corner(1)); @@ -91,37 +97,73 @@ namespace GUI { float right = (float)std::max(start(0), end(0)) * inv_zoom; float bottom = (float)std::min(start(1), end(1)) * inv_zoom; - glsafe(::glLineWidth(1.5f)); - float color[3]; - color[0] = 0.00f; - color[1] = 1.00f; - color[2] = 0.38f; - glsafe(::glColor3fv(color)); + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) { + return; + } + if (!m_rectangle.is_initialized()) { + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(4); + init_data.reserve_indices(4); + + // vertices + init_data.add_vertex(Vec3f(-0.5f, -0.5f, 0.0f)); + init_data.add_vertex(Vec3f(0.5f, -0.5f, 0.0f)); + init_data.add_vertex(Vec3f(0.5f, 0.5f, 0.0f)); + init_data.add_vertex(Vec3f(-0.5f, 0.5f, 0.0f)); + + // indices + init_data.add_index(0); + init_data.add_index(1); + init_data.add_index(2); + init_data.add_index(3); + + m_rectangle.init_from(std::move(init_data)); + } + + Transform3d model_matrix{ Transform3d::Identity() }; + model_matrix.data()[3 * 4 + 0] = (left + right) * 0.5f; + model_matrix.data()[3 * 4 + 1] = (top + bottom) * 0.5f; + model_matrix.data()[0 * 4 + 0] = (right - left); + model_matrix.data()[1 * 4 + 1] = (top - bottom); + + GLboolean was_line_stipple_enabled = GL_FALSE; + + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(1.5f); glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glPushMatrix()); - glsafe(::glLoadIdentity()); - // ensure that the rectangle is renderered inside the frustrum - glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.5))); - // ensure that the overlay fits the frustrum near z plane - double gui_scale = camera.get_gui_scale(); - glsafe(::glScaled(gui_scale, gui_scale, 1.0)); +#ifdef __APPLE__ + const auto& gl_info = p_ogl_manager->get_gl_info(); + const auto formated_gl_version = gl_info.get_formated_gl_version(); + if (formated_gl_version < 30) +#endif + { + glsafe(::glGetBooleanv(GL_LINE_STIPPLE, &was_line_stipple_enabled)); + glsafe(::glLineStipple(4, 0xAAAA)); + glsafe(::glEnable(GL_LINE_STIPPLE)); + } - glsafe(::glPushAttrib(GL_ENABLE_BIT)); - glsafe(::glLineStipple(4, 0xAAAA)); - glsafe(::glEnable(GL_LINE_STIPPLE)); + wxGetApp().bind_shader(p_flat_shader); - ::glBegin(GL_LINE_LOOP); - ::glVertex2f((GLfloat)left, (GLfloat)bottom); - ::glVertex2f((GLfloat)right, (GLfloat)bottom); - ::glVertex2f((GLfloat)right, (GLfloat)top); - ::glVertex2f((GLfloat)left, (GLfloat)top); - glsafe(::glEnd()); + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); - glsafe(::glPopAttrib()); + m_rectangle.set_color({ 0.0f, 1.0f, 0.38f, 1.0f }); + m_rectangle.render_geometry(); - glsafe(::glPopMatrix()); + wxGetApp().unbind_shader(); + + if (!was_line_stipple_enabled) { +#ifdef __APPLE__ + if (formated_gl_version < 30) +#endif + { + glsafe(::glDisable(GL_LINE_STIPPLE)); + } + } } } // namespace GUI diff --git a/src/slic3r/GUI/GLSelectionRectangle.hpp b/src/slic3r/GUI/GLSelectionRectangle.hpp index d9869771e..6c9cb456a 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.hpp +++ b/src/slic3r/GUI/GLSelectionRectangle.hpp @@ -2,10 +2,10 @@ #define slic3r_GLSelectionRectangle_hpp_ #include "libslic3r/Point.hpp" - +#include "GLModel.hpp" namespace Slic3r { namespace GUI { - + struct Camera; class GLCanvas3D; @@ -46,9 +46,10 @@ private: EState m_state = Off; Vec2d m_start_corner; Vec2d m_end_corner; + mutable GLModel m_rectangle; }; - + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLShader.cpp b/src/slic3r/GUI/GLShader.cpp index 41166b5a7..edccb283b 100644 --- a/src/slic3r/GUI/GLShader.cpp +++ b/src/slic3r/GUI/GLShader.cpp @@ -168,9 +168,6 @@ bool GLShaderProgram::init_from_texts(const std::string& name, const ShaderSourc if (shader_ids[i] > 0) glsafe(::glAttachShader(m_id, shader_ids[i])); } - if (boost::ends_with(name,"_instance")) { - glBindAttribLocation(m_id, 3, "instanceMatrix"); - } glsafe(::glLinkProgram(m_id)); GLint params; @@ -204,11 +201,6 @@ void GLShaderProgram::start_using() const glsafe(::glUseProgram(m_id)); } -void GLShaderProgram::stop_using() const -{ - glsafe(::glUseProgram(0)); -} - bool GLShaderProgram::set_uniform(const char* name, int value) const { int id = get_uniform_location(name); @@ -387,13 +379,13 @@ int GLShaderProgram::get_attrib_location(const char* name) const // Shader program not loaded. This should not happen. return -1; - //auto it = std::find_if(m_attrib_location_cache.begin(), m_attrib_location_cache.end(), [name](const auto& p) { return p.first == name; }); - //if (it != m_attrib_location_cache.end()) - // // Attrib ID cached. - // return it->second; + auto it = std::find_if(m_attrib_location_cache.begin(), m_attrib_location_cache.end(), [name](const auto& p) { return p.first == name; }); + if (it != m_attrib_location_cache.end()) + // Attrib ID cached. + return it->second; int id = ::glGetAttribLocation(m_id, name); - //const_cast(this)->m_attrib_location_cache.push_back({ name, id }); + const_cast(this)->m_attrib_location_cache.push_back({ name, id }); return id; } diff --git a/src/slic3r/GUI/GLShader.hpp b/src/slic3r/GUI/GLShader.hpp index 04bcbcfe4..c412d16d1 100644 --- a/src/slic3r/GUI/GLShader.hpp +++ b/src/slic3r/GUI/GLShader.hpp @@ -11,6 +11,7 @@ namespace Slic3r { class GLShaderProgram { + friend class GLShadersManager; public: enum class EShaderType { @@ -41,9 +42,6 @@ public: const std::string& get_name() const { return m_name; } unsigned int get_id() const { return m_id; } - void start_using() const; - void stop_using() const; - bool set_uniform(const char* name, int value) const; bool set_uniform(const char* name, bool value) const; bool set_uniform(const char* name, float value) const; @@ -68,6 +66,9 @@ public: int get_attrib_location(const char* name) const; // returns -1 if not found int get_uniform_location(const char* name) const; + +private: + void start_using() const; }; } // namespace Slic3r diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index fa03b0619..523797f0a 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -3,6 +3,7 @@ #include "GLShadersManager.hpp" #include "3DScene.hpp" #include "GUI_App.hpp" +#include "GLShader.hpp" #include #include @@ -33,43 +34,34 @@ std::pair GLShadersManager::init() bool valid = true; + const std::string glsl_version_prefix = GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1) ? "140/" : "110/"; + // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview - valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" }); + valid &= append_shader("gouraud_light", { glsl_version_prefix + "gouraud_light.vs", glsl_version_prefix + "gouraud_light.fs" }); //used to render thumbnail - valid &= append_shader("thumbnail", { "thumbnail.vs", "thumbnail.fs" }); + valid &= append_shader("thumbnail", { glsl_version_prefix + "thumbnail.vs", glsl_version_prefix + "thumbnail.fs" }); // used to render first layer for calibration - valid &= append_shader("cali", { "cali.vs", "cali.fs"}); - valid &= append_shader("flat", {"110/flat.vs", "110/flat.fs"}); - valid &= append_shader("flat_instance", {"110/flat_instance.vs", "110/flat.fs"}); + valid &= append_shader("flat", { glsl_version_prefix + "flat.vs", glsl_version_prefix + "flat.fs"}); + valid &= append_shader("flat_instance", { glsl_version_prefix + "flat_instance.vs", glsl_version_prefix + "flat.fs"}); // used to render printbed - valid &= append_shader("printbed", {"110/printbed.vs", "110/printbed.fs"}); - valid &= append_shader("hotbed", {"110/hotbed.vs", "110/hotbed.fs"}); + valid &= append_shader("printbed", { glsl_version_prefix + "printbed.vs", glsl_version_prefix + "printbed.fs"}); + valid &= append_shader("hotbed", { glsl_version_prefix + "hotbed.vs", glsl_version_prefix + "hotbed.fs"}); // used to render options in gcode preview if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) - valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); + valid &= append_shader("gouraud_light_instanced", { glsl_version_prefix + "gouraud_light_instanced.vs", glsl_version_prefix + "gouraud_light.fs" }); // used to render extrusion and travel paths as lines in gcode preview - valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); + valid &= append_shader("toolpaths_lines", { glsl_version_prefix + "toolpaths_lines.vs", glsl_version_prefix + "toolpaths_lines.fs" }); // used to render objects in 3d editor - //if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 0)) { - if (0) { - valid &= append_shader("gouraud", { "gouraud_130.vs", "gouraud_130.fs" } -#if ENABLE_ENVIRONMENT_MAP - , { "ENABLE_ENVIRONMENT_MAP"sv } -#endif // ENABLE_ENVIRONMENT_MAP - ); - } - else { - valid &= append_shader("gouraud", { "gouraud.vs", "gouraud.fs" } + valid &= append_shader("gouraud", { glsl_version_prefix + "gouraud.vs", glsl_version_prefix + "gouraud.fs" } #if ENABLE_ENVIRONMENT_MAP , { "ENABLE_ENVIRONMENT_MAP"sv } #endif // ENABLE_ENVIRONMENT_MAP ); - } // used to render variable layers heights in 3d editor - valid &= append_shader("variable_layer_height", { "variable_layer_height.vs", "variable_layer_height.fs" }); + valid &= append_shader("variable_layer_height", { glsl_version_prefix + "variable_layer_height.vs", glsl_version_prefix + "variable_layer_height.fs" }); // used to render highlight contour around selected triangles inside the multi-material gizmo - valid &= append_shader("mm_contour", { "mm_contour.vs", "mm_contour.fs" }); + valid &= append_shader("mm_contour", { glsl_version_prefix + "mm_contour.vs", glsl_version_prefix + "mm_contour.fs" }); // Used to render painted triangles inside the multi-material gizmo. Triangle normals are computed inside fragment shader. // For Apple's on Arm CPU computed triangle normals inside fragment shader using dFdx and dFdy has the opposite direction. // Because of this, objects had darker colors inside the multi-material gizmo. @@ -80,23 +72,30 @@ std::pair GLShadersManager::init() //if (GUI::wxGetApp().plater() && GUI::wxGetApp().plater()->is_wireframe_enabled()) // valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); //else - valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});//{"mm_gouraud.vs", "mm_gouraud.fs"} + valid &= append_shader("mm_gouraud", { glsl_version_prefix + "mm_gouraud_wireframe.vs", glsl_version_prefix + "mm_gouraud_wireframe.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});//{"mm_gouraud.vs", "mm_gouraud.fs"} } else { //if (GUI::wxGetApp().plater() && GUI::wxGetApp().plater()->is_wireframe_enabled()) // valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"}); //else - valid &= append_shader("mm_gouraud", {"mm_gouraud_wireframe.vs", "mm_gouraud_wireframe.fs"});//{"mm_gouraud.vs", "mm_gouraud.fs"} + valid &= append_shader("mm_gouraud", { glsl_version_prefix + "mm_gouraud_wireframe.vs", glsl_version_prefix + "mm_gouraud_wireframe.fs"});//{"mm_gouraud.vs", "mm_gouraud.fs"} } - //BBS: add shader for outline - valid &= append_shader("outline", { "outline.vs", "outline.fs" }); + valid &= append_shader("silhouette", { glsl_version_prefix + "silhouette.vs", glsl_version_prefix + "silhouette.fs" }); - valid &= append_shader("silhouette", { "110/silhouette.vs", "110/silhouette.fs" }); + valid &= append_shader("silhouette_composite", { glsl_version_prefix + "silhouette_composite.vs", glsl_version_prefix + "silhouette_composite.fs" }); - valid &= append_shader("silhouette_composite", { "110/silhouette_composite.vs", "110/silhouette_composite.fs" }); + valid &= append_shader("background", { glsl_version_prefix + "background.vs", glsl_version_prefix + "background.fs" }); - valid &= append_shader("imgui", { "110/imgui.vs", "110/imgui.fs" }); + valid &= append_shader("flat_texture", { glsl_version_prefix + "flat_texture.vs", glsl_version_prefix + "flat_texture.fs" }); + + valid &= append_shader("imgui", { glsl_version_prefix + "imgui.vs", glsl_version_prefix + "imgui.fs" }); + + valid &= append_shader("mainframe_composite", { glsl_version_prefix + "mainframe_composite.vs", glsl_version_prefix + "mainframe_composite.fs" }); + + valid &= append_shader("fxaa", { glsl_version_prefix + "fxaa.vs", glsl_version_prefix + "fxaa.fs" }); + + valid &= append_shader("gaussian_blur33", { glsl_version_prefix + "gaussian_blur33.vs", glsl_version_prefix + "gaussian_blur33.fs" }); return { valid, error }; } @@ -106,21 +105,38 @@ void GLShadersManager::shutdown() m_shaders.clear(); } -GLShaderProgram* GLShadersManager::get_shader(const std::string& shader_name) +const std::shared_ptr& GLShadersManager::get_shader(const std::string& shader_name) const { - auto it = std::find_if(m_shaders.begin(), m_shaders.end(), [&shader_name](std::unique_ptr& p) { return p->get_name() == shader_name; }); - return (it != m_shaders.end()) ? it->get() : nullptr; + const auto& it = std::find_if(m_shaders.begin(), m_shaders.end(), [&shader_name](const std::shared_ptr& p) { return p->get_name() == shader_name; }); + if (it != m_shaders.end()) { + return *it; + } + static std::shared_ptr s_empty_shader{ nullptr }; + return s_empty_shader; } -GLShaderProgram* GLShadersManager::get_current_shader() +std::shared_ptr GLShadersManager::get_current_shader() const { - GLint id = 0; - glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, &id)); - if (id == 0) - return nullptr; + auto rt = m_current_shader.lock(); + return rt; +} - auto it = std::find_if(m_shaders.begin(), m_shaders.end(), [id](std::unique_ptr& p) { return static_cast(p->get_id()) == id; }); - return (it != m_shaders.end()) ? it->get() : nullptr; +void GLShadersManager::bind_shader(const std::shared_ptr& p_shader) +{ + if (p_shader) { + p_shader->start_using(); + } + else { + glsafe(::glUseProgram(0)); + } + + m_current_shader = p_shader; +} + +void GLShadersManager::unbind_shader() +{ + glsafe(::glUseProgram(0)); + m_current_shader.reset(); } } // namespace Slic3r diff --git a/src/slic3r/GUI/GLShadersManager.hpp b/src/slic3r/GUI/GLShadersManager.hpp index b2bbc140b..93e12559d 100644 --- a/src/slic3r/GUI/GLShadersManager.hpp +++ b/src/slic3r/GUI/GLShadersManager.hpp @@ -1,17 +1,17 @@ #ifndef slic3r_GLShadersManager_hpp_ #define slic3r_GLShadersManager_hpp_ -#include "GLShader.hpp" - #include #include #include namespace Slic3r { +class GLShaderProgram; + class GLShadersManager { - std::vector> m_shaders; + std::vector> m_shaders; public: std::pair init(); @@ -19,10 +19,17 @@ public: void shutdown(); // returns nullptr if not found - GLShaderProgram* get_shader(const std::string& shader_name); + const std::shared_ptr& get_shader(const std::string& shader_name) const; // returns currently active shader, nullptr if none - GLShaderProgram* get_current_shader(); + std::shared_ptr get_current_shader() const; + + void bind_shader(const std::shared_ptr& p_shader); + + void unbind_shader(); + +private: + std::weak_ptr m_current_shader; }; } // namespace Slic3r diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 7336b3ba2..56615418f 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -705,25 +705,75 @@ void GLTexture::render_texture(unsigned int tex_id, float left, float right, flo void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, float bottom, float top, const GLTexture::Quad_UVs& uvs) { + const auto& p_flat_texture_shader = wxGetApp().get_shader("flat_texture"); + if (!p_flat_texture_shader) { + return; + } + + GLModel& model = init_model_for_render_image(); + + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d view_matrix = camera.get_view_matrix_for_billboard(); + const auto& projection_matrix = camera.get_projection_matrix(); + + const float center_x = (left + right) * 0.5f; + const float center_y = (bottom + top) * 0.5f; + const float scale_x = (right - left); + const float scale_y = (top - bottom); + Transform3d model_matrix{ Transform3d::Identity() }; + model_matrix.data()[3 * 4 + 0] = center_x; + model_matrix.data()[3 * 4 + 1] = center_y; + model_matrix.data()[0 * 4 + 0] = scale_x; + model_matrix.data()[1 * 4 + 1] = scale_y; + + Transform2d uv_matrix{ Transform2d::Identity() }; + + float center_u = (uvs.right_bottom.u + uvs.left_bottom.u) * 0.5f; + float center_v = (uvs.right_top.v + uvs.right_bottom.v) * 0.5f; + float scale_u = (uvs.right_bottom.u - uvs.left_bottom.u); + float scale_v = (uvs.right_bottom.v - uvs.right_top.v); + + uv_matrix.data()[3 * 2 + 0] = center_u; + uv_matrix.data()[3 * 2 + 1] = center_v; + uv_matrix.data()[3 * 0 + 0] = scale_u; + uv_matrix.data()[3 * 1 + 1] = scale_v; + glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - glsafe(::glEnable(GL_TEXTURE_2D)); - glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + const auto& gl_info = p_ogl_manager->get_gl_info(); + const auto formated_gl_version = gl_info.get_formated_gl_version(); + if (formated_gl_version < 30) + { + glsafe(::glEnable(GL_TEXTURE_2D)); + } + //glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id)); - - ::glBegin(GL_QUADS); - ::glTexCoord2f(uvs.left_bottom.u, uvs.left_bottom.v); ::glVertex2f(left, bottom); - ::glTexCoord2f(uvs.right_bottom.u, uvs.right_bottom.v); ::glVertex2f(right, bottom); - ::glTexCoord2f(uvs.right_top.u, uvs.right_top.v); ::glVertex2f(right, top); - ::glTexCoord2f(uvs.left_top.u, uvs.left_top.v); ::glVertex2f(left, top); - glsafe(::glEnd()); + const int stage = 0; + glsafe(::glActiveTexture(GL_TEXTURE0 + stage)); + wxGetApp().bind_shader(p_flat_texture_shader); + p_flat_texture_shader->set_uniform("u_texture", stage); + p_flat_texture_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + p_flat_texture_shader->set_uniform("projection_matrix", projection_matrix); + p_flat_texture_shader->set_uniform("u_uvTransformMatrix", uv_matrix.matrix()); + model.render_geometry(); + wxGetApp().unbind_shader(); glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); - glsafe(::glDisable(GL_TEXTURE_2D)); glsafe(::glDisable(GL_BLEND)); + + if (formated_gl_version < 30) { + glsafe(::glDisable(GL_TEXTURE_2D)); + } +} + +void GLTexture::shutdown() +{ + auto& model = get_model_for_render_image(); + model.reset(); } bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy) @@ -994,5 +1044,35 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo return true; } +GLModel& GLTexture::init_model_for_render_image() +{ + auto& model = get_model_for_render_image(); + if (!model.is_initialized()) { + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3T2 }; + init_data.reserve_vertices(4); + init_data.reserve_indices(6); + + // vertices + init_data.add_vertex(Vec3f(-0.5f, -0.5f, 0.0f), Vec2f(-0.5f, 0.5f)); + init_data.add_vertex(Vec3f(0.5f, -0.5f, 0.0f), Vec2f(0.5f, 0.5f)); + init_data.add_vertex(Vec3f(0.5f, 0.5f, 0.0f), Vec2f(0.5f, -0.5f)); + init_data.add_vertex(Vec3f(-0.5f, 0.5f, 0.0f), Vec2f(-0.5f, -0.5f)); + + // indices + init_data.add_triangle(0, 1, 2); + init_data.add_triangle(2, 3, 0); + + model.init_from(std::move(init_data)); + } + return model; +} + +GLModel& GLTexture::get_model_for_render_image() +{ + static GLModel s_model_for_render_image; + return s_model_for_render_image; +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp index 6acf57557..26b2a3273 100644 --- a/src/slic3r/GUI/GLTexture.hpp +++ b/src/slic3r/GUI/GLTexture.hpp @@ -14,6 +14,8 @@ class wxImage; namespace Slic3r { namespace GUI { + class GLModel; + class GLTexture { class Compressor @@ -140,10 +142,12 @@ namespace GUI { static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top); static void render_sub_texture(unsigned int tex_id, float left, float right, float bottom, float top, const Quad_UVs& uvs); - + static void shutdown(); private: bool load_from_png(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy); bool load_from_svg(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px); + static GLModel& init_model_for_render_image(); + static GLModel& get_model_for_render_image(); friend class Compressor; }; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 4bba176c0..d8eb50d1f 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2727,6 +2727,14 @@ bool GUI_App::on_init_inner() app_config->set("version", SLIC3R_VERSION); app_config->save(); + const auto& p_ogl_manager = get_opengl_manager(); + if (p_ogl_manager) { + const auto& msaa_type = app_config->get("msaa_type"); + p_ogl_manager->set_msaa_type(msaa_type); + const bool is_fxaa_enabled = app_config->get_bool("enable_advanced_antialiasing"); + p_ogl_manager->set_fxaa_enabled(is_fxaa_enabled); + } + BBLSplashScreen * scrn = nullptr; const bool show_splash_screen = true; if (show_splash_screen) { @@ -5616,6 +5624,24 @@ bool GUI_App::is_glsl_version_greater_or_equal_to(unsigned int major, unsigned i return OpenGLManager::get_gl_info().is_glsl_version_greater_or_equal_to(major, minor); } +void GUI_App::bind_shader(const std::shared_ptr& p_shader) +{ + const auto& p_ogl_manager = get_opengl_manager(); + if (!p_ogl_manager) { + return; + } + p_ogl_manager->bind_shader(p_shader); +} + +void GUI_App::unbind_shader() +{ + const auto& p_ogl_manager = get_opengl_manager(); + if (!p_ogl_manager) { + return; + } + p_ogl_manager->unbind_shader(); +} + int GUI_App::GetSingleChoiceIndex(const wxString& message, const wxString& caption, const wxArrayString& choices, @@ -7076,7 +7102,7 @@ const std::shared_ptr& GUI_App::get_opengl_manager() const return s_empty; } -GLShaderProgram* GUI_App::get_shader(const std::string &shader_name) const +const std::shared_ptr& GUI_App::get_shader(const std::string &shader_name) const { const auto& p_ogl_manager = get_opengl_manager(); if (p_ogl_manager) { @@ -7086,7 +7112,7 @@ GLShaderProgram* GUI_App::get_shader(const std::string &shader_name) const return nullptr; } -GLShaderProgram* GUI_App::get_current_shader() const +const std::shared_ptr GUI_App::get_current_shader() const { const auto& p_ogl_manager = get_opengl_manager(); if (p_ogl_manager) { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index e35d703f7..5c842ddde 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -637,8 +637,10 @@ public: #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG const std::shared_ptr& get_opengl_manager() const; - GLShaderProgram* get_shader(const std::string &shader_name) const; - GLShaderProgram* get_current_shader() const; + const std::shared_ptr& get_shader(const std::string &shader_name) const; + const std::shared_ptr get_current_shader() const; + void bind_shader(const std::shared_ptr& p_shader); + void unbind_shader(); bool is_gl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const; bool is_glsl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 5cefccf55..a63c44947 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -38,9 +38,30 @@ namespace Slic3r { namespace GUI { -View3D::View3D(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) - : m_canvas_widget(nullptr) +BaseView::BaseView() + : wxPanel() + , m_canvas_widget(nullptr) , m_canvas(nullptr) +{ +} + +BaseView::~BaseView() +{ +} + +bool BaseView::Show(bool show) +{ + const bool rt = wxPanel::Show(show); + if (show && rt) { + if (m_canvas) { + m_canvas->mark_context_dirty(); + } + } + return rt; +} + +View3D::View3D(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) + : BaseView() { init(parent, bed, model, config, process); } @@ -60,7 +81,8 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig if (!p_ogl_manager) { return false; } - m_canvas_widget = OpenGLManager::create_wxglcanvas(*this); + const GUI::EMSAAType msaa_type = p_ogl_manager->is_fxaa_enabled() ? GUI::EMSAAType::Disabled : p_ogl_manager->get_msaa_type(); + m_canvas_widget = OpenGLManager::create_wxglcanvas(*this, msaa_type); if (m_canvas_widget == nullptr) return false; @@ -224,7 +246,8 @@ void View3D::render() Preview::Preview( wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodeProcessorResult* gcode_result, std::function schedule_background_process_func) - : m_config(config) + : BaseView() + , m_config(config) , m_process(process) , m_gcode_result(gcode_result) , m_schedule_background_process(schedule_background_process_func) @@ -256,8 +279,9 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model) if (!p_ogl_manager) { return false; } - - m_canvas_widget = OpenGLManager::create_wxglcanvas(*this); + const auto& ogl_manager = wxGetApp().get_opengl_manager(); + const GUI::EMSAAType msaa_type = p_ogl_manager->is_fxaa_enabled() ? GUI::EMSAAType::Disabled : p_ogl_manager->get_msaa_type(); + m_canvas_widget = OpenGLManager::create_wxglcanvas(*this, msaa_type); if (m_canvas_widget == nullptr) return false; @@ -784,8 +808,7 @@ void Preview::load_print_as_fff(bool keep_z_range, bool only_gcode) } AssembleView::AssembleView(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) - : m_canvas_widget(nullptr) - , m_canvas(nullptr) + : BaseView() { init(parent, bed, model, config, process); } @@ -805,8 +828,8 @@ bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrint if (!p_ogl_manager) { return false; } - - m_canvas_widget = OpenGLManager::create_wxglcanvas(*this); + const GUI::EMSAAType msaa_type = p_ogl_manager->is_fxaa_enabled() ? GUI::EMSAAType::Disabled : p_ogl_manager->get_msaa_type(); + m_canvas_widget = OpenGLManager::create_wxglcanvas(*this, msaa_type); if (m_canvas_widget == nullptr) return false; @@ -879,6 +902,5 @@ void AssembleView::select_view(const std::string& direction) m_canvas->select_view(direction); } - } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 7d6a332bc..1aacf6e83 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -38,18 +38,25 @@ class Plater; class BitmapComboBox; #endif -class View3D : public wxPanel +class BaseView : public wxPanel { +public: + explicit BaseView(); + virtual ~BaseView(); + wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; } + GLCanvas3D* get_canvas3d() { return m_canvas; } + bool Show(bool show); +protected: wxGLCanvas* m_canvas_widget; GLCanvas3D* m_canvas; +}; +class View3D : public BaseView +{ public: View3D(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process); virtual ~View3D(); - wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; } - GLCanvas3D* get_canvas3d() { return m_canvas; } - void set_as_dirty(); void bed_shape_changed(); void plates_count_changed(); @@ -83,10 +90,8 @@ private: bool init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process); }; -class Preview : public wxPanel +class Preview : public BaseView { - wxGLCanvas* m_canvas_widget { nullptr }; - GLCanvas3D* m_canvas { nullptr }; DynamicPrintConfig* m_config; BackgroundSlicingProcess* m_process; GCodeProcessorResult* m_gcode_result; @@ -127,16 +132,13 @@ public: Legend }; - Preview(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, + Preview(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, GCodeProcessorResult* gcode_result, std::function schedule_background_process = []() {}); virtual ~Preview(); //BBS: update gcode_result void update_gcode_result(GCodeProcessorResult* gcode_result); - wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; } - GLCanvas3D* get_canvas3d() { return m_canvas; } - void set_as_dirty(); void bed_shape_changed(); @@ -175,7 +177,7 @@ private: void check_layers_slider_values(std::vector& ticks_from_model, const std::vector& layers_z); - void update_layers_slider(const std::vector& layers_z, bool keep_z_range = false); + void update_layers_slider(const std::vector& layers_z, bool keep_z_range = false); void update_layers_slider_mode(); void update_layers_slider_from_canvas(wxKeyEvent &event); //BBS: add only gcode mode @@ -183,17 +185,12 @@ private: }; -class AssembleView : public wxPanel +class AssembleView : public BaseView { - wxGLCanvas* m_canvas_widget{ nullptr }; - GLCanvas3D* m_canvas{ nullptr }; public: AssembleView(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process); ~AssembleView(); - wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; } - GLCanvas3D* get_canvas3d() { return m_canvas; } - void set_as_dirty(); void render(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp index 9e5576bcc..785f6d7ea 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.cpp @@ -16,6 +16,7 @@ #include "slic3r/GUI/Plater.hpp" #include "libslic3r/AppConfig.hpp" #include "../GUI/MsgDialog.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include #include "FixModelByWin10.hpp" @@ -776,13 +777,16 @@ void GLGizmoAdvancedCut::on_render() void GLGizmoAdvancedCut::on_render_for_picking() { + const Camera& camera = wxGetApp().plater()->get_picking_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); if (!m_connectors_editing) { glsafe(::glDisable(GL_DEPTH_TEST)); std::array color; // pick plane { color = picking_color_component(2); - render_glmodel(m_plane, color, Geometry::translation_transform(m_plane_center) * m_rotate_matrix, true); + render_glmodel(m_plane, color, view_matrix * Geometry::translation_transform(m_plane_center) * m_rotate_matrix, projection_matrix, true); } // pick Rotate GLGizmoRotate3D::on_render_for_picking(); @@ -790,6 +794,8 @@ void GLGizmoAdvancedCut::on_render_for_picking() BoundingBoxf3 box = m_parent.get_selection().get_bounding_box(); // pick grabber { + const auto& flat_shader = wxGetApp().get_shader("flat"); + wxGetApp().bind_shader(flat_shader); color = picking_color_component(0); m_move_z_grabber.color[0] = color[0]; m_move_z_grabber.color[1] = color[1]; @@ -804,6 +810,7 @@ void GLGizmoAdvancedCut::on_render_for_picking() m_move_x_grabber.color[3] = color[3]; m_move_x_grabber.render_for_picking(); } + wxGetApp().unbind_shader(); } } else { @@ -831,10 +838,10 @@ void GLGizmoAdvancedCut::on_render_for_picking() Transform3d scale_tf = Transform3d::Identity(); scale_tf.scale(Vec3f(connector.radius, connector.radius, height).cast()); - const Transform3d view_model_matrix = translate_tf * m_rotate_matrix * scale_tf; + const Transform3d view_model_matrix = view_matrix * translate_tf * m_rotate_matrix * scale_tf; std::array color = picking_color_component(i + c_connectors_start_id); - render_glmodel(m_shapes[connectors[i].attribs], color, view_model_matrix, true); + render_glmodel(m_shapes[connectors[i].attribs], color, view_model_matrix, projection_matrix, true); } } } @@ -1233,35 +1240,17 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers() if (m_cut_mode == CutMode::cutTongueAndGroove) { cp_clr.a(cp_clr.a() - 0.1f); } - - const float fullsize = get_fixed_grabber_size(); const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d screen_scalling_matrix{ Transform3d::Identity() }; const auto& t_zoom = camera.get_zoom(); screen_scalling_matrix.data()[0 * 4 + 0] = 1.0f / t_zoom; screen_scalling_matrix.data()[1 * 4 + 1] = 1.0f / t_zoom; screen_scalling_matrix.data()[2 * 4 + 2] = 1.0f / t_zoom; - auto calculate_model_matrix = [&screen_scalling_matrix](const Vec3d& source, const Vec3d& target, Transform3d& model_matrix, float fullsize)->void { - Vec3d the_vector = target - source; - const auto scale = fullsize * the_vector.stableNorm(); - const Vec3d center = source + screen_scalling_matrix.matrix().block<3, 3>(0, 0) * 0.5f * scale * the_vector.normalized(); - Vec3d rotation_axis; - double rotation_angle; - Matrix3d rotation_matrix; - Geometry::rotation_from_two_vectors(Vec3d(1.0f, 0.0f, 0.0f), the_vector, rotation_axis, rotation_angle, &rotation_matrix); - Matrix4d final_rotation_matrix{ Matrix4d::Identity() }; - for (int iColumn = 0; iColumn < 3; ++iColumn) { - for (int jRow = 0; jRow < 3; ++jRow) { - final_rotation_matrix.data()[4 * iColumn + jRow] = rotation_matrix.data()[3 * iColumn + jRow]; - } - } - model_matrix = Geometry::translation_transform(center.cast()).matrix() - * final_rotation_matrix - * Geometry::scale_transform({ scale, scale, scale }).matrix(); - }; - - render_glmodel(m_plane, cp_clr.get_data(), Geometry::translation_transform(m_plane_center) * m_rotate_matrix); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); + render_glmodel(m_plane, cp_clr.get_data(), view_matrix * Geometry::translation_transform(m_plane_center) * m_rotate_matrix, projection_matrix); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_CULL_FACE)); @@ -1272,41 +1261,93 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers() bool is_render_z_grabber = true; // m_hover_id < 0 || m_hover_id == cube_z_move_id; bool is_render_x_grabber = m_cut_mode == CutMode::cutTongueAndGroove; // m_hover_id < 0 || m_hover_id == cube_x_move_id; glsafe(::glDisable(GL_DEPTH_TEST)); - if (is_render_z_grabber) { - Transform3d model_matrix{ Transform3d::Identity() }; - calculate_model_matrix(m_plane_center, m_move_z_grabber.center, model_matrix, 0.3 * fullsize); - model_matrix = model_matrix * screen_scalling_matrix; - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(model_matrix.data())); - glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f)); - glsafe(::glColor3f(1.0, 1.0, 0.0)); - glsafe(::glLineStipple(1, 0x0FFF)); - glsafe(::glEnable(GL_LINE_STIPPLE)); - glsafe(::glBegin(GL_LINES)); - glsafe(::glVertex3f(-0.5f, 0.0f, 0.0f)); - glsafe(::glVertex3f(0.5f, 0.0f, 0.0f)); - glsafe(::glEnd()); - glsafe(::glDisable(GL_LINE_STIPPLE)); - glsafe(::glPopMatrix()); + if (!m_grabber_model.is_initialized()) { + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(2); + init_data.reserve_indices(2); + + // vertices + init_data.add_vertex(Vec3f(-0.5f, 0.0f, 0.0f)); + init_data.add_vertex(Vec3f(0.5f, 0.0f, 0.0f)); + + // indices + init_data.add_line(0, 1); + + m_grabber_model.init_from(std::move(init_data)); } - m_move_x_grabber.center = m_plane_center + m_plane_x_direction * Offset; - if (is_render_x_grabber) { - Transform3d model_matrix{ Transform3d::Identity() }; - calculate_model_matrix(m_plane_center, m_move_x_grabber.center, model_matrix, 0.3 * fullsize); - model_matrix = model_matrix * screen_scalling_matrix; - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(model_matrix.data())); - glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f)); - glsafe(::glColor3f(1.0, 1.0, 0.0)); - glsafe(::glLineStipple(1, 0x0FFF)); - glsafe(::glEnable(GL_LINE_STIPPLE)); - glsafe(::glBegin(GL_LINES)); - glsafe(::glVertex3f(-0.5f, 0.0f, 0.0f)); - glsafe(::glVertex3f(0.5f, 0.0f, 0.0f)); - glsafe(::glEnd()); - glsafe(::glDisable(GL_LINE_STIPPLE)); - glsafe(::glPopMatrix()); + m_grabber_model.set_color({ 1.0f, 1.0f, 0.0f, 1.0f }); + + auto calculate_model_matrix = [&screen_scalling_matrix](const Vec3d& source, const Vec3d& target, Transform3d& model_matrix, float fullsize)->void { + Vec3d the_vector = target - source; + const auto scale = fullsize * the_vector.stableNorm(); + const Vec3d center = source + screen_scalling_matrix.matrix().block<3, 3>(0, 0) * 0.5f * scale * the_vector.normalized(); + + Vec3d rotation_axis; + double rotation_angle; + Matrix3d rotation_matrix; + Geometry::rotation_from_two_vectors(Vec3d(1.0f, 0.0f, 0.0f), the_vector, rotation_axis, rotation_angle, &rotation_matrix); + Matrix4d final_rotation_matrix{ Matrix4d::Identity() }; + for (int iColumn = 0; iColumn < 3; ++iColumn) { + for (int jRow = 0; jRow < 3; ++jRow) { + final_rotation_matrix.data()[4 * iColumn + jRow] = rotation_matrix.data()[3 * iColumn + jRow]; + } + } + + model_matrix = Geometry::translation_transform(center.cast()).matrix() + * final_rotation_matrix + * Geometry::scale_transform({ scale, scale, scale }).matrix(); + }; + + const float fullsize = get_fixed_grabber_size(); + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (p_flat_shader && (is_render_z_grabber || is_render_x_grabber)) { + wxGetApp().bind_shader(p_flat_shader); + + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + + p_flat_shader->set_uniform("projection_matrix", proj_matrix); + + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(m_hover_id != -1 ? 2.0f : 1.5f); + + // to do: remove deprecated api: glLineStipple +#ifdef __APPLE__ + const auto& gl_info = p_ogl_manager->get_gl_info(); + const auto formated_gl_version = gl_info.get_formated_gl_version(); + if (formated_gl_version < 30) +#endif + { + glLineStipple(1, 0x0FFF); + glEnable(GL_LINE_STIPPLE); + } + + if (is_render_z_grabber) { + + Transform3d model_matrix{ Transform3d::Identity() }; + calculate_model_matrix(m_plane_center, m_move_z_grabber.center, model_matrix, 0.3 * fullsize); + model_matrix = model_matrix * screen_scalling_matrix; + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + m_grabber_model.render_geometry(); + } + + m_move_x_grabber.center = m_plane_center + m_plane_x_direction * Offset; + if (is_render_x_grabber) { + + Transform3d model_matrix{ Transform3d::Identity() }; + calculate_model_matrix(m_plane_center, m_move_x_grabber.center, model_matrix, 0.3 * fullsize); + model_matrix = model_matrix * screen_scalling_matrix; + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + m_grabber_model.render_geometry(); + } +#ifdef __APPLE__ + if (formated_gl_version < 30) +#endif + { + glDisable(GL_LINE_STIPPLE); + } } bool hover = (m_hover_id == get_group_id()); @@ -1318,16 +1359,15 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers() // BBS set to fixed size grabber // float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size)); - GLModel &cube_z = m_move_z_grabber.get_cube(); - GLModel &cube_x = m_move_x_grabber.get_cube(); + if (is_render_z_grabber) { Vec3d t_z_dir = m_move_z_grabber.center - m_plane_center; const auto scale_z = screen_scalling_matrix.matrix().block<3, 3>(0, 0) * 0.3 * fullsize * t_z_dir.stableNorm(); const Vec3d target_z = m_plane_center + scale_z * t_z_dir.normalized(); Transform3d cube_mat_z = Geometry::translation_transform(target_z) * m_rotate_matrix * Geometry::scale_transform(fullsize); // m_move_z_grabber.m_matrix = cube_mat_z * screen_scalling_matrix; - render_glmodel(cube_z, render_color, m_move_z_grabber.m_matrix); + render_glmodel(cube_z, render_color, view_matrix * m_move_z_grabber.m_matrix, projection_matrix); } if (is_render_x_grabber) { @@ -1337,7 +1377,7 @@ void GLGizmoAdvancedCut::render_cut_plane_and_grabbers() const Vec3d target_x = m_plane_center + scale_x * t_x_dir.normalized(); Transform3d cube_mat_x = Geometry::translation_transform(target_x) * m_rotate_matrix * Geometry::scale_transform(fullsize); // m_move_x_grabber.m_matrix = cube_mat_x * screen_scalling_matrix; - render_glmodel(cube_x, render_color, m_move_x_grabber.m_matrix); + render_glmodel(cube_x, render_color, view_matrix * m_move_x_grabber.m_matrix, projection_matrix); } // Should be placed at last, because GLGizmoRotate3D clears depth buffer GLGizmoRotate3D::set_center(m_plane_center); @@ -1382,6 +1422,11 @@ void GLGizmoAdvancedCut::render_connectors() ColorRGBA render_color = CONNECTOR_DEF_COLOR; const bool looking_forward = is_looking_forward(); + + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); + for (size_t i = 0; i < connectors.size(); ++i) { const CutConnector &connector = connectors[i]; @@ -1412,9 +1457,9 @@ void GLGizmoAdvancedCut::render_connectors() Transform3d scale_tf = Transform3d::Identity(); scale_tf.scale(Vec3f(connector.radius, connector.radius, height).cast()); - const Transform3d view_model_matrix = translate_tf * m_rotate_matrix * scale_tf; + const Transform3d view_model_matrix = view_matrix * translate_tf * m_rotate_matrix * scale_tf; - render_glmodel(m_shapes[connector.attribs], render_color.get_data(), view_model_matrix); + render_glmodel(m_shapes[connector.attribs], render_color.get_data(), view_model_matrix, projection_matrix); } } @@ -1441,16 +1486,77 @@ void GLGizmoAdvancedCut::render_cut_line() { if (!cut_line_processing() || m_cut_line_end.isApprox(Vec3d::Zero())) return; + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) { + return; + } + + if (!m_cut_line_model.is_initialized()) { + GLModel::Geometry geo; + geo.format.type = GLModel::PrimitiveType::Lines; + geo.format.vertex_layout = GLModel::Geometry::EVertexLayout::P3; + + geo.add_vertex(Vec3f{ -0.5f, 0.0f, 0.0f }); + geo.add_vertex(Vec3f{ 0.5f, 0.0f, 0.0f }); + + geo.add_line(0, 1); + + m_cut_line_model.init_from(std::move(geo)); + } + + Transform3d model_matrix{ Transform3d::Identity() }; + Vec3d the_vector = m_cut_line_end - m_cut_line_begin; + const auto scale = the_vector.stableNorm(); + Vec3d center = (m_cut_line_end + m_cut_line_begin) * 0.5f; + + Vec3d rotation_axis; + double rotation_angle; + Matrix3d rotation_matrix; + Geometry::rotation_from_two_vectors(Vec3d(1.0f, 0.0f, 0.0f), the_vector, rotation_axis, rotation_angle, &rotation_matrix); + Matrix4d final_rotation_matrix{ Matrix4d::Identity() }; + for (int iColumn = 0; iColumn < 3; ++iColumn) { + for (int jRow = 0; jRow < 3; ++jRow) { + final_rotation_matrix.data()[4 * iColumn + jRow] = rotation_matrix.data()[3 * iColumn + jRow]; + } + } + + model_matrix = Geometry::translation_transform(center.cast()).matrix() + * final_rotation_matrix + * Geometry::scale_transform({ scale, scale, scale }).matrix(); + + m_cut_line_model.set_color({ 0.0f, 1.0f, 0.0f, 1.0f}); + +#ifdef __APPLE__ + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + const auto& gl_info = p_ogl_manager->get_gl_info(); + const auto formated_gl_version = gl_info.get_formated_gl_version(); + if (formated_gl_version < 30) +#endif + { + glsafe(::glEnable(GL_LINE_STIPPLE)); + } glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - glsafe(::glColor3f(0.0, 1.0, 0.0)); - glEnable(GL_LINE_STIPPLE); - ::glBegin(GL_LINES); - ::glVertex3dv(m_cut_line_begin.data()); - ::glVertex3dv(m_cut_line_end.data()); - glsafe(::glEnd()); - glDisable(GL_LINE_STIPPLE); + + wxGetApp().bind_shader(p_flat_shader); + + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + + m_cut_line_model.render_geometry(); + + wxGetApp().unbind_shader(); + +#ifdef __APPLE__ + if (formated_gl_version < 30) +#endif + { + glsafe(::glDisable(GL_LINE_STIPPLE)); + } } void GLGizmoAdvancedCut::clear_selection() @@ -1838,7 +1944,11 @@ void GLGizmoAdvancedCut::toggle_model_objects_visibility(bool show_in_3d) { const Selection & selection = m_parent.get_selection(); const ModelObjectPtrs &model_objects = selection.get_model()->objects; - m_parent.toggle_model_objects_visibility(true, model_objects[selection.get_object_idx()], selection.get_instance_idx()); + const int idx = selection.get_object_idx(); + if (idx < 0) { + return; + } + m_parent.toggle_model_objects_visibility(true, model_objects[idx], selection.get_instance_idx()); } } @@ -2820,8 +2930,9 @@ void PartSelection::part_render(const Vec3d *cut_center, const Vec3d *normal) if (!valid()) return; - const Camera &camera = wxGetApp().plater()->get_camera(); - + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); glEnable(GL_DEPTH_TEST); for (size_t id = 0; id < m_cut_parts.size(); ++id) { // m_parts.size() test bool is_looking_forward = true; @@ -2843,7 +2954,7 @@ void PartSelection::part_render(const Vec3d *cut_center, const Vec3d *normal) GLGizmoBase::render_glmodel(m_cut_parts[id].glmodel, m_cut_parts[id].is_modifier ? MODIFIER_COLOR.get_data() : (m_cut_parts[id].is_up_part ? UPPER_PART_COLOR.get_data() : LOWER_PART_COLOR.get_data()), - m_cut_parts[id].trans); + view_matrix * m_cut_parts[id].trans, projection_matrix); if (m_cut_parts[id].is_modifier) glsafe(::glDisable(GL_BLEND)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp index 9f9c4b8c6..e840f26df 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoAdvancedCut.hpp @@ -180,9 +180,13 @@ private: GLModel m_plane; // old name:PickingModel + GLModel m_grabber_model; + Vec3d m_cut_line_begin{Vec3d::Zero()}; Vec3d m_cut_line_end{Vec3d::Zero()}; + GLModel m_cut_line_model; + Transform3d m_rotate_matrix{Transform3d::Identity()}; Transform3d m_start_dragging_m{Transform3d::Identity()}; std::map m_shapes; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index e98cb8906..d517d360f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -5,6 +5,7 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_Colors.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" // TODO: Display tooltips quicker on Linux @@ -120,6 +121,10 @@ void GLGizmoBase::Grabber::set_model_matrix(const Transform3d& model_matrix) void GLGizmoBase::Grabber::render(const std::array& render_color, bool picking) const { + const auto& shader = wxGetApp().get_current_shader(); + if (shader == nullptr) + return; + if (! cube_initialized) { // This cannot be done in constructor, OpenGL is not yet // initialized at that point (on Linux at least). @@ -131,14 +136,19 @@ void GLGizmoBase::Grabber::render(const std::array& render_color, bool //BBS set to fixed size grabber //float fullsize = 2 * (dragging ? get_dragging_half_size(size) : get_half_size(size)); - float fullsize = get_grabber_size(); + //float fullsize = get_grabber_size(); const_cast(&cube)->set_color(-1, render_color); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(m_matrix.data())); - cube.render(); - glsafe(::glPopMatrix()); + const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); + const Transform3d view_model_matrix = camera.get_view_matrix() * m_matrix; + const Transform3d& projection_matrix = camera.get_projection_matrix(); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", projection_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + + cube.render_geometry(); } @@ -216,40 +226,55 @@ bool GLGizmoBase::render_combo(const std::string &label, const std::vectorget_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + + const auto view_model_matrix = view_matrix * matrix; glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glLineWidth(2.0f)); - ::glBegin(GL_LINES); - // draw line for x axis - ::glColor3f(1.0f, 0.0f, 0.0f); - if (!is_single) { - ::glVertex3f(target(0) - half_length, target(1), target(2)); - } - else { - ::glVertex3f(target(0), target(1), target(2)); - } - ::glVertex3f(target(0) + half_length, target(1), target(2)); - // draw line for y axis - ::glColor3f(0.0f, 1.0f, 0.0f); - if (!is_single) { - ::glVertex3f(target(0), target(1) - half_length, target(2)); - } else { - ::glVertex3f(target(0), target(1), target(2)); - } - ::glVertex3f(target(0), target(1) + half_length, target(2)); - // draw line for z axis - ::glColor3f(0.0f, 0.0f, 1.0f); - if (!is_single) { - ::glVertex3f(target(0), target(1), target(2) - half_length); - } else { - ::glVertex3f(target(0), target(1), target(2)); - } - ::glVertex3f(target(0), target(1), target(2) + half_length); - glsafe(::glEnd()); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(2.0f); + + Transform3d model_matrix{ Transform3d::Identity() }; + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::X, target, is_single); + p_flat_shader->set_uniform("view_model_matrix", view_model_matrix * model_matrix); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); + m_cross_mark.set_color({ 1.0f, 0.0f, 0.0f, 1.0f }); + m_cross_mark.render_geometry(); + + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Y, target, is_single); + p_flat_shader->set_uniform("view_model_matrix", view_model_matrix * model_matrix); + m_cross_mark.set_color({ 0.0f, 1.0f, 0.0f, 1.0f }); + m_cross_mark.render_geometry(); + + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Z, target, is_single); + p_flat_shader->set_uniform("view_model_matrix", view_model_matrix * model_matrix); + m_cross_mark.set_color({ 0.0f, 0.0f, 1.0f, 1.0f }); + m_cross_mark.render_geometry(); + + wxGetApp().unbind_shader(); } float GLGizmoBase::get_grabber_size() @@ -263,7 +288,8 @@ float GLGizmoBase::get_grabber_size() float GLGizmoBase::get_fixed_grabber_size() { - return GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::Grabber::GrabberSizeFactor; + const float grabber_size = GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::Grabber::GrabberSizeFactor; + return grabber_size; } GLGizmoBase::GLGizmoBase(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id) @@ -453,20 +479,25 @@ void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const void GLGizmoBase::render_grabbers() const { - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("emission_factor", 0.1f); for (int i = 0; i < (int)m_grabbers.size(); ++i) { if (m_grabbers[i].enabled) m_grabbers[i].render(m_hover_id == i); } - shader->stop_using(); + wxGetApp().unbind_shader(); } void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { + const auto& shader = wxGetApp().get_shader("flat"); + if (!shader) { + return; + } + wxGetApp().bind_shader(shader); for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { if (m_grabbers[i].enabled) { std::array color = picking_color_component(i); @@ -474,6 +505,7 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const m_grabbers[i].render_for_picking(); } } + wxGetApp().unbind_shader(); } std::string GLGizmoBase::format(float value, unsigned int decimals) const @@ -567,34 +599,33 @@ BoundingBoxf3 GLGizmoBase::get_cross_mask_aabb(const Transform3d& matrix, const BoundingBoxf3 t_aabb; t_aabb.reset(); - BoundingBoxf3 t_cross_aabb; - t_cross_aabb.min = Vec3d(-0.5f, 0.0f, 0.0f); - t_cross_aabb.max = Vec3d(0.5f, 0.0f, 0.0f); - t_cross_aabb.defined = true; - Transform3d model_matrix{ Transform3d::Identity() }; - // x axis aabb - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::X, target, is_single); - auto t_x_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); - t_x_axis_aabb.defined = true; - t_aabb.merge(t_x_axis_aabb); - t_aabb.defined = true; - // end x axis aabb + if (m_cross_mark.is_initialized()) { + const auto& t_cross_aabb = m_cross_mark.get_bounding_box(); + Transform3d model_matrix{ Transform3d::Identity() }; + // x axis aabb + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::X, target, is_single); + auto t_x_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); + t_x_axis_aabb.defined = true; + t_aabb.merge(t_x_axis_aabb); + t_aabb.defined = true; + // end x axis aabb - // y axis aabb - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Y, target, is_single); - auto t_y_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); - t_y_axis_aabb.defined = true; - t_aabb.merge(t_y_axis_aabb); - t_aabb.defined = true; - // end y axis aabb + // y axis aabb + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Y, target, is_single); + auto t_y_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); + t_y_axis_aabb.defined = true; + t_aabb.merge(t_y_axis_aabb); + t_aabb.defined = true; + // end y axis aabb - // z axis aabb - model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Z, target, is_single); - auto t_z_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); - t_z_axis_aabb.defined = true; - t_aabb.merge(t_z_axis_aabb); - t_aabb.defined = true; - // end z axis aabb + // z axis aabb + model_matrix = get_corss_mask_model_matrix(ECrossMaskType::Z, target, is_single); + auto t_z_axis_aabb = t_cross_aabb.transformed(matrix * model_matrix); + t_z_axis_aabb.defined = true; + t_aabb.merge(t_z_axis_aabb); + t_aabb.defined = true; + // end z axis aabb + } return t_aabb; } @@ -648,25 +679,21 @@ BoundingBoxf3 GLGizmoBase::get_bounding_box() const return t_aabb; } -void GLGizmoBase::render_glmodel(GLModel &model, const std::array &color, Transform3d view_model_matrix, bool for_picking, float emission_factor) +void GLGizmoBase::render_glmodel(GLModel &model, const std::array &color, Transform3d view_model_matrix, const Transform3d& projection_matrix, bool for_picking, float emission_factor) { - glPushMatrix(); - GLShaderProgram *shader = nullptr; - if (for_picking) - shader = wxGetApp().get_shader("cali"); - else - shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader(for_picking ? "flat" : "gouraud_light"); if (shader) { - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("emission_factor", emission_factor); - glsafe(::glMultMatrixd(view_model_matrix.data())); + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", projection_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); model.set_color(-1, color); - model.render(); + model.render_geometry(); - shader->stop_using(); + wxGetApp().unbind_shader(); } - glPopMatrix(); } std::string GLGizmoBase::get_name(bool include_shortcut) const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index a95527989..024e26aa5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -71,7 +71,7 @@ public: static const float FixedRadiusSize; Vec3d center; - /*Vec3d angles;*/ + /* Vec3d angles;*/ std::array color; std::array hover_color; bool enabled; @@ -147,8 +147,9 @@ protected: mutable std::string m_tooltip; CommonGizmosDataPool* m_c{nullptr}; GLModel m_cone; - GLModel m_cylinder; + mutable GLModel m_cylinder; GLModel m_sphere; + GLModel m_cross_mark; bool m_is_dark_mode = false; @@ -174,7 +175,7 @@ protected: DoubleShowType show_type = DoubleShowType::Normal); bool render_combo(const std::string &label, const std::vector &lines, size_t &selection_idx, float label_width, float item_width); - void render_cross_mark(const Vec3f& target,bool is_single =false); + void render_cross_mark(const Transform3d& matrix, const Vec3f& target,bool is_single =false); static float get_grabber_size(); static float get_fixed_grabber_size(); @@ -244,8 +245,10 @@ public: /// virtual void data_changed(bool is_serializing){}; int get_count() { return ++count; } + virtual BoundingBoxf3 get_bounding_box() const; - static void render_glmodel(GLModel &model, const std::array &color, Transform3d view_model_matrix, bool for_picking = false, float emission_factor = 0.0f); + + static void render_glmodel(GLModel &model, const std::array &color, Transform3d view_model_matrix, const Transform3d& projection_matrix, bool for_picking = false, float emission_factor = 0.0f); protected: float last_input_window_width = 0; virtual bool on_init() = 0; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp index 7157e3af0..4554548ee 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBrimEars.cpp @@ -120,18 +120,24 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co if (!has_points) return; - GLShaderProgram *shader = picking ? nullptr : wxGetApp().get_shader("gouraud_light"); - if (shader != nullptr) shader->start_using(); + const auto& shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); + if (shader == nullptr) + return; + + wxGetApp().bind_shader(shader); ScopeGuard guard([shader]() { - if (shader != nullptr) shader->stop_using(); + wxGetApp().unbind_shader(); }); const GLVolume *vol = selection.get_volume(*selection.get_volume_idxs().begin()); const Transform3d &instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); const Transform3d &instance_matrix = vol->get_instance_transformation().get_matrix(); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(instance_matrix.data())); + const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); + const Transform3d& view_matrix = camera.get_view_matrix(); + const Transform3d& projection_matrix = camera.get_projection_matrix(); + + shader->set_uniform("projection_matrix", projection_matrix); ColorRGBA render_color; for (size_t i = 0; i < cache_size; ++i) { @@ -171,33 +177,34 @@ void GLGizmoBrimEars::render_points(const Selection &selection, bool picking) co if (shader && !picking) shader->set_uniform("emission_factor", 0.5f); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(brim_point.pos(0), brim_point.pos(1), brim_point.pos(2))); - glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data())); + const Transform3d brim_matrix = Geometry::assemble_transform(brim_point.pos.cast()) * instance_scaling_matrix_inverse; - if (vol->is_left_handed()) glFrontFace(GL_CW); + if (vol->is_left_handed()) + glFrontFace(GL_CW); // Matrices set, we can render the point mark now. // If in editing mode, we'll also render a cone pointing to the sphere. - if (editing_cache[i].normal == Vec3f::Zero()) m_c->raycaster()->raycaster()->get_closest_point(editing_cache[i].brim_point.pos, &editing_cache[i].normal); + if (editing_cache[i].normal == Vec3f::Zero()) + m_c->raycaster()->raycaster()->get_closest_point(editing_cache[i].brim_point.pos, &editing_cache[i].normal); + + double radius = (double)brim_point.head_front_radius * RenderPointScale; Eigen::Quaterniond q; q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * editing_cache[i].normal.cast()); Eigen::AngleAxisd aa(q); - glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2))); - glsafe(::glPushMatrix()); - double radius = (double) brim_point.head_front_radius * RenderPointScale; - glsafe(::glScaled(radius, radius, .2)); - m_cylinder.render(); - glsafe(::glPopMatrix()); + const Transform3d view_model_matrix = view_matrix * instance_matrix * brim_matrix * Transform3d(aa.toRotationMatrix()) * + Geometry::assemble_transform(Vec3d(0.0, 0.0, 0.0), + Vec3d(PI, 0.0, 0.0), Vec3d(radius, radius, .2)); - if (vol->is_left_handed()) glFrontFace(GL_CCW); + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); - glsafe(::glPopMatrix()); + m_cylinder.render_geometry(); + + if (vol->is_left_handed()) + glFrontFace(GL_CCW); } - - glsafe(::glPopMatrix()); } bool GLGizmoBrimEars::is_mesh_point_clipped(const Vec3d &point) const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index d5008725e..9200a427c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -128,16 +128,16 @@ void GLGizmoCut::on_render() ::glVertex3dv(m_grabbers[0].center.data()); glsafe(::glEnd()); - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader("gouraud_light"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("emission_factor", 0.1f); m_grabbers[0].color = GrabberColor; m_grabbers[0].render(m_hover_id == 0, (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0)); - shader->stop_using(); + wxGetApp().unbind_shader(); glsafe(::glPushMatrix()); glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z())); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp index b96be246a..09c8684ed 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.cpp @@ -32,9 +32,9 @@ std::string GLGizmoFaceDetector::on_get_name() const void GLGizmoFaceDetector::on_render() { - if (m_iva.has_VBOs()) { - ::glColor4f(0.f, 0.f, 1.f, 0.4f); - m_iva.render(); + if (m_model.is_initialized()) { + m_model.set_color({ 0.f, 0.f, 1.f, 0.4f }); + m_model.render_geometry(); } } @@ -72,7 +72,7 @@ void GLGizmoFaceDetector::on_render_input_window(float x, float y, float bottom_ void GLGizmoFaceDetector::on_set_state() { if (get_state() == On) { - m_iva.release_geometry(); + m_model.reset(); display_exterior_face(); } } @@ -94,8 +94,11 @@ void GLGizmoFaceDetector::perform_recognition(const Selection& selection) void GLGizmoFaceDetector::display_exterior_face() { int cnt = 0; - m_iva.release_geometry(); + m_model.reset(); + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; + init_data.index_type = GLModel::Geometry::EIndexType::UINT; const ModelObjectPtrs& objects = wxGetApp().model().objects; for (ModelObject* mo : objects) { const ModelInstance* mi = mo->instances[0]; @@ -110,19 +113,16 @@ void GLGizmoFaceDetector::display_exterior_face() continue; for (int i = 0; i < 3; ++i) { - m_iva.push_geometry(double(mv_its.vertices[facet_vert_idxs[i]](0)), - double(mv_its.vertices[facet_vert_idxs[i]](1)), - double(mv_its.vertices[facet_vert_idxs[i]](2)), - 0., 0., 1.); + init_data.add_vertex((Vec3f)mv_its.vertices[facet_vert_idxs[i]].cast(), Vec3f{ 0.0f, 0.0f, 1.0f }); } - m_iva.push_triangle(cnt, cnt + 1, cnt + 2); + init_data.add_triangle(cnt, cnt + 1, cnt + 2); cnt += 3; } } } - m_iva.finalize_geometry(true); + m_model.init_from(std::move(init_data)); } CommonGizmosDataID GLGizmoFaceDetector::on_get_requirements() const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp index 4d199ad5d..7906f307e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFaceDetector.hpp @@ -29,7 +29,7 @@ private: void perform_recognition(const Selection& selection); void display_exterior_face(); - GLIndexedVertexArray m_iva; + GUI::GLModel m_model; double m_sample_interval = {0.5}; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 80ae52903..abaf9cccd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -122,9 +122,11 @@ void GLGizmoFdmSupports::render_painter_gizmo() const //BBS: draw support volumes if (m_volume_ready && m_support_volume && (m_edit_state != state_generating)) { - //m_support_volume->set_render_color(); - ::glColor4f(0.f, 0.7f, 0.f, 0.7f); - m_support_volume->render(); + m_support_volume->set_render_color({ 0.f, 0.7f, 0.f, 0.7f }); + + const auto& camera = GUI::wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + m_support_volume->render(view_matrix); } m_c->object_clipper()->render_cut(); @@ -161,13 +163,13 @@ bool GLGizmoFdmSupports::on_key_down_select_tool_type(int keyCode) { void GLGizmoFdmSupports::render_triangles(const Selection& selection) const { ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); - auto* shader = wxGetApp().get_shader("mm_gouraud"); + const auto& shader = wxGetApp().get_shader("mm_gouraud"); if (!shader) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("clipping_plane", clp_data.clp_dataf); shader->set_uniform("z_range", clp_data.z_range); - ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); + ScopeGuard guard([shader]() { if (shader) wxGetApp().unbind_shader(); }); const ModelObject* mo = m_c->selection_info()->model_object(); int mesh_id = -1; @@ -183,8 +185,11 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const if (is_left_handed) glsafe(::glFrontFace(GL_CW)); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(trafo_matrix.data())); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d matrix = camera.get_view_matrix() * trafo_matrix; + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg)); Matrix3f normal_matrix = static_cast(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast()); @@ -194,9 +199,8 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const shader->set_uniform("slope.actived", m_parent.is_using_slope()); shader->set_uniform("slope.volume_world_normal_matrix", normal_matrix); shader->set_uniform("slope.normal_z", normal_z); - m_triangle_selectors[mesh_id]->render(m_imgui); + m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix); - glsafe(::glPopMatrix()); if (is_left_handed) glsafe(::glFrontFace(GL_CCW)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index d35b38bcf..8714f6f6c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -94,6 +94,11 @@ void GLGizmoFlatten::on_start_dragging() void GLGizmoFlatten::on_render() { + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) { + return; + } + const Selection& selection = m_parent.get_selection(); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); @@ -101,50 +106,62 @@ void GLGizmoFlatten::on_render() glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_BLEND)); + wxGetApp().bind_shader(p_flat_shader); if (selection.is_single_full_instance()) { const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z())); - glsafe(::glMultMatrixd(m.data())); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d view_model_matrix = camera.get_view_matrix() * + Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m; + + p_flat_shader->set_uniform("view_model_matrix", view_model_matrix); + p_flat_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); if (this->is_plane_update_necessary()) update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { - if (i == m_hover_id) - glsafe(::glColor4fv(GLGizmoBase::FLATTEN_HOVER_COLOR.data())); - else - glsafe(::glColor4fv(GLGizmoBase::FLATTEN_COLOR.data())); - - if (m_planes[i].vbo.has_VBOs()) - m_planes[i].vbo.render(); + p_flat_shader->set_uniform("uniform_color", i == m_hover_id ? GLGizmoBase::FLATTEN_HOVER_COLOR : GLGizmoBase::FLATTEN_COLOR); + m_planes[i].vbo.render(p_flat_shader); } - glsafe(::glPopMatrix()); } + wxGetApp().unbind_shader(); + glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glDisable(GL_BLEND)); } void GLGizmoFlatten::on_render_for_picking() { + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) { + return; + } + const Selection& selection = m_parent.get_selection(); glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_BLEND)); + wxGetApp().bind_shader(p_flat_shader); + if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) { const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z())); - glsafe(::glMultMatrixd(m.data())); + const Camera& camera = wxGetApp().plater()->get_picking_camera(); + const Transform3d view_model_matrix = camera.get_view_matrix() * + Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m; + + p_flat_shader->set_uniform("view_model_matrix", view_model_matrix); + p_flat_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); if (this->is_plane_update_necessary()) update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { - glsafe(::glColor4fv(picking_color_component(i).data())); - m_planes[i].vbo.render(); + p_flat_shader->set_uniform("uniform_color", picking_color_component(i)); + m_planes[i].vbo.render(p_flat_shader); } - glsafe(::glPopMatrix()); } + wxGetApp().unbind_shader(); + + glsafe(::glEnable(GL_CULL_FACE)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 39bc98d7f..aa4184826 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -101,84 +101,73 @@ void GLGizmoHollow::on_render_for_picking() void GLGizmoHollow::render_points(const Selection& selection, bool picking) const { - GLShaderProgram* shader = picking ? nullptr : wxGetApp().get_shader("gouraud_light"); - if (shader) - shader->start_using(); - ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); + const auto& shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light"); + if (!shader) + return; + + wxGetApp().bind_shader(shader); + ScopeGuard guard([shader]() { wxGetApp().unbind_shader(); }); const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); - const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); - const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); + const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); + const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix(); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift())); - glsafe(::glMultMatrixd(instance_matrix.data())); + const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); + const Transform3d& view_matrix = camera.get_view_matrix(); + const Transform3d& projection_matrix = camera.get_projection_matrix(); - std::array render_color; + shader->set_uniform("projection_matrix", projection_matrix); + + ColorRGBA render_color; const sla::DrainHoles& drain_holes = m_c->selection_info()->model_object()->sla_drain_holes; - size_t cache_size = drain_holes.size(); + const size_t cache_size = drain_holes.size(); for (size_t i = 0; i < cache_size; ++i) { const sla::DrainHole& drain_hole = drain_holes[i]; - const bool& point_selected = m_selected[i]; + const bool point_selected = m_selected[i]; if (is_mesh_point_clipped(drain_hole.pos.cast())) continue; // First decide about the color of the point. - if (picking) { - std::array color = picking_color_component(i); - render_color = color; - } + if (picking) + render_color = picking_color_component(i); else { - if (size_t(m_hover_id) == i) { - render_color = {0.f, 1.f, 1.f, 1.f}; - } + if (size_t(m_hover_id) == i) + render_color = ColorRGBA::CYAN(); else if (m_c->hollowed_mesh() && i < m_c->hollowed_mesh()->get_drainholes().size() && m_c->hollowed_mesh()->get_drainholes()[i].failed) { - render_color = {1.f, 0.f, 0.f, .5f}; - } - else { // neigher hover nor picking - - render_color[0] = point_selected ? 1.0f : 1.f; - render_color[1] = point_selected ? 0.3f : 1.f; - render_color[2] = point_selected ? 0.3f : 1.f; - render_color[3] = 0.5f; + render_color = { 1.0f, 0.0f, 0.0f, 0.5f }; } + else // neither hover nor picking + render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); } - const_cast(&m_vbo_cylinder)->set_color(-1, render_color); + m_cylinder.set_color(render_color); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2))); - glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data())); + const Transform3d hole_matrix = Geometry::assemble_transform(drain_hole.pos.cast()) * instance_scaling_matrix_inverse; if (vol->is_left_handed()) glFrontFace(GL_CW); // Matrices set, we can render the point mark now. Eigen::Quaterniond q; - q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); - Eigen::AngleAxisd aa(q); - glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2))); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(0., 0., -drain_hole.height)); - glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); - m_vbo_cylinder.render(); - glsafe(::glPopMatrix()); + q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); + const Eigen::AngleAxisd aa(q); + const Transform3d view_model_matrix = view_matrix * instance_matrix * hole_matrix * Transform3d(aa.toRotationMatrix()) * + Geometry::assemble_transform(-drain_hole.height * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_cylinder.render_geometry(); if (vol->is_left_handed()) glFrontFace(GL_CCW); - glsafe(::glPopMatrix()); } - - glsafe(::glPopMatrix()); } - - bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const { if (m_c->object_clipper()->get_position() == 0.) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 0e063ada4..23efa97d5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -3,6 +3,7 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include "slic3r/Utils/UndoRedo.hpp" #include "libslic3r/PresetBundle.hpp" @@ -563,6 +564,8 @@ void GLGizmoMeasure::on_render() update_if_needed(); const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); const float inv_zoom = (float)camera.get_inv_zoom(); bool mouse_on_gripper = false; bool mouse_on_object =false; @@ -692,10 +695,10 @@ void GLGizmoMeasure::on_render() reset_gripper_pick(GripperType::UNDEFINE, true); m_curr_feature = curr_feature; - m_curr_feature->volume = m_last_hit_volume; - m_curr_feature->world_tran = m_mesh_raycaster_map[m_last_hit_volume]->world_tran.get_matrix(); if (!m_curr_feature.has_value()) return; + m_curr_feature->volume = m_last_hit_volume; + m_curr_feature->world_tran = m_mesh_raycaster_map[m_last_hit_volume]->world_tran.get_matrix(); switch (m_curr_feature->get_type()) { default: { assert(false); break; } @@ -811,7 +814,7 @@ void GLGizmoMeasure::on_render() glsafe(::glEnable(GL_DEPTH_TEST)); glDisable(GL_BLEND); auto render_feature = - [this](const Measure::SurfaceFeature &feature, const std::vector &colors, + [this, view_matrix, projection_matrix](const Measure::SurfaceFeature &feature, const std::vector &colors, float inv_zoom, bool hover, bool update_raycasters_transform,int featura_index = -1) { switch (feature.get_type()) { @@ -820,7 +823,7 @@ void GLGizmoMeasure::on_render() { const Transform3d feature_matrix = Geometry::translation_transform(feature.get_point()) * Geometry::scale_transform(inv_zoom); Geometry::Transformation tran(feature_matrix); - render_glmodel(*m_sphere, colors.front().get_data(), tran.get_matrix(), false, hover ? 0.5f : 0.25f); + render_glmodel(*m_sphere, colors.front().get_data(), view_matrix * tran.get_matrix(), projection_matrix, false, hover ? 0.5f : 0.25f); if (update_raycasters_transform) { auto it = m_gripper_id_raycast_map.find(GripperType::POINT); if (it != m_gripper_id_raycast_map.end() && it->second != nullptr) @@ -837,20 +840,20 @@ void GLGizmoMeasure::on_render() Geometry::Transformation tran(circle_matrix); if (featura_index == -1) { init_circle_glmodel(GripperType::CIRCLE, feature, m_curr_circle, inv_zoom); - render_glmodel(*m_curr_circle.circle, colors.front().get_data(), tran.get_matrix(), false, hover ? 0.5f : 0.25f); + render_glmodel(*m_curr_circle.circle, colors.front().get_data(), view_matrix * tran.get_matrix(), projection_matrix, false, hover ? 0.5f : 0.25f); } // render plane feature1 or feature2 if (featura_index == 0) { // feature1 init_circle_glmodel(GripperType::CIRCLE_1, feature, m_feature_circle_first, inv_zoom); - render_glmodel(*m_feature_circle_first.circle, colors.front().get_data(), tran.get_matrix(), false, hover ? 0.5f : 0.25f); + render_glmodel(*m_feature_circle_first.circle, colors.front().get_data(), view_matrix * tran.get_matrix(), projection_matrix, false, hover ? 0.5f : 0.25f); } else if (featura_index == 1) { // feature2 init_circle_glmodel(GripperType::CIRCLE_2, feature, m_feature_circle_second, inv_zoom); - render_glmodel(*m_feature_circle_second.circle, colors.front().get_data(), tran.get_matrix(), false, hover ? 0.5f : 0.25f); + render_glmodel(*m_feature_circle_second.circle, colors.front().get_data(), view_matrix * tran.get_matrix(), projection_matrix, false, hover ? 0.5f : 0.25f); } // render center if (colors.size() > 1) { const Transform3d center_matrix = Geometry::translation_transform(center) * Geometry::scale_transform(inv_zoom); - render_glmodel(*m_sphere, colors.back().get_data(), center_matrix, false, hover ? 0.5f : 0.25f); + render_glmodel(*m_sphere, colors.back().get_data(), view_matrix * center_matrix, projection_matrix, false, hover ? 0.5f : 0.25f); Geometry::Transformation tran(center_matrix); auto it = m_gripper_id_raycast_map.find(GripperType::POINT); @@ -868,7 +871,7 @@ void GLGizmoMeasure::on_render() Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to - from).norm() }); Geometry::Transformation tran(edge_matrix); - render_glmodel(*m_cylinder, colors.front().get_data(), tran.get_matrix(), false, hover ? 0.5f : 0.25f); + render_glmodel(*m_cylinder, colors.front().get_data(), view_matrix * tran.get_matrix(), projection_matrix, false, hover ? 0.5f : 0.25f); if (update_raycasters_transform) { auto it = m_gripper_id_raycast_map.find(GripperType::EDGE); if (it != m_gripper_id_raycast_map.end() && it->second != nullptr){ @@ -881,7 +884,7 @@ void GLGizmoMeasure::on_render() if (extra.has_value()) { const Transform3d point_matrix = Geometry::translation_transform(*extra) * Geometry::scale_transform(inv_zoom); Geometry::Transformation tran(point_matrix); - render_glmodel(*m_sphere, colors.back().get_data(), tran.get_matrix(), false, hover ? 0.5f : 0.25f); + render_glmodel(*m_sphere, colors.back().get_data(), view_matrix * tran.get_matrix(), projection_matrix, false, hover ? 0.5f : 0.25f); auto it = m_gripper_id_raycast_map.find(GripperType::POINT); if (it != m_gripper_id_raycast_map.end() && it->second != nullptr) { @@ -893,16 +896,16 @@ void GLGizmoMeasure::on_render() } case Measure::SurfaceFeatureType::Plane: { if (featura_index == -1) { - render_glmodel(*m_curr_plane.plane, colors.back().get_data(), feature.world_tran, false, hover ? 0.5f : 0.25f); + render_glmodel(*m_curr_plane.plane, colors.back().get_data(), view_matrix * feature.world_tran, projection_matrix, false, hover ? 0.5f : 0.25f); break; } //render plane feature1 or feature2 if (featura_index == 0) {//feature1 init_plane_glmodel(GripperType::PLANE_1, feature, m_feature_plane_first); - render_glmodel(*m_feature_plane_first.plane, colors.back().get_data(), feature.world_tran, false, hover ? 0.5f : 0.25f); + render_glmodel(*m_feature_plane_first.plane, colors.back().get_data(), view_matrix * feature.world_tran, projection_matrix, false, hover ? 0.5f : 0.25f); } else if (featura_index == 1) {//feature2 init_plane_glmodel(GripperType::PLANE_2, feature, m_feature_plane_second); - render_glmodel(*m_feature_plane_second.plane, colors.back().get_data(), feature.world_tran, false, hover ? 0.5f : 0.25f); + render_glmodel(*m_feature_plane_second.plane, colors.back().get_data(), view_matrix * feature.world_tran, projection_matrix, false, hover ? 0.5f : 0.25f); } break; } @@ -1050,7 +1053,7 @@ void GLGizmoMeasure::on_render() const ColorRGBA color = hover_selection_color(); Geometry::Transformation tran(matrix); - render_glmodel(*m_sphere, color.get_data(), tran.get_matrix(), false, 0.5f); + render_glmodel(*m_sphere, color.get_data(), view_matrix * tran.get_matrix(), projection_matrix, false, 0.5f); } } render_dimensioning(); @@ -1116,7 +1119,7 @@ void GLGizmoMeasure::render_dimensioning() if (!m_selected_features.second.feature.has_value() && m_selected_features.first.feature->get_type() != Measure::SurfaceFeatureType::Circle) return; - GLShaderProgram* shader = wxGetApp().get_shader("flat"); + auto shader = wxGetApp().get_shader("flat"); if (shader == nullptr) return; @@ -1152,13 +1155,13 @@ void GLGizmoMeasure::render_dimensioning() #if ENABLE_GL_CORE_PROFILE if (OpenGLManager::get_gl_info().is_core_profile()) { - shader->stop_using(); + wxGetApp().unbind_shader(shader); shader = wxGetApp().get_shader("dashed_thick_lines"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("projection_matrix", Transform3d::Identity()); const std::array& viewport = camera.get_viewport(); shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); @@ -1167,40 +1170,41 @@ void GLGizmoMeasure::render_dimensioning() } else #endif // ENABLE_GL_CORE_PROFILE - glsafe(::glLineWidth(2.0f)); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(2.0f); // stem shader->set_uniform("view_model_matrix", overlap ? ss_to_ndc_matrix * Geometry::translation_transform(v1ss_3) * q12ss * Geometry::translation_transform(-2.0 * TRIANGLE_HEIGHT * Vec3d::UnitX()) * Geometry::scale_transform({ v12ss_len + 4.0 * TRIANGLE_HEIGHT, 1.0f, 1.0f }) : ss_to_ndc_matrix * Geometry::translation_transform(v1ss_3) * q12ss * Geometry::scale_transform({ v12ss_len, 1.0f, 1.0f })); m_dimensioning.line.set_color(-1, color); - m_dimensioning.line.render(); + m_dimensioning.line.render_geometry(); #if ENABLE_GL_CORE_PROFILE if (OpenGLManager::get_gl_info().is_core_profile()) { - shader->stop_using(); + wxGetApp().unbind_shader(shader); shader = wxGetApp().get_shader("flat"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); } else #endif // ENABLE_GL_CORE_PROFILE - glsafe(::glLineWidth(1.0f)); + p_ogl_manager->set_line_width(1.0f); // arrow 1 if (show_first_tri) { shader->set_uniform("view_model_matrix", overlap ? ss_to_ndc_matrix * Geometry::translation_transform(v1ss_3) * q12ss : ss_to_ndc_matrix * Geometry::translation_transform(v1ss_3) * q21ss); - m_dimensioning.triangle.render(); + m_dimensioning.triangle.render_geometry(); } // arrow 2 shader->set_uniform("view_model_matrix", overlap ? ss_to_ndc_matrix * Geometry::translation_transform(v2ss_3) * q21ss : ss_to_ndc_matrix * Geometry::translation_transform(v2ss_3) * q12ss); - m_dimensioning.triangle.render(); + m_dimensioning.triangle.render_geometry(); const bool use_inches = wxGetApp().app_config->get("use_inches") == "1"; const double curr_value = use_inches ? GizmoObjectManipulation::mm_to_in * distance : distance; @@ -1356,7 +1360,7 @@ void GLGizmoMeasure::render_dimensioning() shader->set_uniform("view_model_matrix", ss_to_ndc_matrix * Geometry::translation_transform({ pss.x(), pss.y(), 0.0 }) * q * Geometry::scale_transform({ pv_projss_len, 1.0f, 1.0f })); m_dimensioning.line.set_color(-1, ColorRGBA::LIGHT_GRAY().get_data()); - m_dimensioning.line.render(); + m_dimensioning.line.render_geometry(); } }; @@ -1409,13 +1413,13 @@ void GLGizmoMeasure::render_dimensioning() const Camera& camera = wxGetApp().plater()->get_camera(); #if ENABLE_GL_CORE_PROFILE if (OpenGLManager::get_gl_info().is_core_profile()) { - shader->stop_using(); + wxGetApp().unbind_shader(); shader = wxGetApp().get_shader("dashed_thick_lines"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("projection_matrix", Transform3d::Identity()); const std::array& viewport = camera.get_viewport(); shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); @@ -1424,26 +1428,27 @@ void GLGizmoMeasure::render_dimensioning() } else #endif // ENABLE_GL_CORE_PROFILE - glsafe(::glLineWidth(2.0f)); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(2.0f); // arc shader->set_uniform("projection_matrix", camera.get_projection_matrix()); shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::translation_transform(center)); - m_dimensioning.arc.render(); + m_dimensioning.arc.render_geometry(); #if ENABLE_GL_CORE_PROFILE if (OpenGLManager::get_gl_info().is_core_profile()) { - shader->stop_using(); + wxGetApp().unbind_shader(); shader = wxGetApp().get_shader("flat"); if (shader == nullptr) return; - shader->start_using(); + wxGetApp().bind_shader(shader); } else #endif // ENABLE_GL_CORE_PROFILE - glsafe(::glLineWidth(1.0f)); + p_ogl_manager->set_line_width(1.0f); // arrows auto render_arrow = [this, shader, &camera, &normal, ¢er, &e1_unit, draw_radius, step, resolution](unsigned int endpoint_id) { @@ -1455,7 +1460,7 @@ void GLGizmoMeasure::render_dimensioning() const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::translation_transform(position_model) * qx * qz * Geometry::scale_transform(camera.get_inv_zoom()); shader->set_uniform("view_model_matrix", view_model_matrix); - m_dimensioning.triangle.render(); + m_dimensioning.triangle.render_geometry(); }; glsafe(::glDisable(GL_CULL_FACE)); @@ -1473,7 +1478,7 @@ void GLGizmoMeasure::render_dimensioning() Eigen::Quaternion::FromTwoVectors(Vec3d::UnitX(), Measure::edge_direction(e1.first, e1.second)) * Geometry::scale_transform({ e11center_len, 1.0f, 1.0f })); m_dimensioning.line.set_color(-1, ColorRGBA::LIGHT_GRAY().get_data()); - m_dimensioning.line.render(); + m_dimensioning.line.render_geometry(); } // edge 2 extension @@ -1484,7 +1489,7 @@ void GLGizmoMeasure::render_dimensioning() Eigen::Quaternion::FromTwoVectors(Vec3d::UnitX(), Measure::edge_direction(e2.first, e2.second)) * Geometry::scale_transform({ (coplanar && radius > 0.0) ? e21center_len : draw_radius, 1.0f, 1.0f })); m_dimensioning.line.set_color(-1, ColorRGBA::LIGHT_GRAY().get_data()); - m_dimensioning.line.render(); + m_dimensioning.line.render_geometry(); } // label @@ -1550,7 +1555,7 @@ void GLGizmoMeasure::render_dimensioning() Measure::SurfaceFeature(Measure::SurfaceFeatureType::Edge, e2.first, e2.second), calc_radius); }; - shader->start_using(); + wxGetApp().bind_shader(shader); if (!m_dimensioning.line.is_initialized()) { GLModel::Geometry init_data; @@ -1650,7 +1655,7 @@ void GLGizmoMeasure::render_dimensioning() glsafe(::glEnable(GL_DEPTH_TEST)); - shader->stop_using(); + wxGetApp().unbind_shader(); } static void add_row_to_table(std::function col_1 = nullptr, std::function col_2 = nullptr) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 12d46f253..c4143194e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -194,12 +194,12 @@ void GLGizmoMmuSegmentation::render_non_manifold_edges() const { const Camera & camera = wxGetApp().plater()->get_camera(); auto view_mat = camera.get_view_matrix(); auto proj_mat = camera.get_projection_matrix(); - GLShaderProgram *shader = wxGetApp().get_shader("flat"); - shader->start_using(); + const auto& shader = wxGetApp().get_shader("flat"); + wxGetApp().bind_shader(shader); shader->set_uniform("view_model_matrix", view_mat); shader->set_uniform("projection_matrix", proj_mat); m_non_manifold_edges_model.render_geometry(); - shader->stop_using(); + wxGetApp().unbind_shader(); } } } @@ -233,14 +233,14 @@ void GLGizmoMmuSegmentation::set_painter_gizmo_data(const Selection &selection) void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const { ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); - auto *shader = wxGetApp().get_shader("mm_gouraud"); + const auto& shader = wxGetApp().get_shader("mm_gouraud"); if (!shader) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("clipping_plane", clp_data.clp_dataf); shader->set_uniform("z_range", clp_data.z_range); shader->set_uniform("slope.actived", m_parent.is_using_slope()); - ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); + ScopeGuard guard([shader]() { if (shader) wxGetApp().unbind_shader(); }); //BBS: to improve the random white pixel issue glsafe(::glDisable(GL_CULL_FACE)); @@ -266,14 +266,16 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const if (is_left_handed) glsafe(::glFrontFace(GL_CW)); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(trafo_matrix.data())); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d matrix = camera.get_view_matrix() * trafo_matrix; + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); shader->set_uniform("volume_world_matrix", trafo_matrix); shader->set_uniform("volume_mirrored", is_left_handed); - m_triangle_selectors[mesh_id]->render(m_imgui); + m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix); - glsafe(::glPopMatrix()); if (is_left_handed) glsafe(::glFrontFace(GL_CCW)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 335153408..0f4adb408 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -4,6 +4,7 @@ #include "slic3r/GUI/GUI_App.hpp" //BBS: GUI refactor #include "slic3r/GUI/Plater.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include "libslic3r/AppConfig.hpp" @@ -205,7 +206,6 @@ void GLGizmoMove3D::on_render() m_orient_matrix = m_orient_matrix * screen_scalling_matrix; float space_size = 100.f; - space_size *= GLGizmoBase::Grabber::GrabberSizeFactor; #if ENABLE_FIXED_GRABBER // x axis @@ -233,9 +233,10 @@ void GLGizmoMove3D::on_render() m_grabbers[2].color = AXES_COLOR[2]; #endif - glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(Geometry::Transformation(m_orient_matrix).get_matrix().data())); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width((m_hover_id != -1) ? 2.0f : 1.5f); + const auto& gl_info = p_ogl_manager->get_gl_info(); + const auto formated_gl_version = gl_info.get_formated_gl_version(); // draw grabbers for (unsigned int i = 0; i < 3; ++i) { if (m_grabbers[i].enabled) render_grabber_extension((Axis) i, box, false); @@ -243,23 +244,58 @@ void GLGizmoMove3D::on_render() // draw axes line // draw axes - for (unsigned int i = 0; i < 3; ++i) { - if (m_grabbers[i].enabled) { - glsafe(::glColor4fv(AXES_COLOR[i].data())); - glLineStipple(1, 0x0FFF); - glEnable(GL_LINE_STIPPLE); - ::glBegin(GL_LINES); - ::glVertex3dv(origin.data()); - // use extension center - ::glVertex3dv(m_grabbers[i].center.data()); - glsafe(::glEnd()); - glDisable(GL_LINE_STIPPLE); + auto render_grabber_connection = [this, &formated_gl_version](unsigned int id) { + if (m_grabbers[id].enabled) { + m_grabber_connections[id].old_center = m_center; + m_grabber_connections[id].model.reset(); + + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; + init_data.color = AXES_COLOR[id]; + init_data.reserve_vertices(2); + init_data.reserve_indices(2); + + // vertices + init_data.add_vertex((Vec3f)origin.cast()); + init_data.add_vertex((Vec3f)m_grabbers[id].center.cast()); + + // indices + init_data.add_line(0, 1); + + m_grabber_connections[id].model.init_from(std::move(init_data)); + //} + +#ifdef __APPLE__ + if (formated_gl_version < 30) +#endif + { + glLineStipple(1, 0x0FFF); + glEnable(GL_LINE_STIPPLE); + } + + m_grabber_connections[id].model.render_geometry(); + +#ifdef __APPLE__ + if (formated_gl_version < 30) +#endif + { + glDisable(GL_LINE_STIPPLE); + } } + }; + + const auto& shader = wxGetApp().get_shader("flat"); + if (shader) { + wxGetApp().bind_shader(shader); + shader->set_uniform("view_model_matrix", camera.get_view_matrix() * m_orient_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + for (unsigned int i = 0; i < 3; ++i) { + render_grabber_connection(i); + } + wxGetApp().unbind_shader(); } - glsafe(::glPopMatrix()); if (m_object_manipulation->is_instance_coordinates()) { - glsafe(::glPushMatrix()); Geometry::Transformation cur_tran; if (auto mi = m_parent.get_selection().get_selected_single_intance()) { cur_tran = mi->get_transformation(); @@ -267,9 +303,7 @@ void GLGizmoMove3D::on_render() else { cur_tran = selection.get_first_volume()->get_instance_transformation(); } - glsafe(::glMultMatrixd(cur_tran.get_matrix().data())); - render_cross_mark(Vec3f::Zero(), true); - glsafe(::glPopMatrix()); + render_cross_mark(cur_tran.get_matrix(), Vec3f::Zero(), true); } } @@ -287,12 +321,10 @@ void GLGizmoMove3D::on_render_for_picking() m_grabbers[i].color = color; } } - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(Geometry::Transformation(m_orient_matrix).get_matrix().data())); + render_grabber_extension(X, m_bounding_box, true); render_grabber_extension(Y, m_bounding_box, true); render_grabber_extension(Z, m_bounding_box, true); - glsafe(::glPopMatrix()); } //BBS: add input window for move @@ -340,30 +372,31 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box } } - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); if (shader == nullptr) return; + wxGetApp().bind_shader(shader); const_cast(&m_vbo_cone)->set_color(-1, color); + + const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); + Transform3d view_model_matrix = camera.get_view_matrix() * m_orient_matrix * Geometry::assemble_transform(m_grabbers[axis].center); + if (axis == X) + view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY()); + else if (axis == Y) + view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitX()); + view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 2.0 * size)); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); if (!picking) { - shader->start_using(); shader->set_uniform("emission_factor", 0.1f); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); } - glsafe(::glPushMatrix()); - glsafe(::glTranslated(m_grabbers[axis].center.x(), m_grabbers[axis].center.y(), m_grabbers[axis].center.z())); - if (axis == X) - glsafe(::glRotated(90.0, 0.0, 1.0, 0.0)); - else if (axis == Y) - glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0)); + m_vbo_cone.render_geometry(); - //glsafe(::glTranslated(0.0, 0.0, 2.0 * size)); - glsafe(::glScaled(0.75 * size, 0.75 * size, 2.0 * size)); - m_vbo_cone.render(); - glsafe(::glPopMatrix()); - - if (! picking) - shader->stop_using(); + wxGetApp().unbind_shader(); } void GLGizmoMove3D::change_cs_by_selection() { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index bc6439322..0df07661d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -31,6 +31,13 @@ class GLGizmoMove3D : public GLGizmoBase //BBS: add size adjust related GizmoObjectManipulation* m_object_manipulation; + struct GrabberConnection + { + GLModel model; + Vec3d old_center{ Vec3d::Zero() }; + }; + std::array m_grabber_connections; + public: //BBS: add obj manipulation logic //GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index c5e504cdc..4e534d813 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -11,6 +11,7 @@ #include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/Utils/UndoRedo.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" #include "libslic3r/TriangleMesh.hpp" @@ -77,14 +78,14 @@ void GLGizmoPainterBase::update_front_view_radian() void GLGizmoPainterBase::render_triangles(const Selection& selection) const { - auto* shader = wxGetApp().get_shader("gouraud"); + const auto& shader = wxGetApp().get_shader("gouraud"); if (! shader) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("slope.actived", false); shader->set_uniform("print_volume.type", 0); shader->set_uniform("clipping_plane", this->get_clipping_plane_data().clp_dataf); - ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); + ScopeGuard guard([shader]() { if (shader) wxGetApp().unbind_shader(); }); const ModelObject *mo = m_c->selection_info()->model_object(); int mesh_id = -1; @@ -93,7 +94,7 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const continue; ++mesh_id; - + Transform3d trafo_matrix; if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix(); @@ -107,8 +108,11 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const if (is_left_handed) glsafe(::glFrontFace(GL_CW)); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(trafo_matrix.data())); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d matrix = camera.get_view_matrix() * trafo_matrix; + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); // For printers with multiple extruders, it is necessary to pass trafo_matrix // to the shader input variable print_box.volume_world_matrix before @@ -116,9 +120,8 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const // wrong transformation matrix is used for "Clipping of view". shader->set_uniform("volume_world_matrix", trafo_matrix); - m_triangle_selectors[mesh_id]->render(m_imgui); + m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix); - glsafe(::glPopMatrix()); if (is_left_handed) glsafe(::glFrontFace(GL_CCW)); } @@ -180,20 +183,55 @@ void GLGizmoPainterBase::render_cursor() const void GLGizmoPainterBase::render_cursor_circle() const { - const Camera &camera = wxGetApp().plater()->get_camera(); - auto zoom = (float) camera.get_zoom(); + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) { + return; + } + if (!m_circle.is_initialized()) { + GLModel::Geometry init_data; + static const unsigned int StepsCount = 40; + static const float StepSize = 2.0f * float(PI) / float(StepsCount); + init_data.format = { GLModel::PrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 }; + init_data.color = { 0.0f, 1.0f, 0.3f, 1.0f }; + init_data.reserve_vertices(StepsCount); + init_data.reserve_indices(StepsCount); + + // vertices + indices + for (unsigned short i = 0; i < StepsCount; ++i) { + const float angle = float(i * StepSize); + init_data.add_vertex(Vec2f(cos(angle), sin(angle))); + init_data.add_index(i); + } + + m_circle.init_from(std::move(init_data)); + } + + const Camera& camera = wxGetApp().plater()->get_camera(); + auto zoom = (float)camera.get_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - Size cnv_size = m_parent.get_canvas_size(); - float cnv_half_width = 0.5f * (float) cnv_size.get_width(); - float cnv_half_height = 0.5f * (float) cnv_size.get_height(); + Size cnv_size = m_parent.get_canvas_size(); + float cnv_half_width = 0.5f * (float)cnv_size.get_width(); + float cnv_half_height = 0.5f * (float)cnv_size.get_height(); if ((cnv_half_width == 0.0f) || (cnv_half_height == 0.0f)) return; Vec2d mouse_pos(m_parent.get_local_mouse_position()(0), m_parent.get_local_mouse_position()(1)); Vec2d center(mouse_pos(0) - cnv_half_width, cnv_half_height - mouse_pos(1)); center = center * inv_zoom; - glsafe(::glLineWidth(1.5f)); + const auto view_matrix = camera.get_view_matrix_for_billboard(); + const auto& proj_matrix = camera.get_projection_matrix(); + + Transform3d model_matrix{ Transform3d::Identity() }; + model_matrix.data()[3 * 4 + 0] = center.x(); + model_matrix.data()[3 * 4 + 1] = center.y(); + model_matrix.data()[0 * 4 + 0] = m_cursor_radius; + model_matrix.data()[1 * 4 + 1] = m_cursor_radius; + + wxGetApp().bind_shader(p_flat_shader); + + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); // BBS std::array render_color = this->get_cursor_hover_color(); @@ -201,45 +239,49 @@ void GLGizmoPainterBase::render_cursor_circle() const render_color = this->get_cursor_sphere_left_button_color(); else if (m_button_down == Button::Right) render_color = this->get_cursor_sphere_right_button_color(); - glsafe(::glColor4fv(render_color.data())); + m_circle.set_color(render_color); + + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(1.5f); glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glPushMatrix()); - glsafe(::glLoadIdentity()); - // ensure that the circle is renderered inside the frustrum - glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.5))); - // ensure that the overlay fits the frustrum near z plane - double gui_scale = camera.get_gui_scale(); - glsafe(::glScaled(gui_scale, gui_scale, 1.0)); + GLboolean was_line_stipple_enabled = GL_FALSE; +#ifdef __APPLE__ + const auto& gl_info = p_ogl_manager->get_gl_info(); + const auto formated_gl_version = gl_info.get_formated_gl_version(); + if (formated_gl_version < 30) +#endif + { + glsafe(::glGetBooleanv(GL_LINE_STIPPLE, &was_line_stipple_enabled)); + glsafe(::glLineStipple(4, 0xAAAA)); + glsafe(::glEnable(GL_LINE_STIPPLE)); + } - glsafe(::glPushAttrib(GL_ENABLE_BIT)); - glsafe(::glLineStipple(4, 0xAAAA)); - glsafe(::glEnable(GL_LINE_STIPPLE)); + m_circle.render_geometry(); - ::glBegin(GL_LINE_LOOP); - for (double angle=0; angle<2*M_PI; angle+=M_PI/20.) - ::glVertex2f(GLfloat(center.x()+m_cursor_radius*cos(angle)), GLfloat(center.y()+m_cursor_radius*sin(angle))); - glsafe(::glEnd()); - - glsafe(::glPopAttrib()); - glsafe(::glPopMatrix()); + if (!was_line_stipple_enabled) { +#ifdef __APPLE__ + if (formated_gl_version < 30) +#endif + { + glsafe(::glDisable(GL_LINE_STIPPLE)); + } + } glsafe(::glEnable(GL_DEPTH_TEST)); + + wxGetApp().unbind_shader(); } void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const { + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) + return; const Transform3d complete_scaling_matrix_inverse = Geometry::Transformation(trafo).get_matrix(true, true, false, true).inverse(); const bool is_left_handed = Geometry::Transformation(trafo).is_left_handed(); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(trafo.data())); - // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - glsafe(::glTranslatef(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2))); - glsafe(::glMultMatrixd(complete_scaling_matrix_inverse.data())); - glsafe(::glScaled(m_cursor_radius, m_cursor_radius, m_cursor_radius)); - if (is_left_handed) glFrontFace(GL_CW); @@ -249,14 +291,27 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const render_color = this->get_cursor_sphere_left_button_color(); else if (m_button_down == Button::Right) render_color = this->get_cursor_sphere_right_button_color(); - glsafe(::glColor4fv(render_color.data())); - m_vbo_sphere.render(); + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_projection_matrix(); + const auto& proj_matrix = view_matrix; + + // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. + Transform3d view_model_matrix = camera.get_view_matrix() * trafo * + Geometry::assemble_transform(m_rr.hit.cast()) * complete_scaling_matrix_inverse * + Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), m_cursor_radius * Vec3d::Ones()); + + wxGetApp().bind_shader(p_flat_shader); + p_flat_shader->set_uniform("view_model_matrix", view_model_matrix); + p_flat_shader->set_uniform("projection_matrix", proj_matrix); + p_flat_shader->set_uniform("uniform_color", render_color); + + m_vbo_sphere.render(p_flat_shader); + + wxGetApp().unbind_shader(); if (is_left_handed) glFrontFace(GL_CCW); - - glsafe(::glPopMatrix()); } Vec2i GLGizmoPainterBase::_3d_to_mouse(Vec3d pos_in_3d, const Camera &camera) const @@ -366,6 +421,15 @@ void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) co m_cut_contours.resize(volumes_count * 2); } m_volumes_index = 0; + + const auto& shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + + wxGetApp().bind_shader(shader); + + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + for (const ModelVolume* mv : model_object->volumes) { TriangleMesh vol_mesh = mv->mesh(); if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { @@ -380,15 +444,19 @@ void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) co for (int i = 0; i < zs.size(); i++) { update_contours(m_volumes_index, vol_mesh, zs[i], max_z, min_z, m_is_cursor_in_imgui ? false : (i == 0 ? true : false)); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(m_cut_contours[m_volumes_index].shift.x(), m_cut_contours[m_volumes_index].shift.y(), m_cut_contours[m_volumes_index].shift.z())); - glsafe(::glLineWidth(2.0f)); - m_cut_contours[m_volumes_index].contours.render(); - glsafe(::glPopMatrix()); + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_cut_contours[m_volumes_index].shift); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + p_ogl_manager->set_line_width(2.0f); + m_cut_contours[m_volumes_index].contours.render_geometry(); + m_volumes_index++; } - } + + wxGetApp().unbind_shader(); } BoundingBoxf3 GLGizmoPainterBase::bounding_box() const @@ -1202,51 +1270,39 @@ std::array TriangleSelectorGUI::get_seed_fill_color(const std::arrayget_name() == "gouraud"); ScopeGuard guard([shader]() { if (shader) shader->set_uniform("offset_depth_buffer", false);}); shader->set_uniform("offset_depth_buffer", true); for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color), std::make_pair(&m_iva_blockers, blockers_color)}) { - if (iva.first->has_VBOs()) { - shader->set_uniform("uniform_color", iva.second); - iva.first->render(); - } + iva.first->set_color(iva.second); + iva.first->render_geometry(); } - for (auto &iva : m_iva_seed_fills) - if (iva.has_VBOs()) { - size_t color_idx = &iva - &m_iva_seed_fills.front(); - const std::array &color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color : - color_idx == 2 ? blockers_color : - GLVolume::NEUTRAL_COLOR); - shader->set_uniform("uniform_color", color); - iva.render(); - } - - if (m_paint_contour.has_VBO()) { - ScopeGuard guard_gouraud([shader]() { shader->start_using(); }); - shader->stop_using(); - - auto *contour_shader = wxGetApp().get_shader("mm_contour"); - contour_shader->start_using(); - - glsafe(::glDepthFunc(GL_LEQUAL)); - m_paint_contour.render(); - glsafe(::glDepthFunc(GL_LESS)); - - contour_shader->stop_using(); + for (auto& iva : m_iva_seed_fills) { + size_t color_idx = &iva - &m_iva_seed_fills.front(); + const std::array& color = TriangleSelectorGUI::get_seed_fill_color(color_idx == 1 ? enforcers_color : + color_idx == 2 ? blockers_color : + GLVolume::NEUTRAL_COLOR); + iva.set_color(color); + iva.render_geometry(); } + ScopeGuard guard_gouraud([shader]() { wxGetApp().bind_shader(shader); }); + wxGetApp().unbind_shader(); + + render_paint_contour(matrix); + #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG if (imgui) render_debug(imgui); @@ -1262,10 +1318,18 @@ void TriangleSelectorGUI::update_render_data() std::vector seed_fill_cnt(m_iva_seed_fills.size(), 0); for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) - iva->release_geometry(); + iva->reset(); for (auto &iva : m_iva_seed_fills) - iva.release_geometry(); + iva.reset(); + + GLModel::Geometry iva_enforcers_data; + iva_enforcers_data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; + GLModel::Geometry iva_blockers_data; + iva_blockers_data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; + std::array iva_seed_fills_data; + for (auto& data : iva_seed_fills_data) + data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; for (const Triangle &tr : m_triangles) { bool is_valid = tr.valid(); @@ -1276,9 +1340,9 @@ void TriangleSelectorGUI::update_render_data() continue; int tr_state = int(tr.get_state()); - GLIndexedVertexArray &iva = tr.is_selected_by_seed_fill() ? m_iva_seed_fills[tr_state] : - tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : - m_iva_blockers; + GLModel::Geometry& iva = tr.is_selected_by_seed_fill() ? iva_seed_fills_data[tr_state] : + tr.get_state() == EnforcerBlockerType::ENFORCER ? iva_enforcers_data : + iva_blockers_data; int &cnt = tr.is_selected_by_seed_fill() ? seed_fill_cnt[tr_state] : tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt; @@ -1288,37 +1352,64 @@ void TriangleSelectorGUI::update_render_data() //FIXME the normal may likely be pulled from m_triangle_selectors, but it may not be worth the effort // or the current implementation may be more cache friendly. const Vec3f n = (v1 - v0).cross(v2 - v1).normalized(); - iva.push_geometry(v0, n); - iva.push_geometry(v1, n); - iva.push_geometry(v2, n); - iva.push_triangle(cnt, cnt + 1, cnt + 2); + iva.add_vertex(v0, n); + iva.add_vertex(v1, n); + iva.add_vertex(v2, n); + iva.add_triangle((unsigned int)cnt, (unsigned int)cnt + 1, (unsigned int)cnt + 2); cnt += 3; } - for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) - iva->finalize_geometry(true); - - for (auto &iva : m_iva_seed_fills) - iva.finalize_geometry(true); - - m_paint_contour.release_geometry(); - std::vector contour_edges = this->get_seed_fill_contour(); - m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6); - for (const Vec2i &edge : contour_edges) { - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.x()); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.y()); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.z()); - - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.x()); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.y()); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.z()); + if (!iva_enforcers_data.is_empty()) + m_iva_enforcers.init_from(std::move(iva_enforcers_data)); + if (!iva_blockers_data.is_empty()) + m_iva_blockers.init_from(std::move(iva_blockers_data)); + for (size_t i = 0; i < m_iva_seed_fills.size(); ++i) { + if (!iva_seed_fills_data[i].is_empty()) + m_iva_seed_fills[i].init_from(std::move(iva_seed_fills_data[i])); } - m_paint_contour.contour_indices.assign(m_paint_contour.contour_vertices.size() / 3, 0); - std::iota(m_paint_contour.contour_indices.begin(), m_paint_contour.contour_indices.end(), 0); - m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size(); + update_paint_contour(); +} - m_paint_contour.finalize_geometry(); +void TriangleSelectorGUI::update_paint_contour() +{ + m_paint_contour.reset(); + + GLModel::Geometry init_data; + const std::vector contour_edges = this->get_seed_fill_contour(); + init_data.format = { GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(2 * contour_edges.size()); + init_data.reserve_indices(2 * contour_edges.size()); + init_data.color = ColorRGBA::WHITE(); + // vertices + indices + unsigned int vertices_count = 0; + for (const Vec2i& edge : contour_edges) { + init_data.add_vertex(m_vertices[edge(0)].v); + init_data.add_vertex(m_vertices[edge(1)].v); + vertices_count += 2; + init_data.add_line(vertices_count - 2, vertices_count - 1); + } + + if (!init_data.is_empty()) + m_paint_contour.init_from(std::move(init_data)); +} +void TriangleSelectorGUI::render_paint_contour(const Transform3d& matrix) +{ + const auto& contour_shader = wxGetApp().get_shader("mm_contour"); + if (contour_shader) + { + wxGetApp().bind_shader(contour_shader); + + const Camera& camera = wxGetApp().plater()->get_camera(); + contour_shader->set_uniform("view_model_matrix", camera.get_view_matrix() * matrix); + contour_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + + glsafe(::glDepthFunc(GL_LEQUAL)); + m_paint_contour.render_geometry(); + glsafe(::glDepthFunc(GL_LESS)); + + wxGetApp().unbind_shader(); + } } // BBS @@ -1330,30 +1421,21 @@ bool TrianglePatch::is_fragment() const float TriangleSelectorPatch::gap_area = TriangleSelectorPatch::GapAreaMin; bool TriangleSelectorPatch::exist_gap_area = false; -void TriangleSelectorPatch::render(ImGuiWrapper* imgui) +void TriangleSelectorPatch::render(ImGuiWrapper* imgui, const Transform3d& matrix) { - if (m_cached_wireframe_mode != wxGetApp().plater()->is_show_wireframe()) { - m_cached_wireframe_mode = wxGetApp().plater()->is_show_wireframe(); - m_update_render_data = true; - m_paint_changed = true; - } if (m_update_render_data) update_render_data(); - auto* shader = wxGetApp().get_current_shader(); + const auto shader = wxGetApp().get_current_shader(); if (!shader) return; assert(shader->get_name() == "mm_gouraud"); GLint position_id = -1; GLint barycentric_id = -1; - bool show_wireframe = false; if (wxGetApp().plater()->is_wireframe_enabled()) { if (m_need_wireframe && wxGetApp().plater()->is_show_wireframe()) { - position_id = shader->get_attrib_location("v_position"); - barycentric_id = shader->get_attrib_location("v_barycentric"); //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", show_wireframe on"); shader->set_uniform("show_wireframe", true); - show_wireframe = true; } else { //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", show_wireframe off"); @@ -1380,24 +1462,14 @@ void TriangleSelectorPatch::render(ImGuiWrapper* imgui) shader->set_uniform("uniform_color", new_color); //shader->set_uniform("uniform_color", color); //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", buffer_idx %1%: new_color[%2%, %3%, %4%, %5%]")%buffer_idx%new_color[0]%new_color[1]%new_color[2]%new_color[3]; - this->render(buffer_idx, (int) position_id, show_wireframe); + this->render(buffer_idx); } } - if (m_paint_contour.has_VBO()) - { - ScopeGuard guard_mm_gouraud([shader]() { shader->start_using(); }); - shader->stop_using(); + ScopeGuard guard_mm_gouraud([shader]() { wxGetApp().bind_shader(shader); }); + wxGetApp().unbind_shader(); - auto* contour_shader = wxGetApp().get_shader("mm_contour"); - contour_shader->start_using(); - - glsafe(::glDepthFunc(GL_LEQUAL)); - m_paint_contour.render(); - glsafe(::glDepthFunc(GL_LESS)); - - contour_shader->stop_using(); - } + render_paint_contour(matrix); m_update_render_data = false; } @@ -1412,8 +1484,6 @@ void TriangleSelectorPatch::update_triangles_per_type() patch.triangle_indices.reserve(m_triangles.size() / 3); } - bool using_wireframe = (wxGetApp().plater()->is_wireframe_enabled() && wxGetApp().plater()->is_show_wireframe()) ? true : false; - for (auto& triangle : m_triangles) { if (!triangle.valid() || triangle.is_split()) continue; @@ -1423,27 +1493,25 @@ void TriangleSelectorPatch::update_triangles_per_type() //patch.triangle_indices.insert(patch.triangle_indices.end(), triangle.verts_idxs.begin(), triangle.verts_idxs.end()); for (int i = 0; i < 3; ++i) { int j = triangle.verts_idxs[i]; - int index = using_wireframe?int(patch.patch_vertices.size()/6) : int(patch.patch_vertices.size()/3); + int index = int(patch.patch_vertices.size() / 6); //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: i=%2%, j=%3%, index=%4%, v[%5%,%6%,%7%]")%__LINE__%i%j%index%m_vertices[j].v(0)%m_vertices[j].v(1)%m_vertices[j].v(2); patch.patch_vertices.emplace_back(m_vertices[j].v(0)); patch.patch_vertices.emplace_back(m_vertices[j].v(1)); patch.patch_vertices.emplace_back(m_vertices[j].v(2)); - if (using_wireframe) { - if (i == 0) { - patch.patch_vertices.emplace_back(1.0); - patch.patch_vertices.emplace_back(0.0); - patch.patch_vertices.emplace_back(0.0); - } - else if (i == 1) { - patch.patch_vertices.emplace_back(0.0); - patch.patch_vertices.emplace_back(1.0); - patch.patch_vertices.emplace_back(0.0); - } - else { - patch.patch_vertices.emplace_back(0.0); - patch.patch_vertices.emplace_back(0.0); - patch.patch_vertices.emplace_back(1.0); - } + if (i == 0) { + patch.patch_vertices.emplace_back(1.0); + patch.patch_vertices.emplace_back(0.0); + patch.patch_vertices.emplace_back(0.0); + } + else if (i == 1) { + patch.patch_vertices.emplace_back(0.0); + patch.patch_vertices.emplace_back(1.0); + patch.patch_vertices.emplace_back(0.0); + } + else { + patch.patch_vertices.emplace_back(0.0); + patch.patch_vertices.emplace_back(0.0); + patch.patch_vertices.emplace_back(1.0); } patch.triangle_indices.emplace_back( index); } @@ -1470,8 +1538,6 @@ void TriangleSelectorPatch::update_triangles_per_patch() auto [neighbors, neighbors_propagated] = this->precompute_all_neighbors(); std::vector visited(m_triangles.size(), false); - bool using_wireframe = (wxGetApp().plater()->is_wireframe_enabled() && wxGetApp().plater()->is_show_wireframe()) ? true : false; - auto get_all_touching_triangles = [this](int facet_idx, const Vec3i& neighbors, const Vec3i& neighbors_propagated) -> std::vector { assert(facet_idx != -1 && facet_idx < int(m_triangles.size())); assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors)); @@ -1533,26 +1599,24 @@ void TriangleSelectorPatch::update_triangles_per_patch() Triangle& triangle = m_triangles[current_facet]; for (int i = 0; i < 3; ++i) { int j = triangle.verts_idxs[i]; - int index = using_wireframe?int(patch.patch_vertices.size()/6) : int(patch.patch_vertices.size()/3); + int index = int(patch.patch_vertices.size() / 6); patch.patch_vertices.emplace_back(m_vertices[j].v(0)); patch.patch_vertices.emplace_back(m_vertices[j].v(1)); patch.patch_vertices.emplace_back(m_vertices[j].v(2)); - if (using_wireframe) { - if (i == 0) { - patch.patch_vertices.emplace_back(1.0); - patch.patch_vertices.emplace_back(0.0); - patch.patch_vertices.emplace_back(0.0); - } - else if (i == 1) { - patch.patch_vertices.emplace_back(0.0); - patch.patch_vertices.emplace_back(1.0); - patch.patch_vertices.emplace_back(0.0); - } - else { - patch.patch_vertices.emplace_back(0.0); - patch.patch_vertices.emplace_back(0.0); - patch.patch_vertices.emplace_back(1.0); - } + if (i == 0) { + patch.patch_vertices.emplace_back(1.0); + patch.patch_vertices.emplace_back(0.0); + patch.patch_vertices.emplace_back(0.0); + } + else if (i == 1) { + patch.patch_vertices.emplace_back(0.0); + patch.patch_vertices.emplace_back(1.0); + patch.patch_vertices.emplace_back(0.0); + } + else { + patch.patch_vertices.emplace_back(0.0); + patch.patch_vertices.emplace_back(0.0); + patch.patch_vertices.emplace_back(1.0); } patch.triangle_indices.emplace_back( index); } @@ -1581,7 +1645,7 @@ void TriangleSelectorPatch::update_triangles_per_patch() visited[current_facet] = true; } - patch.area = calc_fragment_area(patch, GapAreaMax, using_wireframe?6:3); + patch.area = calc_fragment_area(patch, GapAreaMax, 6); patch.type = start_facet_state; m_triangle_patches.emplace_back(std::move(patch)); } @@ -1623,28 +1687,12 @@ void TriangleSelectorPatch::update_render_data() //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", before paint_contour"); - m_paint_contour.release_geometry(); - std::vector contour_edges = this->get_seed_fill_contour(); - m_paint_contour.contour_vertices.reserve(contour_edges.size() * 6); - for (const Vec2i& edge : contour_edges) { - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.x()); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.y()); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(0)].v.z()); + update_paint_contour(); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.x()); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.y()); - m_paint_contour.contour_vertices.emplace_back(m_vertices[edge(1)].v.z()); - } - - m_paint_contour.contour_indices.assign(m_paint_contour.contour_vertices.size() / 3, 0); - std::iota(m_paint_contour.contour_indices.begin(), m_paint_contour.contour_indices.end(), 0); - m_paint_contour.contour_indices_size = m_paint_contour.contour_indices.size(); - - m_paint_contour.finalize_geometry(); //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", exit"); } -void TriangleSelectorPatch::render(int triangle_indices_idx, int position_id, bool show_wireframe) +void TriangleSelectorPatch::render(int triangle_indices_idx) { assert(triangle_indices_idx < this->m_triangle_indices_VBO_ids.size()); assert(this->m_triangle_patches.size() == this->m_triangle_indices_VBO_ids.size()); @@ -1653,25 +1701,31 @@ void TriangleSelectorPatch::render(int triangle_indices_idx, int position_id, bo assert(this->m_vertices_VBO_ids[triangle_indices_idx] != 0); assert(this->m_triangle_indices_VBO_ids[triangle_indices_idx] != 0); - //glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_id)); - //glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void*)(0 * sizeof(float)))); + const auto& shader = wxGetApp().get_current_shader(); + if (shader == nullptr) + return; + + int position_id = -1; + int color_id = -1; + if (this->m_triangle_indices_sizes[triangle_indices_idx] > 0) { glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_ids[triangle_indices_idx])); - if (show_wireframe) { - glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void *) 0)); - glsafe(::glColorPointer(3,GL_FLOAT, 6 * sizeof(float), (const void *) (3 * sizeof(float)))); - glsafe(::glEnableClientState(GL_COLOR_ARRAY)); + position_id = shader->get_attrib_location("v_position"); + + if (position_id != -1) { + glsafe(::glVertexAttribPointer((GLint)position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), nullptr)); + glsafe(::glEnableVertexAttribArray((GLint)position_id)); } - else { - glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); + color_id = shader->get_attrib_location("v_color"); + if (color_id != -1) { + glsafe(::glVertexAttribPointer((GLint)color_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); + glsafe(::glEnableVertexAttribArray((GLint)color_id)); } //glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: triangle_indices_idx %2%, bind vertex vbo, buffer id %3%")%__LINE__%triangle_indices_idx%this->m_vertices_VBO_ids[triangle_indices_idx]; } - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - // Render using the Vertex Buffer Objects. if (this->m_triangle_indices_sizes[triangle_indices_idx] > 0) { glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->m_triangle_indices_VBO_ids[triangle_indices_idx])); @@ -1680,14 +1734,16 @@ void TriangleSelectorPatch::render(int triangle_indices_idx, int position_id, bo //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: triangle_indices_idx %2%, bind indices vbo, buffer id %3%")%__LINE__%triangle_indices_idx%this->m_triangle_indices_VBO_ids[triangle_indices_idx]; } - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - if ((this->m_triangle_indices_sizes[triangle_indices_idx] > 0)&&(position_id != -1)) - glsafe(::glDisableVertexAttribArray(position_id)); - if ((this->m_triangle_indices_sizes[triangle_indices_idx] > 0)&&show_wireframe) { - glsafe(::glDisableClientState(GL_COLOR_ARRAY)); - } if (this->m_triangle_indices_sizes[triangle_indices_idx] > 0) + { + if (position_id != -1) { + glsafe(::glDisableVertexAttribArray(position_id)); + } + if (color_id != -1) { + glsafe(::glDisableVertexAttribArray(color_id)); + } glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + } } void TriangleSelectorPatch::release_geometry() @@ -1754,15 +1810,23 @@ void TriangleSelectorPatch::finalize_triangle_indices() void GLPaintContour::render() const { + const auto shader = wxGetApp().get_current_shader(); + if (shader == nullptr) + return; + assert(this->m_contour_VBO_id != 0); assert(this->m_contour_EBO_id != 0); - glsafe(::glLineWidth(4.0f)); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(4.0f); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_VBO_id)); - glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + auto position_id = shader->get_attrib_location("v_position"); + if (position_id != -1) { + glsafe(::glVertexAttribPointer((GLint)position_id, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr)); + glsafe(::glEnableVertexAttribArray((GLint)position_id)); + } if (this->contour_indices_size > 0) { glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->m_contour_EBO_id)); @@ -1770,9 +1834,11 @@ void GLPaintContour::render() const glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + + if (position_id != -1) { + glsafe(::glDisableVertexAttribArray(position_id)); + } } void GLPaintContour::finalize_geometry() @@ -1846,56 +1912,73 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) }; for (auto& va : m_varrays) - va.release_geometry(); + va.reset(); std::array cnts; - ::glScalef(1.01f, 1.01f, 1.01f); + std::array varrays_data; + for (auto& data : varrays_data) + data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3, GLModel::Geometry::EIndexType::UINT }; for (int tr_id=0; tr_idpush_geometry(double(m_vertices[tr.verts_idxs[i]].v[0]), - double(m_vertices[tr.verts_idxs[i]].v[1]), - double(m_vertices[tr.verts_idxs[i]].v[2]), - 0., 0., 1.); - va->push_triangle(*cnt, - *cnt+1, - *cnt+2); + for (int i = 0; i < 3; ++i) { + va->add_vertex(m_vertices[tr.verts_idxs[i]].v, Vec3f(0.0f, 0.0f, 1.0f)); + } + va->add_uint_triangle((unsigned int)*cnt, (unsigned int)*cnt + 1, (unsigned int)*cnt + 2); *cnt += 3; } - ::glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - for (vtype i : {ORIGINAL, SPLIT, INVALID}) { - GLIndexedVertexArray& va = m_varrays[i]; - va.finalize_geometry(true); - if (va.has_VBOs()) { + for (int i = 0; i < 3; ++i) { + if (!varrays_data[i].is_empty()) + m_varrays[i].init_from(std::move(varrays_data[i])); + } + + const auto curr_shader = wxGetApp().get_current_shader(); + if (curr_shader != nullptr) + wxGetApp().unbind_shader(); + + const auto& shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + wxGetApp().bind_shader(shader); + + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix()); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + + ::glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + for (vtype i : {ORIGINAL, SPLIT, INVALID}) { + GLModel& va = m_varrays[i]; switch (i) { - case ORIGINAL : ::glColor3f(0.f, 0.f, 1.f); break; - case SPLIT : ::glColor3f(1.f, 0.f, 0.f); break; - case INVALID : ::glColor3f(1.f, 1.f, 0.f); break; + case ORIGINAL: va.set_color({ 0.0f, 0.0f, 1.0f, 1.0f }); break; + case SPLIT: va.set_color({ 1.0f, 0.0f, 0.0f, 1.0f }); break; + case INVALID: va.set_color({ 1.0f, 1.0f, 0.0f, 1.0f }); break; } va.render(); } + ::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + wxGetApp().unbind_shader(); } - ::glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + + if (curr_shader != nullptr) + wxGetApp().bind_shader(curr_shader); } #endif diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index f72a51db3..7bb777adb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -71,8 +71,7 @@ public: // Render current selection. Transformation matrices are supposed // to be already set. - virtual void render(ImGuiWrapper *imgui); - void render() { this->render(nullptr); } + virtual void render(ImGuiWrapper *imgui, const Transform3d& matrix); void set_wireframe_needed(bool need_wireframe) { m_need_wireframe = need_wireframe; } bool get_wireframe_needed() { return m_need_wireframe; } @@ -93,6 +92,10 @@ public: bool m_show_invalid{false}; #endif +protected: + void update_paint_contour(); + void render_paint_contour(const Transform3d& matrix); + protected: bool m_update_render_data = false; // BBS @@ -103,13 +106,13 @@ protected: private: void update_render_data(); - GLIndexedVertexArray m_iva_enforcers; - GLIndexedVertexArray m_iva_blockers; - std::array m_iva_seed_fills; - std::array m_varrays; + GLModel m_iva_enforcers; + GLModel m_iva_blockers; + std::array m_iva_seed_fills; + std::array m_varrays; protected: - GLPaintContour m_paint_contour; + GLModel m_paint_contour; bool m_need_wireframe {false}; }; @@ -134,7 +137,7 @@ public: // Render current selection. Transformation matrices are supposed // to be already set. - void render(ImGuiWrapper* imgui) override; + void render(ImGuiWrapper* imgui, const Transform3d& matrix) override; // TriangleSelector.m_triangles => m_gizmo_scene.triangle_patches void update_triangles_per_type(); // m_gizmo_scene.triangle_patches => TriangleSelector.m_triangles @@ -199,11 +202,10 @@ protected: std::vector> m_ebt_colors; bool m_filter_state = false; - bool m_cached_wireframe_mode = false; private: void update_render_data(); - void render(int buffer_idx, int position_id = -1, bool show_wireframe=false); + void render(int buffer_idx); }; @@ -375,6 +377,7 @@ protected: ObjectID object_id; int instance_idx{ -1 }; }; + mutable GLModel m_circle; mutable std::vector m_cut_contours; mutable int m_volumes_index = 0; mutable float m_cursor_z{0}; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 349c6f508..5a71e6633 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -8,6 +8,7 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/Plater.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include "libslic3r/PresetBundle.hpp" #include "slic3r/GUI/Jobs/RotoptimizeJob.hpp" @@ -130,41 +131,54 @@ void GLGizmoRotate::on_render() init_data_from_selection(selection); } + const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset); + m_grabbers.front().center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); + m_grabbers.front().color = AXES_COLOR[m_axis]; + m_grabbers.front().hover_color = AXES_HOVER_COLOR[m_axis]; + + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d scalling_matrix{ Transform3d::Identity() }; + const auto& t_zoom = camera.get_zoom(); + scalling_matrix.data()[0 * 4 + 0] = 1.0f / t_zoom; + scalling_matrix.data()[1 * 4 + 1] = 1.0f / t_zoom; + scalling_matrix.data()[2 * 4 + 2] = 1.0f / t_zoom; + m_base_model_matrix = calculate_base_model_matrix();// transform_to_local(selection)* scalling_matrix; + const auto t_angle = Vec3d(0.0f, 0.0f, m_angle); + const auto t_fullsize = get_fixed_grabber_size(); + m_grabbers.front().m_matrix = m_base_model_matrix * Geometry::assemble_transform(m_grabbers.front().center, t_angle, t_fullsize * Vec3d::Ones()); + glsafe(::glEnable(GL_DEPTH_TEST)); - glsafe(::glPushMatrix()); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width((m_hover_id != -1) ? 2.0f : 1.5f); + ColorRGBA color((m_hover_id != -1) ? m_drag_color : m_highlight_color); + const auto& shader = wxGetApp().get_shader("flat"); + if (shader) { + wxGetApp().bind_shader(shader); - Transform3d redius_scale_matrix; - Geometry::scale_transform(redius_scale_matrix, { m_radius, m_radius, m_radius }); - Transform3d circle_model_matrix = m_base_model_matrix * redius_scale_matrix; - glsafe(::glMultMatrixd(circle_model_matrix.data())); + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d redius_scale_matrix; + Geometry::scale_transform(redius_scale_matrix, { m_radius, m_radius, m_radius }); + Transform3d view_model_matrix = camera.get_view_matrix() * m_base_model_matrix * redius_scale_matrix; - glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); - glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color.data() : m_highlight_color.data())); + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - render_circle(); + render_circle(color); - if (m_hover_id != -1) { - render_scale(); - render_snap_radii(); - render_reference_radius(); + if (m_hover_id != -1) { + render_scale(color); + render_snap_radii(color); + render_reference_radius(color); + render_angle(m_highlight_color); + } + render_grabber_connection(color); + + wxGetApp().unbind_shader(); } - glsafe(::glColor4fv(m_highlight_color.data())); - - if (m_hover_id != -1) - render_angle(); - - glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color.data() : m_highlight_color.data())); - - glsafe(::glBegin(GL_LINES)); - glsafe(::glVertex3f(0.0f, 0.0f, 0.0f)); - glsafe(::glVertex3f(::cos(m_angle) * (1.0 + (double)GrabberOffset), ::sin(m_angle) * (1.0 + (double)GrabberOffset), 0.0f)); - glsafe(::glEnd()); - - glsafe(::glPopMatrix()); render_grabber(m_bounding_box); render_grabber_extension(m_bounding_box, false); } @@ -175,13 +189,9 @@ void GLGizmoRotate::on_render_for_picking() glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glPushMatrix()); - const BoundingBoxf3& box = selection.get_bounding_box(); render_grabbers_for_picking(box); render_grabber_extension(box, true); - - glsafe(::glPopMatrix()); } //BBS: add input window for move @@ -216,105 +226,185 @@ void GLGizmoRotate3D::load_rotoptimize_state() } } -void GLGizmoRotate::render_circle() const +void GLGizmoRotate::render_circle(const ColorRGBA& color) const { - ::glBegin(GL_LINE_LOOP); - for (unsigned int i = 0; i < ScaleStepsCount; ++i) - { - float angle = (float)i * ScaleStepRad; - float x = ::cos(angle) * 1.0f; - float y = ::sin(angle) * 1.0f; - float z = 0.0f; - ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z); + if (!m_circle.is_initialized()) { + m_circle.reset(); + + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(ScaleStepsCount); + init_data.reserve_indices(ScaleStepsCount); + + // vertices + indices + for (unsigned short i = 0; i < ScaleStepsCount; ++i) { + const float angle = float(i * ScaleStepRad); + init_data.add_vertex(Vec3f(::cos(angle), ::sin(angle), 0.0f)); + init_data.add_index(i); + } + + m_circle.init_from(std::move(init_data)); } - glsafe(::glEnd()); + + m_circle.set_color(color); + m_circle.render_geometry(); } -void GLGizmoRotate::render_scale() const +void GLGizmoRotate::render_scale(const ColorRGBA& color) const { - float out_radius_long = m_snap_fine_out_radius; - float out_radius_short = 1.0f * (1.0f + 0.5f * ScaleLongTooth); + const float out_radius_long = m_snap_fine_out_radius; + const float out_radius_short = 1.0f * (1.0f + 0.5f * ScaleLongTooth); - ::glBegin(GL_LINES); - for (unsigned int i = 0; i < ScaleStepsCount; ++i) - { - float angle = (float)i * ScaleStepRad; - float cosa = ::cos(angle); - float sina = ::sin(angle); - float in_x = cosa * 1.0f; - float in_y = sina * 1.0f; - float in_z = 0.0f; - float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short; - float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short; - float out_z = 0.0f; - ::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z); - ::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z); + if (!m_scale.is_initialized()) { + m_scale.reset(); + + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(2 * ScaleStepsCount); + init_data.reserve_indices(2 * ScaleStepsCount); + + // vertices + indices + for (unsigned short i = 0; i < ScaleStepsCount; ++i) { + const float angle = float(i * ScaleStepRad); + const float cosa = ::cos(angle); + const float sina = ::sin(angle); + const float in_x = cosa; + const float in_y = sina; + const float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short; + const float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short; + + init_data.add_vertex(Vec3f(in_x, in_y, 0.0f)); + init_data.add_vertex(Vec3f(out_x, out_y, 0.0f)); + init_data.add_index(i * 2); + init_data.add_index(i * 2 + 1); + } + + m_scale.init_from(std::move(init_data)); } - glsafe(::glEnd()); + + m_scale.set_color(color); + m_scale.render_geometry(); } -void GLGizmoRotate::render_snap_radii() const +void GLGizmoRotate::render_snap_radii(const ColorRGBA& color) const { - float step = 2.0f * (float)PI / (float)SnapRegionsCount; + const float step = 2.0f * float(PI) / float(SnapRegionsCount); + const float in_radius = 1.0f / 3.0f; + const float out_radius = 2.0f * in_radius; - float in_radius = 1.0f / 3.0f; - float out_radius = 2.0f * in_radius; + if (!m_snap_radii.is_initialized()) { + m_snap_radii.reset(); - ::glBegin(GL_LINES); - for (unsigned int i = 0; i < SnapRegionsCount; ++i) - { - float angle = (float)i * step; - float cosa = ::cos(angle); - float sina = ::sin(angle); - float in_x = cosa * in_radius; - float in_y = sina * in_radius; - float in_z = 0.0f; - float out_x = cosa * out_radius; - float out_y = sina * out_radius; - float out_z = 0.0f; - ::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z); - ::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z); + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(2 * ScaleStepsCount); + init_data.reserve_indices(2 * ScaleStepsCount); + + // vertices + indices + for (unsigned short i = 0; i < ScaleStepsCount; ++i) { + const float angle = float(i * step); + const float cosa = ::cos(angle); + const float sina = ::sin(angle); + const float in_x = cosa * in_radius; + const float in_y = sina * in_radius; + const float out_x = cosa * out_radius; + const float out_y = sina * out_radius; + + init_data.add_vertex(Vec3f(in_x, in_y, 0.0f)); + init_data.add_vertex(Vec3f(out_x, out_y, 0.0f)); + init_data.add_index(i * 2); + init_data.add_index(i * 2 + 1); + } + + m_snap_radii.init_from(std::move(init_data)); } - glsafe(::glEnd()); + + m_snap_radii.set_color(color); + m_snap_radii.render_geometry(); } -void GLGizmoRotate::render_reference_radius() const +void GLGizmoRotate::render_reference_radius(const ColorRGBA& color) const { - ::glBegin(GL_LINES); - ::glVertex3f(0.0f, 0.0f, 0.0f); - ::glVertex3f((GLfloat)(1.0f * (1.0f + GrabberOffset)), 0.0f, 0.0f); - glsafe(::glEnd()); + if (!m_reference_radius.is_initialized()) { + m_reference_radius.reset(); + + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(2); + init_data.reserve_indices(2); + + // vertices + init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f)); + init_data.add_vertex(Vec3f(1.0f * (1.0f + GrabberOffset), 0.0f, 0.0f)); + + // indices + init_data.add_line(0, 1); + + m_reference_radius.init_from(std::move(init_data)); + } + + m_reference_radius.set_color(color); + m_reference_radius.render_geometry(); } -void GLGizmoRotate::render_angle() const +void GLGizmoRotate::render_angle(const ColorRGBA& color) const { - float step_angle = (float)m_angle / AngleResolution; - float ex_radius = 1.0f * (1.0f + GrabberOffset); + const float step_angle = float(m_angle) / float(AngleResolution); + const float ex_radius = 1.0f * (1.0f + GrabberOffset); - ::glBegin(GL_LINE_STRIP); - for (unsigned int i = 0; i <= AngleResolution; ++i) - { - float angle = (float)i * step_angle; - float x = ::cos(angle) * ex_radius; - float y = ::sin(angle) * ex_radius; - float z = 0.0f; - ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z); + const bool angle_changed = std::abs(m_old_angle - m_angle) > EPSILON; + m_old_angle = m_angle; + + if (!m_angle_arc.is_initialized() || angle_changed) { + m_angle_arc.reset(); + if (m_angle > 0.0f) { + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(1 + AngleResolution); + init_data.reserve_indices(1 + AngleResolution); + + // vertices + indices + for (unsigned short i = 0; i <= AngleResolution; ++i) { + const float angle = float(i) * step_angle; + init_data.add_vertex(Vec3f(::cos(angle) * ex_radius, ::sin(angle) * ex_radius, 0.0f)); + init_data.add_index(i); + } + + m_angle_arc.init_from(std::move(init_data)); + } } - glsafe(::glEnd()); + + m_angle_arc.set_color(color); + m_angle_arc.render_geometry(); +} + +void GLGizmoRotate::render_grabber_connection(const ColorRGBA& color) +{ + if (!m_grabber_connection.model.is_initialized()) { + m_grabber_connection.model.reset(); + + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(2); + init_data.reserve_indices(2); + + // vertices + init_data.add_vertex(Vec3f(0.0f, 0.0f, 0.0f)); + init_data.add_vertex(Vec3f(::cos(m_angle) * (1.0 + (double)GrabberOffset), ::sin(m_angle) * (1.0 + (double)GrabberOffset), 0.0f)); + + // indices + init_data.add_line(0, 1); + + m_grabber_connection.model.init_from(std::move(init_data)); + } + + m_grabber_connection.model.set_color(color); + m_grabber_connection.model.render_geometry(); } void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const { - double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset); - m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); - m_grabbers[0].color = AXES_COLOR[m_axis]; - m_grabbers[0].hover_color = AXES_HOVER_COLOR[m_axis]; - - const auto t_angle = Vec3d(0.0f, 0.0f, m_angle); - const auto t_fullsize = get_fixed_grabber_size(); - m_grabbers.front().m_matrix = m_base_model_matrix * Geometry::assemble_transform(m_grabbers.front().center, t_angle, t_fullsize * Vec3d::Ones()); - - m_grabbers[0].color = m_highlight_color; + m_grabbers.front().color = m_highlight_color; render_grabbers(box); } @@ -325,40 +415,43 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick std::array color = m_grabbers[0].color; if (!picking && m_hover_id != -1) { color = m_grabbers[0].hover_color; - //color[0] = 1.0f - color[0]; - //color[1] = 1.0f - color[1]; - //color[2] = 1.0f - color[2]; } - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + const auto& shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); if (shader == nullptr) return; const_cast(&m_cone)->set_color(-1, color); + + wxGetApp().bind_shader(shader); + if (!picking) { - shader->start_using(); shader->set_uniform("emission_factor", 0.1f); } const Vec3d& center = m_grabbers.front().center; - glsafe(::glPushMatrix()); - Transform3d model_matrix = m_base_model_matrix - * Geometry::assemble_transform(center, Vec3d(0.5 * PI, 0.0, m_angle)) - * Geometry::assemble_transform(1.5 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size)); - glsafe(::glMultMatrixd(model_matrix.data())); - m_cone.render(); - glsafe(::glPopMatrix()); - model_matrix = m_base_model_matrix * + const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); + const Transform3d& view_matrix = camera.get_view_matrix(); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + + Transform3d view_model_matrix = view_matrix * m_base_model_matrix * + Geometry::assemble_transform(center, Vec3d(0.5 * PI, 0.0, m_angle)) * + Geometry::assemble_transform(1.5 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size)); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_cone.render_geometry(); + + view_model_matrix = view_matrix * m_base_model_matrix * Geometry::assemble_transform(center, Vec3d(-0.5 * PI, 0.0, m_angle)) * Geometry::assemble_transform(1.5 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size)); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(model_matrix.data())); - m_cone.render(); - glsafe(::glPopMatrix()); - if (! picking) - shader->stop_using(); + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_cone.render_geometry(); + + wxGetApp().unbind_shader(); } Transform3d GLGizmoRotate::calculate_base_model_matrix() const @@ -406,9 +499,12 @@ Transform3d GLGizmoRotate::transform_to_local(const Selection &selection) const break; } } + if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) ret = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true) * ret; + return m_orient_matrix * ret; + } Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const @@ -472,26 +568,24 @@ BoundingBoxf3 GLGizmoRotate::get_bounding_box() const // m_circle aabb Transform3d t_circle_model_matrix = calculate_circle_model_matrix(); - BoundingBoxf3 t_circle_aabb; - t_circle_aabb.min = Vec3d(-1.0f, -1.0f, 0.0f); - t_circle_aabb.max = Vec3d(1.0f, 1.0f, 0.0f); - t_circle_aabb.defined = true; - t_circle_aabb.defined = true; - t_circle_aabb = t_circle_aabb.transformed(t_circle_model_matrix); - t_circle_aabb.defined = true; - t_aabb.merge(t_circle_aabb); - t_aabb.defined = true; + if (m_circle.is_initialized()) { + BoundingBoxf3 t_circle_aabb = m_circle.get_bounding_box(); + t_circle_aabb.defined = true; + t_circle_aabb = t_circle_aabb.transformed(t_circle_model_matrix); + t_circle_aabb.defined = true; + t_aabb.merge(t_circle_aabb); + t_aabb.defined = true; + } // end m_circle aabb - + // m_grabber_connection aabb - BoundingBoxf3 t_grabber_connection_aabb; - t_grabber_connection_aabb.merge(Vec3d(0.0f, 0.0f, 0.0f)); - t_grabber_connection_aabb.merge(Vec3d(::cos(m_angle) * (1.0 + (double)GrabberOffset), ::sin(m_angle) * (1.0 + (double)GrabberOffset), 0.0f)); - t_grabber_connection_aabb.defined = true; - t_grabber_connection_aabb = t_grabber_connection_aabb.transformed(t_circle_model_matrix); - t_grabber_connection_aabb.defined = true; - t_aabb.merge(t_grabber_connection_aabb); - t_aabb.defined = true; + if (m_grabber_connection.model.is_initialized()) { + BoundingBoxf3 t_grabber_connection_aabb = m_grabber_connection.model.get_bounding_box(); + t_grabber_connection_aabb = t_grabber_connection_aabb.transformed(t_circle_model_matrix); + t_grabber_connection_aabb.defined = true; + t_aabb.merge(t_grabber_connection_aabb); + t_aabb.defined = true; + } // m_grabbers aabb @@ -503,7 +597,7 @@ BoundingBoxf3 GLGizmoRotate::get_bounding_box() const t_aabb.defined = true; } // end m_grabbers aabb - + // m_cone aabb if (m_cone.is_initialized()) { auto t_cone_aabb = m_cone.get_bounding_box(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index 0e4564ab2..d414f820a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -47,6 +47,19 @@ private: // emboss need to draw rotation gizmo in local coordinate systems bool m_force_local_coordinate{false}; + + struct GrabberConnection + { + GLModel model; + }; + mutable GrabberConnection m_grabber_connection; + mutable GLModel m_circle; + mutable GLModel m_scale; + mutable GLModel m_snap_radii; + mutable GLModel m_reference_radius; + mutable GLModel m_angle_arc; + + mutable float m_old_angle{ 0.0f }; Transform3d m_base_model_matrix{ Transform3d::Identity() }; public: GLGizmoRotate(GLCanvas3D& parent, Axis axis); @@ -73,11 +86,12 @@ protected: void on_render_for_picking() override; private: - void render_circle() const; - void render_scale() const; - void render_snap_radii() const; - void render_reference_radius() const; - void render_angle() const; + void render_circle(const ColorRGBA& color) const; + void render_scale(const ColorRGBA& color) const; + void render_snap_radii(const ColorRGBA& color) const; + void render_reference_radius(const ColorRGBA& color) const; + void render_angle(const ColorRGBA& color) const; + void render_grabber_connection(const ColorRGBA& color); void render_grabber(const BoundingBoxf3& box) const; void render_grabber_extension(const BoundingBoxf3& box, bool picking) const; Transform3d calculate_base_model_matrix() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp index a5d54974a..24d5909ee 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSVG.cpp @@ -607,13 +607,13 @@ void GLGizmoSVG::on_render() Transform3d rotate_matrix = tran.get_rotation_matrix(); Transform3d cube_mat = Geometry::translation_transform(m_move_grabber.center) * rotate_matrix * Geometry::scale_transform(fullsize); m_move_grabber.set_model_matrix(cube_mat); - render_glmodel(m_move_grabber.get_cube(), render_color, cube_mat); + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& projection_matrix = camera.get_projection_matrix(); + render_glmodel(m_move_grabber.get_cube(), render_color, view_matrix * cube_mat, projection_matrix); } #ifdef DEBUG_SVG - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(tran.get_matrix().data())); - render_cross_mark(Vec3f::Zero(), true); - glsafe(::glPopMatrix()); + render_cross_mark(tran.get_matrix(), Vec3f::Zero(), true); #endif if (is_rotate_by_grabbers || (!is_surface_dragging && !is_parent_dragging)) { if (m_hover_id == c_move_cube_id && m_dragging) { @@ -634,7 +634,13 @@ void GLGizmoSVG::on_render_for_picking() m_move_grabber.color[1] = color[1]; m_move_grabber.color[2] = color[2]; m_move_grabber.color[3] = color[3]; - m_move_grabber.render_for_picking(); + + const auto& shader = wxGetApp().get_shader("flat"); + if (nullptr != shader) { + wxGetApp().bind_shader(shader); + m_move_grabber.render_for_picking(); + wxGetApp().unbind_shader(); + } } //BBS: add input window for move diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 07fc61fe7..ca706eb8f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -2,6 +2,7 @@ #include "GLGizmoScale.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include @@ -29,7 +30,15 @@ GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filen , m_snap_step(0.05) //BBS: GUI refactor: add obj manipulation , m_object_manipulation(obj_manipulation) -{} +{ + m_grabber_connections[0].grabber_indices = { 0, 1 }; + m_grabber_connections[1].grabber_indices = { 2, 3 }; + m_grabber_connections[2].grabber_indices = { 4, 5 }; + m_grabber_connections[3].grabber_indices = { 6, 7 }; + m_grabber_connections[4].grabber_indices = { 7, 8 }; + m_grabber_connections[5].grabber_indices = { 8, 9 }; + m_grabber_connections[6].grabber_indices = { 9, 6 }; +} const Vec3d &GLGizmoScale3D::get_scale() { @@ -273,33 +282,36 @@ void GLGizmoScale3D::change_cs_by_selection() { void GLGizmoScale3D::on_render() { + const Selection& selection = m_parent.get_selection(); + + bool single_instance = selection.is_single_full_instance(); + bool single_volume = selection.is_single_modifier() || selection.is_single_volume(); + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_DEPTH_TEST)); update_grabbers_data(); - glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width((m_hover_id != -1) ? 2.0f : 1.5f); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(m_grabbers_tran.get_matrix().data())); - //draw connections - - // BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5) - //if (single_instance || single_volume) { - - if (m_grabbers[4].enabled && m_grabbers[5].enabled) { - glsafe(::glColor4fv(m_grabbers[4].color.data())); - render_grabbers_connection(4, 5); + //draw connections + const auto& shader = wxGetApp().get_shader("flat"); + if (shader != nullptr) { + wxGetApp().bind_shader(shader); + // BBS: when select multiple objects, uniform scale can be deselected, display the connection(4,5) + //if (single_instance || single_volume) { + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("view_model_matrix", camera.get_view_matrix() * m_grabbers_tran.get_matrix()); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + if (m_grabbers[4].enabled && m_grabbers[5].enabled) + render_grabbers_connection(4, 5, m_grabbers[4].color); + render_grabbers_connection(6, 7, m_grabbers[2].color); + render_grabbers_connection(7, 8, m_grabbers[0].color); + render_grabbers_connection(8, 9, m_grabbers[2].color); + render_grabbers_connection(9, 6, m_grabbers[0].color); + wxGetApp().unbind_shader(); } - - glsafe(::glColor4fv(m_grabbers[2].color.data())); - render_grabbers_connection(6, 7); - render_grabbers_connection(8, 9); - - glsafe(::glColor4fv(m_grabbers[0].color.data())); - render_grabbers_connection(7, 8); - render_grabbers_connection(9, 6); - glsafe(::glPopMatrix()); // draw grabbers render_grabbers(); } @@ -310,18 +322,62 @@ void GLGizmoScale3D::on_render_for_picking() render_grabbers_for_picking(m_parent.get_selection().get_bounding_box()); } -void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const +void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2, const ColorRGBA& color) const { - unsigned int grabbers_count = (unsigned int)m_grabbers.size(); - if ((id_1 < grabbers_count) && (id_2 < grabbers_count)) + auto grabber_connection = [this](unsigned int id_1, unsigned int id_2) { + for (int i = 0; i < int(m_grabber_connections.size()); ++i) { + if (m_grabber_connections[i].grabber_indices.first == id_1 && m_grabber_connections[i].grabber_indices.second == id_2) + return i; + } + return -1; + }; + + const int id = grabber_connection(id_1, id_2); + if (id == -1) + return; + + if (!m_grabber_connections[id].model.is_initialized() || + !m_grabber_connections[id].old_v1.isApprox(m_grabbers[id_1].center) || + !m_grabber_connections[id].old_v2.isApprox(m_grabbers[id_2].center)) { + m_grabber_connections[id].old_v1 = m_grabbers[id_1].center; + m_grabber_connections[id].old_v2 = m_grabbers[id_2].center; + m_grabber_connections[id].model.reset(); + + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(2); + init_data.reserve_indices(2); + + // vertices + init_data.add_vertex((Vec3f)m_grabbers[id_1].center.cast()); + init_data.add_vertex((Vec3f)m_grabbers[id_2].center.cast()); + + // indices + init_data.add_line(0, 1); + + m_grabber_connections[id].model.init_from(std::move(init_data)); + } + + m_grabber_connections[id].model.set_color(color); + +#ifdef __APPLE__ + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + const auto& gl_info = p_ogl_manager->get_gl_info(); + const auto formated_gl_version = gl_info.get_formated_gl_version(); + if (formated_gl_version < 30) +#endif { - glLineStipple(1, 0x0FFF); - glEnable(GL_LINE_STIPPLE); - ::glBegin(GL_LINES); - ::glVertex3dv(m_grabbers[id_1].center.data()); - ::glVertex3dv(m_grabbers[id_2].center.data()); - glsafe(::glEnd()); - glDisable(GL_LINE_STIPPLE); + glsafe(::glLineStipple(1, 0x0FFF)); + glsafe(::glEnable(GL_LINE_STIPPLE)); + } + + m_grabber_connections[id].model.render_geometry(); + +#ifdef __APPLE__ + if (formated_gl_version < 30) +#endif + { + glsafe(::glDisable(GL_LINE_STIPPLE)); } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp index 27b1d816f..1d1f77522 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -44,6 +44,15 @@ class GLGizmoScale3D : public GLGizmoBase //BBS: add size adjust related GizmoObjectManipulation* m_object_manipulation; + struct GrabberConnection + { + GLModel model; + std::pair grabber_indices; + Vec3d old_v1{ Vec3d::Zero() }; + Vec3d old_v2{ Vec3d::Zero() }; + }; + mutable std::array m_grabber_connections; + public: //BBS: add obj manipulation logic //GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); @@ -75,7 +84,7 @@ protected: //BBS: GUI refactor: add object manipulation virtual void on_render_input_window(float x, float y, float bottom_limit); private: - void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const; + void render_grabbers_connection(unsigned int id_1, unsigned int id_2, const ColorRGBA& color) const; void do_scale_along_axis(Axis axis, const UpdateData& data); void do_scale_uniform(const UpdateData& data); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index b5259d4b2..868ecc4f3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -103,13 +103,13 @@ bool GLGizmoSeam::on_key_down_select_tool_type(int keyCode) { void GLGizmoSeam::render_triangles(const Selection& selection) const { ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); - auto* shader = wxGetApp().get_shader("mm_gouraud"); + const auto& shader = wxGetApp().get_shader("mm_gouraud"); if (!shader) return; - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("clipping_plane", clp_data.clp_dataf); shader->set_uniform("z_range", clp_data.z_range); - ScopeGuard guard([shader]() { if (shader) shader->stop_using(); }); + ScopeGuard guard([shader]() { if (shader) wxGetApp().unbind_shader(); }); const ModelObject* mo = m_c->selection_info()->model_object(); int mesh_id = -1; @@ -125,8 +125,11 @@ void GLGizmoSeam::render_triangles(const Selection& selection) const if (is_left_handed) glsafe(::glFrontFace(GL_CW)); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(trafo_matrix.data())); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d matrix = camera.get_view_matrix() * trafo_matrix; + shader->set_uniform("view_model_matrix", matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); float normal_z = -::cos(Geometry::deg2rad(m_highlight_by_angle_threshold_deg)); Matrix3f normal_matrix = static_cast(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast()); @@ -136,9 +139,8 @@ void GLGizmoSeam::render_triangles(const Selection& selection) const shader->set_uniform("slope.actived", m_parent.is_using_slope()); shader->set_uniform("slope.volume_world_normal_matrix", static_cast(trafo_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast())); shader->set_uniform("slope.normal_z", normal_z); - m_triangle_selectors[mesh_id]->render(m_imgui); + m_triangle_selectors[mesh_id]->render(m_imgui, trafo_matrix); - glsafe(::glPopMatrix()); if (is_left_handed) glsafe(::glFrontFace(GL_CCW)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index a190f631a..024c070a6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -6,6 +6,7 @@ #include "slic3r/GUI/NotificationManager.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/format.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include "libslic3r/AppConfig.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/QuadricEdgeCollapse.hpp" @@ -652,31 +653,38 @@ void GLGizmoSimplify::on_render() return; const Transform3d trafo_matrix = selected_volume->world_matrix(); - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(trafo_matrix.data())); - auto *gouraud_shader = wxGetApp().get_shader("gouraud_light"); - glsafe(::glPushAttrib(GL_DEPTH_TEST)); + const auto& gouraud_shader = wxGetApp().get_shader("gouraud_light"); + const GLboolean was_depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); glsafe(::glEnable(GL_DEPTH_TEST)); - gouraud_shader->start_using(); - m_glmodel.render(); - gouraud_shader->stop_using(); + wxGetApp().bind_shader(gouraud_shader); + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d view_model_matrix = camera.get_view_matrix() * trafo_matrix; + gouraud_shader->set_uniform("view_model_matrix", view_model_matrix); + gouraud_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + gouraud_shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_glmodel.render_geometry(); + wxGetApp().unbind_shader(); if (m_show_wireframe) { - auto* contour_shader = wxGetApp().get_shader("mm_contour"); - contour_shader->start_using(); - glsafe(::glLineWidth(1.0f)); + const auto& contour_shader = wxGetApp().get_shader("mm_contour"); + wxGetApp().bind_shader(contour_shader); + contour_shader->set_uniform("view_model_matrix", view_model_matrix); + contour_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(1.0f); glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)); //ScopeGuard offset_fill_guard([]() { glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); }); //glsafe(::glEnable(GL_POLYGON_OFFSET_FILL)); //glsafe(::glPolygonOffset(5.0, 5.0)); - m_glmodel.render(); + m_glmodel.render_geometry(); glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)); - contour_shader->stop_using(); + wxGetApp().unbind_shader(); } - glsafe(::glPopAttrib()); - glsafe(::glPopMatrix()); + if (!was_depth_test_enabled) { + glsafe(::glDisable(GL_DEPTH_TEST)); + } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index b4ad8d3ea..ceefc3218 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -120,22 +120,25 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) if (! has_points && ! has_holes) return; - GLShaderProgram* shader = picking ? nullptr : wxGetApp().get_shader("gouraud_light"); - if (shader != nullptr) - shader->start_using(); + const auto& shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); + if (!shader) + return; + + wxGetApp().bind_shader(shader); ScopeGuard guard([shader]() { - if (shader != nullptr) - shader->stop_using(); + wxGetApp().unbind_shader(); }); const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); - const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); - float z_shift = m_c->selection_info()->get_sla_shift(); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(0.0, 0.0, z_shift)); - glsafe(::glMultMatrixd(instance_matrix.data())); + const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix(); + + const Camera& camera = picking ? wxGetApp().plater()->get_picking_camera() : wxGetApp().plater()->get_camera(); + const Transform3d& view_matrix = camera.get_view_matrix(); + const Transform3d& projection_matrix = camera.get_projection_matrix(); + + shader->set_uniform("projection_matrix", projection_matrix); std::array render_color; for (size_t i = 0; i < cache_size; ++i) { @@ -173,9 +176,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) shader->set_uniform("emission_factor", 0.5f); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(support_point.pos(0), support_point.pos(1), support_point.pos(2))); - glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data())); + const Transform3d support_matrix = Geometry::assemble_transform(support_point.pos.cast()) * instance_scaling_matrix_inverse; if (vol->is_left_handed()) glFrontFace(GL_CW); @@ -189,32 +190,31 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) Eigen::Quaterniond q; q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast()); - Eigen::AngleAxisd aa(q); - glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2))); + Eigen::AngleAxisd aa(q); const double cone_radius = 0.25; // mm const double cone_height = 0.75; - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(0.f, 0.f, cone_height + support_point.head_front_radius * RenderPointScale)); - glsafe(::glPushMatrix()); - glsafe(::glRotated(180., 1., 0., 0.)); - glsafe(::glScaled(cone_radius, cone_radius, cone_height)); - m_cone.render(); - glsafe(::glPopMatrix()); - glsafe(::glTranslatef(0.f, 0.f, cone_height)); - glsafe(::glPopMatrix()); + const Transform3d view_model_matrix = view_matrix * instance_matrix * support_matrix * Transform3d(aa.toRotationMatrix()) * + Geometry::assemble_transform((cone_height + support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ(), + Vec3d(PI, 0.0, 0.0), Vec3d(cone_radius, cone_radius, cone_height)); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + + m_cone.render_geometry(); } - glsafe(::glPushMatrix()); - double radius = (double)support_point.head_front_radius * RenderPointScale; - glsafe(::glScaled(radius, radius, radius)); - m_sphere.render(); - glsafe(::glPopMatrix()); + const double radius = (double)support_point.head_front_radius * RenderPointScale; + const Transform3d view_model_matrix = view_matrix * instance_matrix * support_matrix * + Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), radius * Vec3d::Ones()); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + + m_sphere.render_geometry(); if (vol->is_left_handed()) glFrontFace(GL_CCW); - - glsafe(::glPopMatrix()); } // Now render the drain holes: @@ -230,37 +230,29 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) if (is_mesh_point_clipped(drain_hole.pos.cast())) continue; - // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2))); - glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data())); + const Transform3d hole_matrix = Geometry::assemble_transform(drain_hole.pos.cast()) * instance_scaling_matrix_inverse; if (vol->is_left_handed()) glFrontFace(GL_CW); // Matrices set, we can render the point mark now. - Eigen::Quaterniond q; - q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); - Eigen::AngleAxisd aa(q); - glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2))); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(0., 0., -drain_hole.height)); - glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); - m_cylinder.render(); - glsafe(::glPopMatrix()); + // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. + q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast()); + const Eigen::AngleAxisd aa(q); + const Transform3d view_model_matrix = view_matrix * instance_matrix * hole_matrix * Transform3d(aa.toRotationMatrix()) * + Geometry::assemble_transform(-drain_hole.height * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_cylinder.render_geometry(); if (vol->is_left_handed()) glFrontFace(GL_CCW); - glsafe(::glPopMatrix()); } } - - glsafe(::glPopMatrix()); } - - bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const { if (m_c->object_clipper()->get_position() == 0.) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp index 279d02972..ea65ead50 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoText.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoText.cpp @@ -643,6 +643,10 @@ void GLGizmoText::on_render() BOOST_LOG_TRIVIAL(info) << boost::format("Text: selected object is null"); return; } + + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& projection_matrix = camera.get_projection_matrix(); + const auto& view_matrix = camera.get_view_matrix(); // First check that the mouse pointer is on an object. const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; Plater *plater = wxGetApp().plater(); @@ -653,16 +657,10 @@ void GLGizmoText::on_render() Geometry::Transformation tran(m_text_volume_tran); if (tran.get_offset().norm() > 1) { auto text_volume_tran_world = mi->get_transformation().get_matrix() * m_text_volume_tran; - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(text_volume_tran_world.data())); - render_cross_mark(Vec3f::Zero(), true); - glsafe(::glPopMatrix()); + render_cross_mark(text_volume_tran_world, Vec3f::Zero(), true); } - glsafe(::glPushMatrix()); - glsafe(::glMultMatrixd(m_text_tran_in_world.get_matrix().data())); - render_cross_mark(Vec3f::Zero(), true); - glsafe(::glPopMatrix()); + render_cross_mark(m_text_tran_in_world, Vec3f::Zero(), true); glsafe(::glLineWidth(2.0f)); ::glBegin(GL_LINES); @@ -678,7 +676,6 @@ void GLGizmoText::on_render() } #endif if (!m_is_modify || m_shift_down) {//for temp text - const Camera &camera = wxGetApp().plater()->get_camera(); // Precalculate transformations of individual meshes. std::vector trafo_matrices; for (const ModelVolume *mv : mo->volumes) { @@ -731,7 +728,7 @@ void GLGizmoText::on_render() Transform3d rotate_matrix = tran.get_rotation_matrix(); Transform3d cube_mat = Geometry::translation_transform(m_move_grabber.center) * rotate_matrix * Geometry::scale_transform(fullsize); m_move_grabber.set_model_matrix(cube_mat); - render_glmodel(m_move_grabber.get_cube(), render_color, cube_mat); + render_glmodel(m_move_grabber.get_cube(), render_color, view_matrix * cube_mat, projection_matrix); } delete_temp_preview_text_volume(); @@ -746,7 +743,10 @@ void GLGizmoText::on_render() void GLGizmoText::on_render_for_picking() { glsafe(::glDisable(GL_DEPTH_TEST)); - + const auto& shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + wxGetApp().bind_shader(shader); int obejct_idx, volume_idx; ModelVolume *model_volume = m_parent.get_selection().get_selected_single_volume(obejct_idx, volume_idx); if (model_volume && !model_volume->get_text_info().m_text.empty()) { @@ -761,6 +761,7 @@ void GLGizmoText::on_render_for_picking() m_move_grabber.color[3] = color[3]; m_move_grabber.render_for_picking(); } + wxGetApp().unbind_shader(); } void GLGizmoText::on_start_dragging() diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 6e820907b..35fe5d37a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -219,18 +219,12 @@ void InstancesHider::render_cut() const } else clipper->set_limiting_plane(ClippingPlane::ClipsNothing()); - glsafe(::glPushMatrix()); - if (mv->is_model_part()) - glsafe(::glColor3f(0.8f, 0.3f, 0.0f)); - else { - const std::array& c = color_from_model_volume(*mv); - glsafe(::glColor4f(c[0], c[1], c[2], c[3])); - } - glsafe(::glPushAttrib(GL_DEPTH_TEST)); + const GLboolean was_depth_teset_enabled = glIsEnabled(GL_DEPTH_TEST); glsafe(::glDisable(GL_DEPTH_TEST)); clipper->render_cut(mv->is_model_part() ? ColorRGBA{0.8f, 0.3f, 0.0f, 1.0f} : color_from_model_volume(*mv)); - glsafe(::glPopAttrib()); - glsafe(::glPopMatrix()); + if (was_depth_teset_enabled) { + glsafe(::glEnable(GL_DEPTH_TEST)); + } ++clipper_id; } @@ -624,9 +618,7 @@ void SupportsClipper::render_cut() const m_clipper->set_plane(*ocl->get_clipping_plane()); m_clipper->set_transformation(supports_trafo); - glsafe(::glPushMatrix()); m_clipper->render_cut({1.0f, 0.f, 0.37f, 1.0f}); - glsafe(::glPopMatrix()); } @@ -772,10 +764,8 @@ void ModelObjectsClipper::render_cut() const auto& clipper = m_clippers[clipper_id]; clipper->set_plane(*m_clp); clipper->set_transformation(trafo); - glsafe(::glPushMatrix()); // BBS clipper->render_cut({0.25f, 0.25f, 0.25f, 1.0f}); - glsafe(::glPopMatrix()); ++clipper_id; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index e92695086..5e3d9161f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -342,6 +342,7 @@ public: GizmoObjectManipulation& get_object_manipulation() { return m_object_manipulation; } bool get_uniform_scaling() const { return m_object_manipulation.get_uniform_scaling();} BoundingBoxf3 get_bounding_box() const; + private: void render_background(float left, float top, float right, float bottom, float border) const; diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index ca6a05311..430f8dcb3 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -2686,35 +2686,30 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) { if (draw_data == nullptr || draw_data->CmdListsCount == 0) return; - GLShaderProgram* shader = wxGetApp().get_shader("imgui"); + + const auto& shader = wxGetApp().get_shader("imgui"); if (shader == nullptr) return; + // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); const int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x); const int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; - GLShaderProgram* curr_shader = wxGetApp().get_current_shader(); + + const auto curr_shader = wxGetApp().get_current_shader(); if (curr_shader != nullptr) - curr_shader->stop_using(); - shader->start_using(); - // We are using the OpenGL fixed pipeline to make the example code simpler to read! - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. - GLint last_texture; glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture)); - GLint last_polygon_mode[2]; glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode)); - GLint last_viewport[4]; glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport)); - GLint last_scissor_box[4]; glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box)); - const GLboolean was_blend_enabled = glIsEnabled(GL_BLEND); - const GLboolean was_cull_face_enabled = glIsEnabled(GL_CULL_FACE); - const GLboolean was_depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); - const GLboolean was_scissor_test_enabled = glIsEnabled(GL_SCISSOR_TEST); + wxGetApp().unbind_shader(); + + wxGetApp().bind_shader(shader); + GLboolean was_texture2d_enabled = GL_FALSE; - const auto& ogl_manager = wxGetApp().get_opengl_manager(); - if (!ogl_manager) { + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + if (!p_ogl_manager) { return; } - const auto& gl_info = ogl_manager->get_gl_info(); + const auto& gl_info = p_ogl_manager->get_gl_info(); const auto formated_gl_version = gl_info.get_formated_gl_version(); if (formated_gl_version < 30) { was_texture2d_enabled = glIsEnabled(GL_TEXTURE_2D); @@ -2805,37 +2800,13 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glDeleteBuffers(1, &ibo_id)); glsafe(::glDeleteBuffers(1, &vbo_id)); } - // Restore modified state - glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture)); - if (!was_blend_enabled) { - glsafe(::glDisable(GL_BLEND)); - } - if (was_cull_face_enabled) { - glsafe(::glEnable(GL_CULL_FACE)); - } - if (was_depth_test_enabled) { - glsafe(::glEnable(GL_DEPTH_TEST)); - } - if (!was_scissor_test_enabled) { - glsafe(::glDisable(GL_SCISSOR_TEST)); - } - if (formated_gl_version < 30) { - if (!was_texture2d_enabled) { - glsafe(::glDisable(GL_TEXTURE_2D)); - } - } - if (formated_gl_version < 30) { - glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); - glsafe(::glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]))); - } - else { - glsafe(::glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0])); - } - glsafe(::glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3])); - glsafe(::glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3])); - shader->stop_using(); + + glsafe(::glDisable(GL_SCISSOR_TEST)); + + wxGetApp().unbind_shader(); + if (curr_shader != nullptr) - curr_shader->start_using(); + wxGetApp().bind_shader(curr_shader); } bool ImGuiWrapper::display_initialized() const diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index 3070fde04..021ba42d8 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -75,12 +75,14 @@ void MeshClipper::set_transformation(const Geometry::Transformation& trafo) void MeshClipper::render_cut(const ColorRGBA &color, const std::vector *ignore_idxs) { if (!m_result) recalculate_triangles(); - GLShaderProgram *curr_shader = wxGetApp().get_current_shader(); - if (curr_shader != nullptr) curr_shader->stop_using(); + const auto& curr_shader = wxGetApp().get_current_shader(); + if (curr_shader != nullptr) { + wxGetApp().unbind_shader(); + } - GLShaderProgram *shader = wxGetApp().get_shader("flat"); + const auto& shader = wxGetApp().get_shader("flat"); if (shader != nullptr) { - shader->start_using(); + wxGetApp().bind_shader(shader); const Camera &camera = wxGetApp().plater()->get_camera(); shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); @@ -89,24 +91,28 @@ void MeshClipper::render_cut(const ColorRGBA &color, const std::vector * auto isl = m_result->cut_islands[i]; ColorRGBA gray{0.5f, 0.5f, 0.5f, 1.f}; isl->model.set_color(-1, isl->disabled ? gray.get_data() : color.get_data()); - isl->model.render(); + isl->model.render_geometry(); } - shader->stop_using(); + wxGetApp().unbind_shader(); } - if (curr_shader != nullptr) curr_shader->start_using(); + if (curr_shader != nullptr) { + wxGetApp().bind_shader(curr_shader); + } } void MeshClipper::render_contour(const ColorRGBA &color, const std::vector *ignore_idxs) { if (!m_result) recalculate_triangles(); - GLShaderProgram *curr_shader = wxGetApp().get_current_shader(); - if (curr_shader != nullptr) curr_shader->stop_using(); + const auto curr_shader = wxGetApp().get_current_shader(); + if (curr_shader != nullptr) { + wxGetApp().unbind_shader(); + } - GLShaderProgram *shader = wxGetApp().get_shader("flat"); + const auto& shader = wxGetApp().get_shader("flat"); if (shader != nullptr) { - shader->start_using(); + wxGetApp().bind_shader(shader); const Camera &camera = wxGetApp().plater()->get_camera(); shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); @@ -115,13 +121,14 @@ void MeshClipper::render_contour(const ColorRGBA &color, const std::vectorcut_islands[i]; ColorRGBA red{1.0f, 0.f, 0.f, 1.f}; isl->model_expanded.set_color(-1, isl->disabled ? red.get_data() : color.get_data()); - isl->model_expanded.render(); + isl->model_expanded.render_geometry(); } - shader->stop_using(); + wxGetApp().unbind_shader(); } - if (curr_shader != nullptr) - curr_shader->start_using(); + if (curr_shader != nullptr) { + wxGetApp().unbind_shader(); + } } int MeshClipper::is_projection_inside_cut(const Vec3d &point_in) const diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index 2b0fa7f09..388d504ab 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -1,4 +1,4 @@ -#include "libslic3r/libslic3r.h" +#include "libslic3r/libslic3r.h" #include "OpenGLManager.hpp" #include "GUI.hpp" @@ -6,6 +6,7 @@ #include "3DScene.hpp" #include "libslic3r/Platform.hpp" +#include "slic3r/GUI/GLTexture.hpp" #include @@ -196,12 +197,95 @@ bool OpenGLVersionCheck::message_pump_exit = false; #endif // __WIN32__ #define BBS_GL_EXTENSION_FUNC(_func) (OpenGLManager::get_framebuffers_type() == OpenGLManager::EFramebufferType::Ext ? _func ## EXT : _func) -#define BBS_GL_EXTENSION_FRAMEBUFFER OpenGLManager::get_framebuffers_type() == OpenGLManager::EFramebufferType::Ext ? GL_FRAMEBUFFER_EXT : GL_FRAMEBUFFER -#define BBS_GL_EXTENSION_COLOR_ATTACHMENT(color_attachment) (OpenGLManager::get_framebuffers_type() == OpenGLManager::EFramebufferType::Ext ? color_attachment ## _EXT : color_attachment) -#define BBS_GL_EXTENSION_DEPTH_ATTACHMENT OpenGLManager::get_framebuffers_type() == OpenGLManager::EFramebufferType::Ext ? GL_DEPTH_ATTACHMENT_EXT : GL_DEPTH_ATTACHMENT -#define BBS_GL_EXTENSION_RENDER_BUFFER OpenGLManager::get_framebuffers_type() == OpenGLManager::EFramebufferType::Ext ? GL_RENDERBUFFER_EXT : GL_RENDERBUFFER +#define BBS_GL_EXTENSION_PARAMETER(_param) OpenGLManager::get_framebuffers_type() == OpenGLManager::EFramebufferType::Ext ? _param ## _EXT : _param +static uint8_t get_msaa_samples(Slic3r::GUI::EMSAAType msaa_type) { + uint8_t num_samples = 0; + switch (msaa_type) + { + case Slic3r::GUI::EMSAAType::X2: + num_samples = 2; + break; + case Slic3r::GUI::EMSAAType::X8: + num_samples = 8; + break; + case Slic3r::GUI::EMSAAType::X16: + num_samples = 16; + break; + case Slic3r::GUI::EMSAAType::X4: + num_samples = 4; + default: + break; + } + + return num_samples; +} + +static GLenum get_pixel_format(Slic3r::GUI::EPixelFormat type) { + switch (type) + { + case Slic3r::GUI::EPixelFormat::RGBA: + return GL_RGBA; + case Slic3r::GUI::EPixelFormat::DepthComponent: + return GL_DEPTH_COMPONENT; + case Slic3r::GUI::EPixelFormat::StencilIndex: + return GL_STENCIL_INDEX; + case Slic3r::GUI::EPixelFormat::DepthAndStencil: + return GL_DEPTH_STENCIL; + } + + return GL_INVALID_ENUM; +} + +static GLenum get_pixel_data_type(Slic3r::GUI::EPixelDataType type) { + switch (type) + { + case Slic3r::GUI::EPixelDataType::UByte: + return GL_UNSIGNED_BYTE; + case Slic3r::GUI::EPixelDataType::Byte: + return GL_BYTE; + case Slic3r::GUI::EPixelDataType::UShort: + return GL_UNSIGNED_SHORT; + case Slic3r::GUI::EPixelDataType::Short: + return GL_SHORT; + case Slic3r::GUI::EPixelDataType::UInt: + return GL_UNSIGNED_INT; + case Slic3r::GUI::EPixelDataType::Int: + return GL_INT; + case Slic3r::GUI::EPixelDataType::Float: + return GL_FLOAT; + } + + return GL_INVALID_ENUM; +} + +static bool version_to_major_minor(const std::string& version, unsigned int& major, unsigned int& minor) +{ + major = 0; + minor = 0; + + if (version == "N/A") + return false; + + std::vector tokens; + boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on); + + if (tokens.empty()) + return false; + + std::vector numbers; + boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); + + if (numbers.size() > 0) + major = ::atoi(numbers[0].c_str()); + + if (numbers.size() > 1) + minor = ::atoi(numbers[1].c_str()); + + return true; +} + namespace Slic3r { namespace GUI { @@ -212,6 +296,9 @@ std::string gl_get_string_safe(GLenum param, const std::string& default_value) return std::string((value != nullptr) ? value : default_value); } +std::string OpenGLManager::s_back_frame = "backframe"; +std::string OpenGLManager::s_picking_frame = "pickingframe"; + const std::string& OpenGLManager::GLInfo::get_version() const { if (!m_detected) @@ -224,11 +311,11 @@ const uint32_t OpenGLManager::GLInfo::get_formated_gl_version() const { if (0 == m_formated_gl_version) { - GLint major = 0; - GLint minor = 0; - glGetIntegerv(GL_MAJOR_VERSION, &major); - glGetIntegerv(GL_MINOR_VERSION, &minor); - + unsigned int major = 0; + unsigned int minor = 0; + if (!m_detected) + detect(); + version_to_major_minor(m_version, major, minor); m_formated_gl_version = major * 10 + minor; } return m_formated_gl_version; @@ -307,26 +394,11 @@ void OpenGLManager::GLInfo::detect() const static bool version_greater_or_equal_to(const std::string& version, unsigned int major, unsigned int minor) { - if (version == "N/A") - return false; - - std::vector tokens; - boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on); - - if (tokens.empty()) - return false; - - std::vector numbers; - boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); - unsigned int gl_major = 0; unsigned int gl_minor = 0; - - if (numbers.size() > 0) - gl_major = ::atoi(numbers[0].c_str()); - - if (numbers.size() > 1) - gl_minor = ::atoi(numbers[1].c_str()); + const bool rt = version_to_major_minor(version, gl_major, gl_minor); + if (!rt) + return false; if (gl_major < major) return false; @@ -416,8 +488,10 @@ OpenGLManager::OpenGLManager() OpenGLManager::~OpenGLManager() { release_vao(); + Slic3r::GUI::GLTexture::shutdown(); m_shaders_manager.shutdown(); - m_name_to_frame_buffer.clear(); + m_name_to_framebuffer.clear(); + #ifdef __APPLE__ // This is an ugly hack needed to solve the crash happening when closing the application on OSX 10.9.5 with newer wxWidgets // The crash is triggered inside wxGLContext destructor @@ -606,6 +680,16 @@ wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas) return m_context; } +void OpenGLManager::bind_shader(const std::shared_ptr& p_shader) +{ + m_shaders_manager.bind_shader(p_shader); +} + +void OpenGLManager::unbind_shader() +{ + m_shaders_manager.unbind_shader(); +} + void OpenGLManager::clear_dirty() { m_b_viewport_dirty = false; @@ -623,6 +707,11 @@ void OpenGLManager::set_viewport_size(uint32_t width, uint32_t height) m_b_viewport_dirty = true; m_viewport_height = height; } + + if (m_b_viewport_dirty) + { + m_name_to_framebuffer.clear(); + } } void OpenGLManager::get_viewport_size(uint32_t& width, uint32_t& height) const @@ -631,37 +720,120 @@ void OpenGLManager::get_viewport_size(uint32_t& width, uint32_t& height) const height = m_viewport_height; } -void OpenGLManager::_bind_frame_buffer(const std::string& name) +void OpenGLManager::_bind_frame_buffer(const std::string& name, EMSAAType msaa_type, uint32_t t_width, uint32_t t_height) { - const auto& iter = m_name_to_frame_buffer.find(name); - if (iter == m_name_to_frame_buffer.end() || m_b_viewport_dirty) { - const auto& p_frame_buffer = std::make_shared(m_viewport_width, m_viewport_height); - m_name_to_frame_buffer.insert_or_assign(name, p_frame_buffer); + if (OpenGLManager::s_back_frame == name) { + const auto current_framebuffer = m_current_binded_framebuffer.lock(); + if (current_framebuffer) { + current_framebuffer->unbind(); + m_current_binded_framebuffer.reset(); + } + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), 0)); + return; + } + const auto& iter = m_name_to_framebuffer.find(name); + if (iter == m_name_to_framebuffer.end()) { + uint32_t width = t_width == 0 ? m_viewport_width : t_width; + uint32_t height = t_height == 0 ? m_viewport_height : t_height; + if (s_picking_frame == name) { + width = 1; + height = 1; + } + const auto& p_frame_buffer = std::make_shared(width, height, msaa_type); + m_name_to_framebuffer.insert_or_assign(name, p_frame_buffer); } - m_name_to_frame_buffer[name]->bind(); + const auto current_framebuffer = m_current_binded_framebuffer.lock(); + if (current_framebuffer != m_name_to_framebuffer[name]) { + if (current_framebuffer) { + current_framebuffer->unbind(); + } + m_name_to_framebuffer[name]->bind(); + m_current_binded_framebuffer = m_name_to_framebuffer[name]; + } } void OpenGLManager::_unbind_frame_buffer(const std::string& name) { - const auto& iter = m_name_to_frame_buffer.find(name); - if (iter == m_name_to_frame_buffer.end()) { + const auto& iter = m_name_to_framebuffer.find(name); + if (iter == m_name_to_framebuffer.end()) { return; } - m_name_to_frame_buffer[name]->unbind(); + m_name_to_framebuffer[name]->unbind(); } const std::shared_ptr& OpenGLManager::get_frame_buffer(const std::string& name) const { - const auto& iter = m_name_to_frame_buffer.find(name); - if (iter != m_name_to_frame_buffer.end()) { + const auto& iter = m_name_to_framebuffer.find(name); + if (iter != m_name_to_framebuffer.end()) { return iter->second; } static std::shared_ptr sEmpty{ nullptr }; return sEmpty; } +void OpenGLManager::set_msaa_type(const std::string& type) +{ + EMSAAType msaa = EMSAAType::Disabled; + if ("X2" == type) { + msaa = EMSAAType::X2; + } + if ("X4" == type) { + msaa = EMSAAType::X4; + } + else if ("X8" == type) { + msaa = EMSAAType::X8; + } + else if ("X16" == type) { + msaa = EMSAAType::X16; + } + + set_msaa_type(msaa); +} + +void OpenGLManager::set_msaa_type(EMSAAType type) +{ + m_msaa_type = type; +} + +EMSAAType OpenGLManager::get_msaa_type() const +{ + return m_msaa_type; +} + +bool OpenGLManager::read_pixel(const std::string& frame_name, uint32_t x, uint32_t y, uint32_t width, uint32_t height, EPixelFormat format, EPixelDataType type, void* pixels) const +{ + std::shared_ptr fb{ nullptr }; + if (frame_name.empty()) { + fb = m_current_binded_framebuffer.lock(); + } + else if (frame_name != s_back_frame) { + const auto& iter = m_name_to_framebuffer.find(frame_name); + if (iter == m_name_to_framebuffer.end()) { + return false; + } + fb = iter->second; + } + + GLenum gl_format = get_pixel_format(format); + GLenum gl_type = get_pixel_data_type(type); + + if (fb) { + fb->read_pixel(x, y, width, height, format, type, pixels); + } + else { + glsafe(::glReadPixels(x, y, width, height, gl_format, gl_type, pixels)); + } + + const auto current_fb = m_current_binded_framebuffer.lock(); + if (current_fb) { + current_fb->bind(); + } + + return true; +} + void OpenGLManager::bind_vao() { if (m_vao_type != EVAOType::Unknown) { @@ -702,7 +874,7 @@ void OpenGLManager::unbind_vao() void OpenGLManager::release_vao() { - if (0 != m_vao) { + if (0 == m_vao) { return; } if (m_vao_type != EVAOType::Unknown) { @@ -720,6 +892,75 @@ void OpenGLManager::release_vao() } } +void OpenGLManager::set_off_screen_msaa_type(EMSAAType type) +{ + m_off_screen_msaa_type = type; +} + +EMSAAType OpenGLManager::get_off_screen_msaa_type() +{ + return m_off_screen_msaa_type; +} + +void OpenGLManager::set_fxaa_enabled(bool is_enabled) +{ + m_fxaa_enabled = is_enabled; +} + +bool OpenGLManager::is_fxaa_enabled() const +{ + return m_fxaa_enabled; +} + +void OpenGLManager::blit_framebuffer(const std::string& source, const std::string& target) +{ + if (source == target) { + return; + } + if (s_back_frame == source) { + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_READ_FRAMEBUFFER), 0)); + } + else + { + const auto& iter = m_name_to_framebuffer.find(source); + if (iter == m_name_to_framebuffer.end()) { + return; + } + const uint32_t source_id = iter->second->get_gl_id(); + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_READ_FRAMEBUFFER), source_id)); + } + + if (s_back_frame == target) { + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_DRAW_FRAMEBUFFER), 0)); + } + else + { + const auto& iter = m_name_to_framebuffer.find(target); + if (iter == m_name_to_framebuffer.end()) { + return; + } + const uint32_t target_id = iter->second->get_gl_id(); + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_DRAW_FRAMEBUFFER), target_id)); + } + + glsafe(::glBlitFramebuffer(0, 0, m_viewport_width, m_viewport_height, 0, 0, m_viewport_width, m_viewport_height, GL_COLOR_BUFFER_BIT, GL_LINEAR)); +} + +void OpenGLManager::set_line_width(float width) const +{ + const auto formated_gl_version = s_gl_info.get_formated_gl_version(); + if (formated_gl_version < 30) { + glsafe(::glLineWidth(width)); + } + else { +#ifdef __APPLE__ + glsafe(::glLineWidth(1.0f)); +#else + glsafe(::glLineWidth(width)); +#endif + } +} + std::string OpenGLManager::framebuffer_type_to_string(EFramebufferType type) { switch (type) @@ -736,8 +977,9 @@ std::string OpenGLManager::framebuffer_type_to_string(EFramebufferType type) } } -wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) +wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent, EMSAAType msaa_type) { + const uint8_t msaa_samples = get_msaa_samples(msaa_type); int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, @@ -751,8 +993,11 @@ wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) WX_GL_DEPTH_SIZE, 24, //BBS: turn on stencil buffer for outline WX_GL_STENCIL_SIZE, 8, - WX_GL_SAMPLE_BUFFERS, GL_TRUE, - WX_GL_SAMPLES, 4, + WX_GL_SAMPLE_BUFFERS, msaa_samples > 0 ? GL_TRUE : GL_FALSE, + WX_GL_SAMPLES, msaa_samples, +#ifndef __APPLE__ + WX_GL_CORE_PROFILE, +#endif 0 }; @@ -783,9 +1028,10 @@ void OpenGLManager::detect_multisample(int* attribList) // s_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample"); } -FrameBuffer::FrameBuffer(uint32_t width, uint32_t height) +FrameBuffer::FrameBuffer(uint32_t width, uint32_t height, EMSAAType msaa_type) : m_width(width) , m_height(height) + , m_msaa_type(msaa_type) { } @@ -793,8 +1039,7 @@ FrameBuffer::~FrameBuffer() { if (UINT32_MAX != m_gl_id) { - //glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, 0)); - glsafe(::glDeleteFramebuffers(1, &m_gl_id)); + glsafe(BBS_GL_EXTENSION_FUNC(::glDeleteFramebuffers)(1, &m_gl_id)); m_gl_id = UINT32_MAX; } @@ -806,9 +1051,19 @@ FrameBuffer::~FrameBuffer() if (UINT32_MAX != m_depth_rbo_id) { - glDeleteRenderbuffers(1, &m_depth_rbo_id); + glsafe(BBS_GL_EXTENSION_FUNC(::glDeleteRenderbuffers)(1, &m_depth_rbo_id)); m_depth_rbo_id = UINT32_MAX; } + + if (UINT32_MAX != m_gl_id_for_back_fbo) + { + glsafe(BBS_GL_EXTENSION_FUNC(::glDeleteFramebuffers)(1, &m_gl_id_for_back_fbo)); + m_gl_id_for_back_fbo = UINT32_MAX; + + glsafe(BBS_GL_EXTENSION_FUNC(::glDeleteRenderbuffers)(2, m_msaa_back_buffer_rbos)); + m_msaa_back_buffer_rbos[0] = UINT32_MAX; + m_msaa_back_buffer_rbos[1] = UINT32_MAX; + } } void FrameBuffer::bind() @@ -823,19 +1078,14 @@ void FrameBuffer::bind() } if (UINT32_MAX == m_gl_id) { - glsafe(BBS_GL_EXTENSION_FUNC(::glGenFramebuffers)(1, &m_gl_id)); - - glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_FRAMEBUFFER, m_gl_id)); - - glsafe(::glGenTextures(1, &m_color_texture_id)); - glsafe(::glBindTexture(GL_TEXTURE_2D, m_color_texture_id)); - - glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr)); - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - - glsafe(BBS_GL_EXTENSION_FUNC(::glFramebufferTexture2D)(BBS_GL_EXTENSION_FRAMEBUFFER, BBS_GL_EXTENSION_COLOR_ATTACHMENT(GL_COLOR_ATTACHMENT0), GL_TEXTURE_2D, m_color_texture_id, 0)); - + if (EMSAAType::Disabled == m_msaa_type) + { + create_no_msaa_fbo(true); + } + else + { + create_msaa_fbo(); + } if (OpenGLManager::EFramebufferType::Ext == framebuffer_type) { GLenum bufs[1]{ GL_COLOR_ATTACHMENT0_EXT }; glsafe(::glDrawBuffers((GLsizei)1, bufs)); @@ -844,34 +1094,15 @@ void FrameBuffer::bind() GLenum bufs[1]{ GL_COLOR_ATTACHMENT0 }; glsafe(::glDrawBuffers((GLsizei)1, bufs)); } - - glsafe(BBS_GL_EXTENSION_FUNC(::glGenRenderbuffers)(1, &m_depth_rbo_id)); - glsafe(BBS_GL_EXTENSION_FUNC(::glBindRenderbuffer)(BBS_GL_EXTENSION_RENDER_BUFFER, m_depth_rbo_id)); - - glsafe(BBS_GL_EXTENSION_FUNC(::glRenderbufferStorage)(BBS_GL_EXTENSION_RENDER_BUFFER, GL_DEPTH24_STENCIL8, m_width, m_height)); - - glsafe(BBS_GL_EXTENSION_FUNC(::glFramebufferRenderbuffer)(BBS_GL_EXTENSION_FRAMEBUFFER, BBS_GL_EXTENSION_DEPTH_ATTACHMENT, BBS_GL_EXTENSION_RENDER_BUFFER, m_depth_rbo_id)); - - if (OpenGLManager::EFramebufferType::Ext == framebuffer_type) { - if (::glCheckFramebufferStatusEXT(BBS_GL_EXTENSION_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE_EXT) - { - BOOST_LOG_TRIVIAL(error) << "Framebuffer is not complete!"; - glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_FRAMEBUFFER, 0)); - return; - } - } - else { - if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - BOOST_LOG_TRIVIAL(error) << "Framebuffer is not complete!"; - glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_FRAMEBUFFER, 0)); - return; - } + const bool rt = check_frame_buffer_status(); + if (!rt) + { + return; } BOOST_LOG_TRIVIAL(trace) << "Successfully created framebuffer: width = " << m_width << ", heihgt = " << m_height; } - - glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_FRAMEBUFFER, m_gl_id)); + m_needs_to_solve = (m_gl_id_for_back_fbo != UINT32_MAX); + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), (UINT32_MAX == m_gl_id_for_back_fbo ? m_gl_id : m_gl_id_for_back_fbo))); } void FrameBuffer::unbind() @@ -880,7 +1111,10 @@ void FrameBuffer::unbind() if (OpenGLManager::EFramebufferType::Unknown == framebuffer_type) { return; } - glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_FRAMEBUFFER, 0)); + + resolve(); + + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), 0)); } uint32_t FrameBuffer::get_color_texture() const noexcept @@ -893,16 +1127,191 @@ bool FrameBuffer::is_texture_valid(uint32_t texture_id) const noexcept return m_color_texture_id != UINT32_MAX; } -OpenGLManager::FrameBufferModifier::FrameBufferModifier(OpenGLManager& ogl_manager, const std::string& frame_buffer_name) +uint32_t FrameBuffer::get_gl_id() +{ + resolve(); + return m_gl_id; +} + +void FrameBuffer::read_pixel(uint32_t x, uint32_t y, uint32_t width, uint32_t height, EPixelFormat format, EPixelDataType type, void* pixels) +{ + const GLenum gl_format = get_pixel_format(format); + const GLenum gl_type = get_pixel_data_type(type); + + if (UINT32_MAX != m_gl_id_for_back_fbo) { + EBlitOptionType old_blit_type = m_blit_option_type; + if (EPixelFormat::DepthComponent == format) { + m_blit_option_type = EBlitOptionType::Depth; + } + unbind(); + m_blit_option_type = old_blit_type; + } + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), m_gl_id)); + glsafe(::glReadPixels(x, y, width, height, gl_format, gl_type, pixels)); + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), 0)); +} + +void FrameBuffer::create_no_msaa_fbo(bool with_depth) +{ + const OpenGLManager::EFramebufferType framebuffer_type = OpenGLManager::get_framebuffers_type(); + + glsafe(BBS_GL_EXTENSION_FUNC(::glGenFramebuffers)(1, &m_gl_id)); + + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), m_gl_id)); + + glsafe(::glGenTextures(1, &m_color_texture_id)); + glsafe(::glBindTexture(GL_TEXTURE_2D, m_color_texture_id)); + + glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + + glsafe(BBS_GL_EXTENSION_FUNC(::glFramebufferTexture2D)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), BBS_GL_EXTENSION_PARAMETER(GL_COLOR_ATTACHMENT0), GL_TEXTURE_2D, m_color_texture_id, 0)); + + if (with_depth) + { + glsafe(BBS_GL_EXTENSION_FUNC(::glGenRenderbuffers)(1, &m_depth_rbo_id)); + glsafe(BBS_GL_EXTENSION_FUNC(::glBindRenderbuffer)(BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), m_depth_rbo_id)); + + glsafe(BBS_GL_EXTENSION_FUNC(::glRenderbufferStorage)(BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), GL_DEPTH24_STENCIL8, m_width, m_height)); + + const auto& gl_info = OpenGLManager::get_gl_info(); + uint32_t formated_gl_version = gl_info.get_formated_gl_version(); + if (formated_gl_version < 30) + { + glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depth_rbo_id)); + glsafe(::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depth_rbo_id)); + } + else + { + glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depth_rbo_id)); + } + } +} + +void FrameBuffer::create_msaa_fbo() +{ + glsafe(BBS_GL_EXTENSION_FUNC(::glGenFramebuffers)(1, &m_gl_id_for_back_fbo)); + + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), m_gl_id_for_back_fbo)); + + uint8_t num_samples = get_msaa_samples(m_msaa_type); + // use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2 + glsafe(BBS_GL_EXTENSION_FUNC(::glGenRenderbuffers)(2, m_msaa_back_buffer_rbos)); + + glsafe(BBS_GL_EXTENSION_FUNC(::glBindRenderbuffer)(BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), m_msaa_back_buffer_rbos[0])); + glsafe(BBS_GL_EXTENSION_FUNC(::glRenderbufferStorageMultisample)(BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), num_samples, GL_RGBA8, m_width, m_height)); + + glsafe(BBS_GL_EXTENSION_FUNC(::glBindRenderbuffer)(BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), m_msaa_back_buffer_rbos[1])); + glsafe(::glRenderbufferStorageMultisample(BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), num_samples, GL_DEPTH24_STENCIL8, m_width, m_height)); + + glsafe(BBS_GL_EXTENSION_FUNC(::glFramebufferRenderbuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), BBS_GL_EXTENSION_PARAMETER(GL_COLOR_ATTACHMENT0), BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), m_msaa_back_buffer_rbos[0])); + + const auto& gl_info = OpenGLManager::get_gl_info(); + if (gl_info.is_version_greater_or_equal_to(3, 0)) { + glsafe(::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_msaa_back_buffer_rbos[1])); + } + else { + glsafe(BBS_GL_EXTENSION_FUNC(::glFramebufferRenderbuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), BBS_GL_EXTENSION_PARAMETER(GL_DEPTH_ATTACHMENT), BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), m_msaa_back_buffer_rbos[1])); + glsafe(BBS_GL_EXTENSION_FUNC(::glFramebufferRenderbuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), BBS_GL_EXTENSION_PARAMETER(GL_STENCIL_ATTACHMENT), BBS_GL_EXTENSION_PARAMETER(GL_RENDERBUFFER), m_msaa_back_buffer_rbos[1])); + } +} + +bool FrameBuffer::check_frame_buffer_status() const +{ + const OpenGLManager::EFramebufferType framebuffer_type = OpenGLManager::get_framebuffers_type(); + + if (OpenGLManager::EFramebufferType::Ext == framebuffer_type) { + if (::glCheckFramebufferStatusEXT(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE_EXT) + { + BOOST_LOG_TRIVIAL(error) << "Framebuffer is not complete!"; + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), 0)); + return false; + } + } + else { + if (::glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + { + BOOST_LOG_TRIVIAL(error) << "Framebuffer is not complete!"; + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), 0)); + return false; + } + } + + return true; +} + +void FrameBuffer::resolve() +{ + + if (!m_needs_to_solve) { + return; + } + + if (UINT32_MAX == m_gl_id_for_back_fbo) { + return; + } + + if (UINT32_MAX == m_gl_id) { + create_no_msaa_fbo(true); + + const OpenGLManager::EFramebufferType framebuffer_type = OpenGLManager::get_framebuffers_type(); + if (OpenGLManager::EFramebufferType::Ext == framebuffer_type) + { + GLenum bufs[1]{ GL_COLOR_ATTACHMENT0_EXT }; + glsafe(::glDrawBuffers((GLsizei)1, bufs)); + } + else + { + GLenum bufs[1]{ GL_COLOR_ATTACHMENT0 }; + glsafe(::glDrawBuffers((GLsizei)1, bufs)); + } + + const bool rt = check_frame_buffer_status(); + if (!rt) + { + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_FRAMEBUFFER), 0)); + } + } + + glsafe(::glDisable(GL_SCISSOR_TEST)); + + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_READ_FRAMEBUFFER), m_gl_id_for_back_fbo)); + glsafe(BBS_GL_EXTENSION_FUNC(::glBindFramebuffer)(BBS_GL_EXTENSION_PARAMETER(GL_DRAW_FRAMEBUFFER), m_gl_id)); + + if (EBlitOptionType::Color & m_blit_option_type) { + glsafe(::glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST)); + } + + if (EBlitOptionType::Depth & m_blit_option_type) { + glsafe(::glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_DEPTH_BUFFER_BIT, GL_NEAREST)); + } + + m_needs_to_solve = false; +} + +OpenGLManager::FrameBufferModifier::FrameBufferModifier(OpenGLManager& ogl_manager, const std::string& frame_buffer_name, EMSAAType msaa_type) : m_ogl_manager(ogl_manager) , m_frame_buffer_name(frame_buffer_name) + , m_msaa_type(msaa_type) { - m_ogl_manager._bind_frame_buffer(m_frame_buffer_name); } OpenGLManager::FrameBufferModifier::~FrameBufferModifier() { - m_ogl_manager._unbind_frame_buffer(m_frame_buffer_name); + m_ogl_manager._bind_frame_buffer(m_frame_buffer_name, m_msaa_type, m_width, m_height); +} + +OpenGLManager::FrameBufferModifier& OpenGLManager::FrameBufferModifier::set_width(uint32_t t_width) +{ + m_width = t_width; + return *this; +} + +OpenGLManager::FrameBufferModifier& OpenGLManager::FrameBufferModifier::set_height(uint32_t t_height) +{ + m_height = t_height; + return *this; } } // namespace GUI diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index e5c0d3a70..4c85c9cbf 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -13,10 +13,40 @@ class wxGLContext; namespace Slic3r { namespace GUI { +enum class EMSAAType : uint8_t +{ + Disabled, + X2, + X4, + // desktop only + X8, + X16 +}; + +enum class EPixelFormat : uint16_t +{ + Unknow, + RGBA, + DepthComponent, + StencilIndex, + DepthAndStencil +}; + +enum class EPixelDataType : uint16_t +{ + Unknow, + UByte, + Byte, + UShort, + Short, + UInt, + Int, + Float +}; struct FrameBuffer { - FrameBuffer(uint32_t width, uint32_t height); + FrameBuffer(uint32_t width, uint32_t height, EMSAAType msaa_type); ~FrameBuffer(); void bind(); @@ -26,16 +56,41 @@ struct FrameBuffer bool is_texture_valid(uint32_t texture_id) const noexcept; + uint32_t get_gl_id(); + + void read_pixel(uint32_t x, uint32_t y, uint32_t width, uint32_t height, EPixelFormat format, EPixelDataType type, void* pixels); + +private: + enum EBlitOptionType + { + Color = 1, + Depth = 1 << 1, + All = Color | Depth + }; + +private: + void create_no_msaa_fbo(bool with_depth); + void create_msaa_fbo(); + bool check_frame_buffer_status() const; + void resolve(); private: uint32_t m_width{ 0 }; uint32_t m_height{ 0 }; + EMSAAType m_msaa_type{ EMSAAType::Disabled }; + uint32_t m_msaa_back_buffer_rbos[2]{ UINT32_MAX, UINT32_MAX }; + uint32_t m_gl_id_for_back_fbo{ UINT32_MAX }; uint32_t m_gl_id{ UINT32_MAX }; uint32_t m_color_texture_id{ UINT32_MAX }; uint32_t m_depth_rbo_id{ UINT32_MAX }; + bool m_needs_to_solve{ false }; + EBlitOptionType m_blit_option_type{ EBlitOptionType::Color }; }; class OpenGLManager { +public: + static std::string s_back_frame; + static std::string s_picking_frame; public: enum class EFramebufferType : unsigned char { @@ -92,8 +147,10 @@ public: class FrameBufferModifier { public: - explicit FrameBufferModifier(OpenGLManager& ogl_manager, const std::string& frame_buffer_name); + explicit FrameBufferModifier(OpenGLManager& ogl_manager, const std::string& frame_buffer_name, EMSAAType msaa_type = EMSAAType::Disabled); ~FrameBufferModifier(); + FrameBufferModifier& set_width(uint32_t t_width); + FrameBufferModifier& set_height(uint32_t t_height); private: // no copy @@ -107,6 +164,9 @@ public: private: OpenGLManager& m_ogl_manager; std::string m_frame_buffer_name{}; + EMSAAType m_msaa_type{ EMSAAType::Disabled }; + uint32_t m_width{ 0u }; + uint32_t m_height{ 0u }; }; #ifdef __APPLE__ @@ -133,7 +193,11 @@ private: uint32_t m_viewport_width{ 0 }; uint32_t m_viewport_height{ 0 }; bool m_b_viewport_dirty{ true }; - std::unordered_map> m_name_to_frame_buffer; + std::unordered_map> m_name_to_framebuffer; + std::weak_ptr m_current_binded_framebuffer; + bool m_fxaa_enabled{ false }; + EMSAAType m_off_screen_msaa_type{ EMSAAType::X4 }; + EMSAAType m_msaa_type{ EMSAAType::X4 }; EVAOType m_vao_type{ EVAOType::Unknown }; uint32_t m_vao{ 0 }; static GLInfo s_gl_info; @@ -145,7 +209,6 @@ private: static bool s_compressed_textures_supported; static EMultisampleState s_multisample; static EFramebufferType s_framebuffers_type; - static bool m_use_manually_generated_mipmaps; public: OpenGLManager(); @@ -154,31 +217,44 @@ public: bool init_gl(bool popup_error = true); wxGLContext* init_glcontext(wxGLCanvas& canvas); - GLShaderProgram* get_shader(const std::string& shader_name) { return m_shaders_manager.get_shader(shader_name); } - GLShaderProgram* get_current_shader() { return m_shaders_manager.get_current_shader(); } + const std::shared_ptr& get_shader(const std::string& shader_name) const { return m_shaders_manager.get_shader(shader_name); } + std::shared_ptr get_current_shader() const { return m_shaders_manager.get_current_shader(); } + void bind_shader(const std::shared_ptr&); + void unbind_shader(); void clear_dirty(); void set_viewport_size(uint32_t width, uint32_t height); void get_viewport_size(uint32_t& width, uint32_t& height) const; const std::shared_ptr& get_frame_buffer(const std::string& name) const; + bool read_pixel(const std::string& frame_name, uint32_t x, uint32_t y, uint32_t width, uint32_t height, EPixelFormat format, EPixelDataType type, void* pixels) const; void bind_vao(); void unbind_vao(); void release_vao(); + void set_line_width(float width) const; + + void set_msaa_type(const std::string& type); + void set_msaa_type(EMSAAType type); + EMSAAType get_msaa_type() const; + void set_off_screen_msaa_type(EMSAAType type); + EMSAAType get_off_screen_msaa_type(); + void set_fxaa_enabled(bool is_enabled); + bool is_fxaa_enabled() const; + void blit_framebuffer(const std::string& source, const std::string& target); static bool init(bool prefer_to_use_dgpu = false); + static bool are_compressed_textures_supported() { return s_compressed_textures_supported; } static bool can_multisample() { return s_multisample == EMultisampleState::Enabled; } static bool are_framebuffers_supported() { return (s_framebuffers_type != EFramebufferType::Unknown); } static EFramebufferType get_framebuffers_type() { return s_framebuffers_type; } static std::string framebuffer_type_to_string(EFramebufferType type); - static wxGLCanvas* create_wxglcanvas(wxWindow& parent); + static wxGLCanvas* create_wxglcanvas(wxWindow& parent, EMSAAType msaa_type = EMSAAType::Disabled); static const GLInfo& get_gl_info() { return s_gl_info; } static bool use_manually_generated_mipmaps() { return m_use_manually_generated_mipmaps; } - private: static void detect_multisample(int* attribList); - void _bind_frame_buffer(const std::string& name); + void _bind_frame_buffer(const std::string& name, EMSAAType msaa_type, uint32_t t_width = 0, uint32_t t_height = 0); void _unbind_frame_buffer(const std::string& name); }; diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 3db3792a9..627c1915a 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -670,18 +670,19 @@ void PartPlate::render_height_limit(PartPlate::HeightLimitMode mode) if (m_print && m_print->config().print_sequence == PrintSequence::ByObject && mode != HEIGHT_LIMIT_NONE) { // draw lower limit - glsafe(::glLineWidth(3.0f * m_scale_factor)); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(3.0f * m_scale_factor); m_height_limit_common.set_color(HEIGHT_LIMIT_BOTTOM_COLOR); m_height_limit_common.render_geometry(); if ((mode == HEIGHT_LIMIT_BOTTOM) || (mode == HEIGHT_LIMIT_BOTH)) { - glsafe(::glLineWidth(3.0f * m_scale_factor)); + p_ogl_manager->set_line_width(3.0f * m_scale_factor); m_height_limit_bottom.set_color(HEIGHT_LIMIT_BOTTOM_COLOR); m_height_limit_bottom.render_geometry(); } // draw upper limit if ((mode == HEIGHT_LIMIT_TOP) || (mode == HEIGHT_LIMIT_BOTH)){ - glsafe(::glLineWidth(3.0f * m_scale_factor)); + p_ogl_manager->set_line_width(3.0f * m_scale_factor); m_height_limit_top.set_color(HEIGHT_LIMIT_TOP_COLOR); m_height_limit_top.render_geometry(); } @@ -1008,12 +1009,12 @@ void PartPlate::render_right_arrow(const float* render_color, bool use_lighting) void PartPlate::on_render_for_picking() { //glsafe(::glDisable(GL_DEPTH_TEST)); - const Camera &camera = wxGetApp().plater()->get_camera(); + const Camera &camera = wxGetApp().plater()->get_picking_camera(); auto view_mat = camera.get_view_matrix(); auto proj_mat = camera.get_projection_matrix(); - GLShaderProgram *shader = wxGetApp().get_shader("flat"); - shader->start_using(); + const auto& shader = wxGetApp().get_shader("flat"); + wxGetApp().bind_shader(shader); auto model_mat = m_partplate_list->m_plate_trans[m_plate_index].get_matrix(); shader->set_uniform("view_model_matrix", view_mat * model_mat); shader->set_uniform("projection_matrix", proj_mat); @@ -1023,14 +1024,17 @@ void PartPlate::on_render_for_picking() { &m_partplate_list->m_plate_filament_map_icon, &m_plate_name_edit_icon}; for (size_t i = 0; i < gl_models.size(); i++) { if (!gl_models[i]->get_visible()) { + continue; + } + if (!camera.getFrustum().intersects(gl_models[i]->get_bounding_box().transformed(model_mat))) { continue; } int hover_id = i; std::array color = picking_color_component(hover_id); gl_models[i]->set_color(-1, color); gl_models[i]->render_geometry(); - } - shader->stop_using(); + } + wxGetApp().unbind_shader(); } std::array PartPlate::picking_color_component(int idx) const @@ -2588,17 +2592,17 @@ void PartPlate::render(bool bottom, bool only_body, bool force_background_color, auto view_mat = camera.get_view_matrix(); auto proj_mat = camera.get_projection_matrix(); { - GLShaderProgram *shader = wxGetApp().get_shader("flat"); - shader->start_using(); + const auto& shader = wxGetApp().get_shader("flat"); + wxGetApp().bind_shader(shader); shader->set_uniform("view_model_matrix", view_mat); shader->set_uniform("projection_matrix", proj_mat); render_height_limit(mode); - shader->stop_using(); + wxGetApp().unbind_shader(); } { - GLShaderProgram *shader = wxGetApp().get_shader("printbed"); - shader->start_using(); + const auto& shader = wxGetApp().get_shader("printbed"); + wxGetApp().bind_shader(shader); auto model_mat = m_partplate_list->m_plate_trans[m_plate_index].get_matrix(); shader->set_uniform("view_model_matrix", view_mat * model_mat); shader->set_uniform("projection_matrix", proj_mat); @@ -2617,7 +2621,7 @@ void PartPlate::render(bool bottom, bool only_body, bool force_background_color, render_numbers(bottom); } } - shader->stop_using(); + wxGetApp().unbind_shader(); } } @@ -5082,13 +5086,13 @@ void PartPlateList::render_instance(bool bottom, bool only_current, bool only_bo auto view_mat = camera.get_view_matrix(); auto proj_mat = camera.get_projection_matrix(); { - auto cur_shader = wxGetApp().get_current_shader(); - if (cur_shader) { - cur_shader->stop_using(); - } - GLShaderProgram *shader = wxGetApp().get_shader("flat"); + const auto cur_shader = wxGetApp().get_current_shader(); + if (cur_shader) { + wxGetApp().unbind_shader(); + } + const auto& shader = wxGetApp().get_shader("flat"); {//for selected - shader->start_using(); + wxGetApp().bind_shader(shader); shader->set_uniform("view_model_matrix", view_mat * m_plate_trans[m_current_plate].get_matrix()); shader->set_uniform("projection_matrix", proj_mat); if (!bottom) { // draw background @@ -5098,12 +5102,12 @@ void PartPlateList::render_instance(bool bottom, bool only_current, bool only_bo render_grid(bottom); // for selected_plate } if (enable_multi_instance) { - shader->stop_using(); + wxGetApp().unbind_shader(); } if (!only_current) { if (enable_multi_instance) { - GLShaderProgram *shader = wxGetApp().get_shader("flat_instance"); - shader->start_using(); + const auto& shader = wxGetApp().get_shader("flat_instance"); + wxGetApp().bind_shader(shader); auto res = shader->set_uniform("view_matrix", view_mat); res = shader->set_uniform("projection_matrix", proj_mat); if (!bottom) { // draw background @@ -5112,7 +5116,7 @@ void PartPlateList::render_instance(bool bottom, bool only_current, bool only_bo } render_instance_grid(bottom); // for unselected_plate - shader->stop_using(); + wxGetApp().unbind_shader(); } else { for (size_t i = 0; i < m_unselected_plate_trans.size(); i++) { @@ -5126,17 +5130,21 @@ void PartPlateList::render_instance(bool bottom, bool only_current, bool only_bo } } if (!enable_multi_instance) { - shader->stop_using(); + wxGetApp().unbind_shader(); + } + + if (cur_shader) { + wxGetApp().bind_shader(cur_shader); } } - } void PartPlateList::render_grid(bool bottom) { + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); // glsafe(::glEnable(GL_MULTISAMPLE)); // draw grid - glsafe(::glLineWidth(1.0f * m_scale_factor)); + p_ogl_manager->set_line_width(1.0f * m_scale_factor); ColorRGBA color; if (bottom) color = PartPlate::LINE_BOTTOM_COLOR; @@ -5146,7 +5154,7 @@ void PartPlateList::render_grid(bool bottom) m_gridlines.set_color(color); m_gridlines.render_geometry(); - glsafe(::glLineWidth(2.0f * m_scale_factor)); + p_ogl_manager->set_line_width(2.0f * m_scale_factor); m_gridlines_bolder.set_color(color); m_gridlines_bolder.render_geometry(); } @@ -5155,7 +5163,8 @@ void PartPlateList::render_instance_grid(bool bottom) { // draw grid if (m_unselected_plate_trans.size() == 0) { return; } - glsafe(::glLineWidth(1.0f * m_scale_factor)); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(1.0f * m_scale_factor); ColorRGBA color; if (bottom) color = PartPlate::LINE_BOTTOM_COLOR; @@ -5164,14 +5173,15 @@ void PartPlateList::render_instance_grid(bool bottom) } m_gridlines.set_color(color); m_gridlines.render_geometry_instance(m_unselected_plate_mats_vbo, m_unselected_plate_trans.size()); - glsafe(::glLineWidth(2.0f * m_scale_factor)); + p_ogl_manager->set_line_width(2.0f * m_scale_factor); m_gridlines_bolder.set_color(color); m_gridlines_bolder.render_geometry_instance(m_unselected_plate_mats_vbo, m_unselected_plate_trans.size()); } void PartPlateList::render_unselected_grid(bool bottom) { - glsafe(::glLineWidth(1.0f * m_scale_factor)); + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + p_ogl_manager->set_line_width(1.0f * m_scale_factor); ColorRGBA color; if (bottom) color = PartPlate::LINE_BOTTOM_COLOR; @@ -5180,7 +5190,7 @@ void PartPlateList::render_unselected_grid(bool bottom) } m_gridlines.set_color(color); m_gridlines.render_geometry(); - glsafe(::glLineWidth(2.0f * m_scale_factor)); + p_ogl_manager->set_line_width(2.0f * m_scale_factor); m_gridlines_bolder.set_color(color); m_gridlines_bolder.render_geometry(); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 515ad6880..3df14927d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3648,6 +3648,7 @@ struct Plater::priv Bed3D bed; Camera camera; + Camera picking_camera; //BBS: partplate related structure PartPlateList partplate_list; //BBS: add a flag to ignore cancel event @@ -15779,6 +15780,16 @@ Camera& Plater::get_camera() return p->camera; } +const Camera& Plater::get_picking_camera() const +{ + return p->picking_camera; +} + +Camera& Plater::get_picking_camera() +{ + return p->picking_camera; +} + //BBS: partplate list related functions PartPlateList& Plater::get_partplate_list() { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 5ee862917..38a90bcf0 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -634,6 +634,8 @@ public: const Camera& get_camera() const; Camera& get_camera(); + const Camera& get_picking_camera() const; + Camera& get_picking_camera(); //BBS: partplate list related functions PartPlateList& get_partplate_list(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 3d7eca3b8..f47c4d7ec 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -9,6 +9,7 @@ #include "Gizmos/GLGizmoBase.hpp" #include "Camera.hpp" #include "Plater.hpp" +#include "OpenGLManager.hpp" #include "slic3r/Utils/UndoRedo.hpp" #include "libslic3r/LocalesUtils.hpp" @@ -137,7 +138,7 @@ bool Selection::init() m_curved_arrow.init_from(circular_arrow(16, 10.0f, 5.0f, 10.0f, 5.0f, 1.0f)); #if ENABLE_RENDER_SELECTION_CENTER - m_vbo_sphere.init_from(make_sphere(0.75, 2*PI/24)); + m_vbo_sphere.init_from(its_make_sphere(0.75, 2*PI/24)); #endif // ENABLE_RENDER_SELECTION_CENTER return true; @@ -1986,15 +1987,26 @@ void Selection::render_center(bool gizmo_is_dragging) const if (!m_valid || is_empty()) return; + const auto& shader = wxGetApp().get_shader("flat"); + if (!shader) + return; + + wxGetApp().bind_shader(shader); + const Vec3d center = gizmo_is_dragging ? m_cache.dragging_center : get_bounding_box().center(); glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glColor3f(1.0f, 1.0f, 1.0f)); - glsafe(::glPushMatrix()); - glsafe(::glTranslated(center(0), center(1), center(2))); - m_vbo_sphere.render(); - glsafe(::glPopMatrix()); + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(center); + + shader->set_uniform("view_model_matrix", view_model_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + + m_vbo_sphere.set_color(ColorRGBA::WHITE()); + m_vbo_sphere.render_geometry(); + + wxGetApp().unbind_shader(); } #endif // ENABLE_RENDER_SELECTION_CENTER @@ -2005,30 +2017,25 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif if (sidebar_field.empty()) return; - GLShaderProgram* shader = nullptr; + const auto& shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light"); + if (shader == nullptr) + return; + + wxGetApp().bind_shader(shader); if (!boost::starts_with(sidebar_field, "layer")) { - shader = wxGetApp().get_shader("gouraud_light"); - if (shader == nullptr) - return; - - shader->start_using(); glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); } - glsafe(::glEnable(GL_DEPTH_TEST)); - glsafe(::glPushMatrix()); + Transform3d base_matrix = Geometry::assemble_transform(get_bounding_box().center()); Transform3d orient_matrix = Transform3d::Identity(); if (!boost::starts_with(sidebar_field, "layer")) { Vec3d center = get_bounding_box().center(); const auto &[box, box_trafo] = get_bounding_box_in_current_reference_system(); // BBS if (is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) { - center = box_trafo.translation(); - glsafe(::glTranslated(center(0), center(1), center(2))); orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix(); - glsafe(::glMultMatrixd(orient_matrix.data())); } else if (is_single_volume_or_modifier()) { if (!wxGetApp().obj_manipul()->is_world_coordinates()) { if (wxGetApp().obj_manipul()->is_local_coordinates()) { @@ -2039,33 +2046,27 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif center = box_trafo.translation(); } } - glsafe(::glTranslated(center(0), center(1), center(2))); - glsafe(::glMultMatrixd(orient_matrix.data())); + base_matrix = Geometry::assemble_transform({ center(0), center(1), center(2) }); } else { - glsafe(::glTranslated(center(0), center(1), center(2))); if (requires_local_axes()) { orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix(); - glsafe(::glMultMatrixd(orient_matrix.data())); } } } if (boost::starts_with(sidebar_field, "position")) - render_sidebar_position_hints(sidebar_field); + render_sidebar_position_hints(sidebar_field, *shader, base_matrix * orient_matrix); else if (boost::starts_with(sidebar_field, "rotation")) - render_sidebar_rotation_hints(sidebar_field); + render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix); else if (boost::starts_with(sidebar_field, "absolute_rotation")) - render_sidebar_rotation_hints(sidebar_field); + render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix); else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size")) //BBS: GUI refactor: add uniform_scale from gizmo - render_sidebar_scale_hints(sidebar_field, uniform_scale); + render_sidebar_scale_hints(sidebar_field, uniform_scale, *shader, base_matrix * orient_matrix); else if (boost::starts_with(sidebar_field, "layer")) - render_sidebar_layers_hints(sidebar_field); + render_sidebar_layers_hints(*shader, sidebar_field); - glsafe(::glPopMatrix()); - - if (!boost::starts_with(sidebar_field, "layer")) - shader->stop_using(); + wxGetApp().unbind_shader(); } bool Selection::requires_local_axes() const @@ -2583,50 +2584,42 @@ void Selection::render_bounding_box(const BoundingBoxf3& box, float* color) cons if (color == nullptr) return; + const auto& p_ogl_manager = wxGetApp().get_opengl_manager(); + const auto& p_flat_shader = wxGetApp().get_shader("flat"); + if (!p_flat_shader) + return; + + init_bounding_box_model(); + Vec3f b_min = box.min.cast(); Vec3f b_max = box.max.cast(); - Vec3f size = 0.2f * box.size().cast(); + Vec3f size = box.size().cast(); + const auto& center = box.center(); + + Transform3d model_matrix{ Transform3d::Identity() }; + model_matrix.data()[3 * 4 + 0] = center(0); + model_matrix.data()[3 * 4 + 1] = center(1); + model_matrix.data()[3 * 4 + 2] = center(2); + model_matrix.data()[0 * 4 + 0] = size(0); + model_matrix.data()[1 * 4 + 1] = size(1); + model_matrix.data()[2 * 4 + 2] = size(2); glsafe(::glEnable(GL_DEPTH_TEST)); - glsafe(::glColor3fv(color)); - glsafe(::glLineWidth(2.0f * m_scale_factor)); + p_ogl_manager->set_line_width(2.0f * m_scale_factor); - ::glBegin(GL_LINES); + wxGetApp().bind_shader(p_flat_shader); - ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0) + size(0), b_min(1), b_min(2)); - ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0), b_min(1) + size(1), b_min(2)); - ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0), b_min(1), b_min(2) + size(2)); + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + p_flat_shader->set_uniform("view_model_matrix", view_matrix * model_matrix); + p_flat_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0) - size(0), b_min(1), b_min(2)); - ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0), b_min(1) + size(1), b_min(2)); - ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0), b_min(1), b_min(2) + size(2)); + m_bounding_box_model.set_color({ color[0], color[1], color[2], 1.0f}); + m_bounding_box_model.render_geometry(); - ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0) - size(0), b_max(1), b_min(2)); - ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0), b_max(1) - size(1), b_min(2)); - ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0), b_max(1), b_min(2) + size(2)); - - ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0) + size(0), b_max(1), b_min(2)); - ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_min(2)); - ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0), b_max(1), b_min(2) + size(2)); - - ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0) + size(0), b_min(1), b_max(2)); - ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0), b_min(1) + size(1), b_max(2)); - ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0), b_min(1), b_max(2) - size(2)); - - ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0) - size(0), b_min(1), b_max(2)); - ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0), b_min(1) + size(1), b_max(2)); - ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0), b_min(1), b_max(2) - size(2)); - - ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0) - size(0), b_max(1), b_max(2)); - ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0), b_max(1) - size(1), b_max(2)); - ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0), b_max(1), b_max(2) - size(2)); - - ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0) + size(0), b_max(1), b_max(2)); - ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_max(2)); - ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1), b_max(2) - size(2)); - - glsafe(::glEnd()); + wxGetApp().unbind_shader(); } static std::array get_color(Axis axis) @@ -2637,91 +2630,106 @@ static std::array get_color(Axis axis) GLGizmoBase::AXES_COLOR[axis][3] }; }; -void Selection::render_sidebar_position_hints(const std::string& sidebar_field) const +void Selection::render_sidebar_position_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& model_matrix) const { + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d view_matrix = camera.get_view_matrix() * model_matrix; + shader.set_uniform("projection_matrix", camera.get_projection_matrix()); + if (boost::ends_with(sidebar_field, "x")) { - glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0)); + const Transform3d view_model_matrix = view_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ()); + shader.set_uniform("view_model_matrix", view_model_matrix); + shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); const_cast(&m_arrow)->set_color(-1, get_color(X)); - m_arrow.render(); + m_arrow.render_geometry(); } else if (boost::ends_with(sidebar_field, "y")) { + shader.set_uniform("view_model_matrix", view_matrix); + shader.set_uniform("normal_matrix", (Matrix3d)view_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); const_cast(&m_arrow)->set_color(-1, get_color(Y)); - m_arrow.render(); + m_arrow.render_geometry(); } else if (boost::ends_with(sidebar_field, "z")) { - glsafe(::glRotated(90.0, 1.0, 0.0, 0.0)); + const Transform3d view_model_matrix = view_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitX()); + shader.set_uniform("view_model_matrix", view_model_matrix); + shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); const_cast(&m_arrow)->set_color(-1, get_color(Z)); - m_arrow.render(); + m_arrow.render_geometry(); } } -void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field) const +void Selection::render_sidebar_rotation_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& model_matrix) const { - auto render_sidebar_rotation_hint = [this]() { - m_curved_arrow.render(); - glsafe(::glRotated(180.0, 0.0, 0.0, 1.0)); - m_curved_arrow.render(); + auto render_sidebar_rotation_hint = [this](GLShaderProgram& shader, const Transform3d& matrix) { + Transform3d view_model_matrix = matrix; + shader.set_uniform("view_model_matrix", view_model_matrix); + shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_curved_arrow.render_geometry(); + + view_model_matrix = matrix * Geometry::assemble_transform(Vec3d::Zero(), PI * Vec3d::UnitZ()); + shader.set_uniform("view_model_matrix", view_model_matrix); + shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_curved_arrow.render_geometry(); }; + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d view_matrix = camera.get_view_matrix() * model_matrix; + shader.set_uniform("projection_matrix", camera.get_projection_matrix()); + if (boost::ends_with(sidebar_field, "x")) { - glsafe(::glRotated(90.0, 0.0, 1.0, 0.0)); const_cast(&m_curved_arrow)->set_color(-1, get_color(X)); - render_sidebar_rotation_hint(); + render_sidebar_rotation_hint(shader, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY())); } else if (boost::ends_with(sidebar_field, "y")) { - glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0)); const_cast(&m_curved_arrow)->set_color(-1, get_color(Y)); - render_sidebar_rotation_hint(); + render_sidebar_rotation_hint(shader, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitX())); } else if (boost::ends_with(sidebar_field, "z")) { const_cast(&m_curved_arrow)->set_color(-1, get_color(Z)); - render_sidebar_rotation_hint(); + render_sidebar_rotation_hint(shader, view_matrix); } } //BBS: GUI refactor: add gizmo uniform_scale -void Selection::render_sidebar_scale_hints(const std::string& sidebar_field, bool gizmo_uniform_scale) const +void Selection::render_sidebar_scale_hints(const std::string& sidebar_field, bool gizmo_uniform_scale, GLShaderProgram& shader, const Transform3d& model_matrix) const { // BBS //bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling(); bool uniform_scale = requires_uniform_scale() || gizmo_uniform_scale; - auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis) { + auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis, GLShaderProgram& shader, const Transform3d& matrix) { const_cast(&m_arrow)->set_color(-1, uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis)); - GLShaderProgram* shader = wxGetApp().get_current_shader(); - if (shader != nullptr) - shader->set_uniform("emission_factor", 0.0f); + shader.set_uniform("emission_factor", 0.0f); - glsafe(::glTranslated(0.0, 5.0, 0.0)); - m_arrow.render(); + Transform3d view_model_matrix = matrix * Geometry::assemble_transform(5.0 * Vec3d::UnitY()); + shader.set_uniform("view_model_matrix", view_model_matrix); + shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_arrow.render_geometry(); - glsafe(::glTranslated(0.0, -10.0, 0.0)); - glsafe(::glRotated(180.0, 0.0, 0.0, 1.0)); - m_arrow.render(); + view_model_matrix = matrix * Geometry::assemble_transform(-10.0 * Vec3d::UnitY(), PI * Vec3d::UnitZ()); + shader.set_uniform("view_model_matrix", view_model_matrix); + shader.set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); + m_arrow.render_geometry(); }; + const Camera& camera = wxGetApp().plater()->get_camera(); + const Transform3d view_matrix = camera.get_view_matrix() * model_matrix; + shader.set_uniform("projection_matrix", camera.get_projection_matrix()); + if (boost::ends_with(sidebar_field, "x") || uniform_scale) { - glsafe(::glPushMatrix()); - glsafe(::glRotated(-90.0, 0.0, 0.0, 1.0)); - render_sidebar_scale_hint(X); - glsafe(::glPopMatrix()); + render_sidebar_scale_hint(X, shader, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ())); } if (boost::ends_with(sidebar_field, "y") || uniform_scale) { - glsafe(::glPushMatrix()); - render_sidebar_scale_hint(Y); - glsafe(::glPopMatrix()); + render_sidebar_scale_hint(Y, shader, view_matrix); } if (boost::ends_with(sidebar_field, "z") || uniform_scale) { - glsafe(::glPushMatrix()); - glsafe(::glRotated(90.0, 1.0, 0.0, 0.0)); - render_sidebar_scale_hint(Z); - glsafe(::glPopMatrix()); + render_sidebar_scale_hint(Z, shader, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitX())); } } -void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) const +void Selection::render_sidebar_layers_hints(GLShaderProgram& shader, const std::string& sidebar_field) const { static const double Margin = 10.0; if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasView3D) { @@ -2769,32 +2777,139 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - ::glBegin(GL_QUADS); - if ((camera_on_top && type == 1) || (!camera_on_top && type == 2)) - ::glColor4f(0.0f, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f); - else - ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); - ::glVertex3f(min_x, min_y, z1); - ::glVertex3f(max_x, min_y, z1); - ::glVertex3f(max_x, max_y, z1); - ::glVertex3f(min_x, max_y, z1); - glsafe(::glEnd()); + if (!m_sidebar_layers_hints_model.is_initialized()) { + GLModel::Geometry init_data; + init_data.format = { GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 }; + init_data.reserve_vertices(4); + init_data.reserve_indices(6); - ::glBegin(GL_QUADS); - if ((camera_on_top && type == 2) || (!camera_on_top && type == 1)) - ::glColor4f(0.0f, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f); - else - ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); - ::glVertex3f(min_x, min_y, z2); - ::glVertex3f(max_x, min_y, z2); - ::glVertex3f(max_x, max_y, z2); - ::glVertex3f(min_x, max_y, z2); - glsafe(::glEnd()); + // vertices + init_data.add_vertex(Vec3f(-0.5f, -0.5f, 0.0f)); + init_data.add_vertex(Vec3f(0.5f, -0.5f, 0.0f)); + init_data.add_vertex(Vec3f(0.5f, 0.5f, 0.0f)); + init_data.add_vertex(Vec3f(-0.5f, 0.5f, 0.0f)); + + // indices + init_data.add_triangle(0, 1, 2); + init_data.add_triangle(2, 3, 0); + + m_sidebar_layers_hints_model.init_from(std::move(init_data)); + } + Transform3d model_matrix{ Transform3d::Identity() }; + model_matrix.data()[3 * 4 + 0] = (max_x + min_x) * 0.5f; + model_matrix.data()[3 * 4 + 1] = (max_y + min_y) * 0.5f; + model_matrix.data()[3 * 4 + 2] = z1; + model_matrix.data()[0 * 4 + 0] = (max_x - min_x); + model_matrix.data()[1 * 4 + 1] = (max_y - min_y); + model_matrix.data()[2 * 4 + 2] = 1.0f; + + ColorRGBA color1; + if ((camera_on_top && type == 1) || (!camera_on_top && type == 2)) { + color1 = { 0.0f, 174.0f / 255.0f, 66.0f / 255.0f, 1.0f }; + } + else { + color1 = { 0.8f, 0.8f, 0.8f, 0.5 }; + } + m_sidebar_layers_hints_model.set_color(color1); + + const Camera& camera = wxGetApp().plater()->get_camera(); + const auto& view_matrix = camera.get_view_matrix(); + const auto& proj_matrix = camera.get_projection_matrix(); + + shader.set_uniform("projection_matrix", proj_matrix); + + shader.set_uniform("view_model_matrix", view_matrix * model_matrix); + m_sidebar_layers_hints_model.render_geometry(); + + model_matrix.data()[3 * 4 + 2] = z2; + shader.set_uniform("view_model_matrix", view_matrix * model_matrix); + m_sidebar_layers_hints_model.render_geometry(); glsafe(::glEnable(GL_CULL_FACE)); glsafe(::glDisable(GL_BLEND)); } +void Selection::init_bounding_box_model() const +{ + if (m_bounding_box_model.is_initialized()) { + return; + } + + GLModel::Geometry geo; + geo.format.type = GLModel::PrimitiveType::Lines; + geo.format.vertex_layout = GLModel::Geometry::EVertexLayout::P3; + + const float size = 0.2f; + Vec3f b_min{ -0.5f, -0.5f, -0.5f }; + Vec3f b_max{ 0.5f, 0.5f, 0.5f }; + geo.add_vertex(Vec3f{ b_min(0), b_min(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_min(0) + size, b_min(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_min(1) + size, b_min(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_min(1), b_min(2) + size }); + geo.add_vertex(Vec3f{ b_max(0), b_min(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_max(0) - size, b_min(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_min(1) + size, b_min(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_min(1), b_min(2) + size }); + geo.add_vertex(Vec3f{ b_max(0), b_max(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_max(0) - size, b_max(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_max(1) - size, b_min(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_max(1), b_min(2) + size }); + geo.add_vertex(Vec3f{ b_min(0), b_max(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_min(0) + size, b_max(1), b_min(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_max(1) - size, b_min(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_max(1), b_min(2) + size }); + geo.add_vertex(Vec3f{ b_min(0), b_min(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_min(0) + size, b_min(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_min(1) + size, b_max(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_min(1), b_max(2) - size }); + geo.add_vertex(Vec3f{ b_max(0), b_min(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_max(0) - size, b_min(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_min(1) + size, b_max(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_min(1), b_max(2) - size }); + geo.add_vertex(Vec3f{ b_max(0), b_max(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_max(0) - size, b_max(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_max(1) - size, b_max(2) }); + geo.add_vertex(Vec3f{ b_max(0), b_max(1), b_max(2) - size }); + geo.add_vertex(Vec3f{ b_min(0), b_max(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_min(0) + size, b_max(1), b_max(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_max(1) - size, b_max(2) }); + geo.add_vertex(Vec3f{ b_min(0), b_max(1), b_max(2) - size }); + + geo.add_line(0, 1); + geo.add_line(0, 2); + geo.add_line(0, 3); + + geo.add_line(4, 5); + geo.add_line(4, 6); + geo.add_line(4, 7); + + geo.add_line(8, 9); + geo.add_line(8, 10); + geo.add_line(8, 11); + + geo.add_line(12, 13); + geo.add_line(12, 14); + geo.add_line(12, 15); + + geo.add_line(16, 17); + geo.add_line(16, 18); + geo.add_line(16, 19); + + geo.add_line(20, 21); + geo.add_line(20, 22); + geo.add_line(20, 23); + + geo.add_line(24, 25); + geo.add_line(24, 26); + geo.add_line(24, 27); + + geo.add_line(28, 29); + geo.add_line(28, 30); + geo.add_line(28, 31); + + m_bounding_box_model.init_from(std::move(geo)); +} + #ifndef NDEBUG static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to) { diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 62e801405..4dd1832a5 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -265,7 +265,7 @@ private: std::optional> m_bounding_sphere; #if ENABLE_RENDER_SELECTION_CENTER - GLModel m_vbo_sphere; + mutable GLModel m_vbo_sphere; #endif // ENABLE_RENDER_SELECTION_CENTER GLModel m_arrow; @@ -279,6 +279,8 @@ private: bool m_volume_selection_locked { false }; std::vector m_trafo_matrices; + mutable GLModel m_bounding_box_model; + mutable GLModel m_sidebar_layers_hints_model; public: Selection(); @@ -496,11 +498,12 @@ private: void render_selected_volumes() const; void render_synchronized_volumes() const; void render_bounding_box(const BoundingBoxf3& box, float* color) const; - void render_sidebar_position_hints(const std::string& sidebar_field) const; - void render_sidebar_rotation_hints(const std::string& sidebar_field) const; + void render_sidebar_position_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& model_matrix) const; + void render_sidebar_rotation_hints(const std::string& sidebar_field, GLShaderProgram& shader, const Transform3d& model_matrix) const; //BBS: GUI refactor: add uniform_scale from gizmo - void render_sidebar_scale_hints(const std::string& sidebar_field, bool gizmo_uniform_scale) const; - void render_sidebar_layers_hints(const std::string& sidebar_field) const; + void render_sidebar_scale_hints(const std::string& sidebar_field, bool gizmo_uniform_scale, GLShaderProgram& shader, const Transform3d& model_matrix) const; + void render_sidebar_layers_hints(GLShaderProgram& shader, const std::string& sidebar_field) const; + void init_bounding_box_model() const; public: enum class SyncRotationType { diff --git a/src/slic3r/Utils/CalibUtils.cpp b/src/slic3r/Utils/CalibUtils.cpp index 5fe00c6ba..c1461fd2f 100644 --- a/src/slic3r/Utils/CalibUtils.cpp +++ b/src/slic3r/Utils/CalibUtils.cpp @@ -1343,7 +1343,7 @@ bool CalibUtils::process_and_store_3mf(Model *model, const DynamicPrintConfig &f ThumbnailData* thumbnail_data = &plate_data_list[0]->plate_thumbnail; unsigned int thumbnail_width = 512, thumbnail_height = 512; const ThumbnailsParams thumbnail_params = {{}, false, true, true, true, 0}; - GLShaderProgram* shader = wxGetApp().get_shader("thumbnail"); + const auto& shader = wxGetApp().get_shader("thumbnail"); for (unsigned int obj_idx = 0; obj_idx < (unsigned int)model->objects.size(); ++ obj_idx) { const ModelObject &model_object = *model->objects[obj_idx];