diff --git a/resources/shaders/110/gouraud.fs b/resources/shaders/110/gouraud.fs index 010baaa0dd..59c4e4d410 100644 --- a/resources/shaders/110/gouraud.fs +++ b/resources/shaders/110/gouraud.fs @@ -231,6 +231,8 @@ void main() s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0))); s = max(s, DetectSilho(fragCoord.xy + vec2(0, i))); } + if (s < 0.01) + discard; gl_FragColor = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a); } #ifdef ENABLE_ENVIRONMENT_MAP diff --git a/resources/shaders/110/gouraud.vs b/resources/shaders/110/gouraud.vs index ff3a190c79..184529be82 100644 --- a/resources/shaders/110/gouraud.vs +++ b/resources/shaders/110/gouraud.vs @@ -30,6 +30,8 @@ uniform mat4 projection_matrix; uniform mat3 view_normal_matrix; uniform mat4 volume_world_matrix; uniform SlopeDetection slope; +uniform bool is_outline; +uniform vec2 screen_size; // 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; @@ -75,6 +77,15 @@ void main() world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0; gl_Position = projection_matrix * position; + if (is_outline) { + vec3 n = normalize((view_normal_matrix * v_normal).xyz); + vec2 dir = normalize(n.xy); + if (dot(dir, dir) > 0.0) { + //set outline thickness + float px = 3.0; + gl_Position.xy += dir * (px * 2.0 / screen_size) * gl_Position.w; + } + } // 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); color_clip_plane_dot = dot(world_pos, color_clip_plane); diff --git a/resources/shaders/110/phong.fs b/resources/shaders/110/phong.fs index a5c1c5b8ab..5fedf7edff 100644 --- a/resources/shaders/110/phong.fs +++ b/resources/shaders/110/phong.fs @@ -273,6 +273,8 @@ void main() s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0))); s = max(s, DetectSilho(fragCoord.xy + vec2(0, i))); } + if (s < 0.01) + discard; gl_FragColor = vec4(mix(shaded_color.rgb, getBackfaceColor(shaded_color.rgb), s), shaded_color.a); } #ifdef ENABLE_ENVIRONMENT_MAP diff --git a/resources/shaders/110/phong.vs b/resources/shaders/110/phong.vs index b9e90e7cc2..10d36e233f 100644 --- a/resources/shaders/110/phong.vs +++ b/resources/shaders/110/phong.vs @@ -14,6 +14,8 @@ uniform mat4 projection_matrix; uniform mat3 view_normal_matrix; uniform mat4 volume_world_matrix; uniform SlopeDetection slope; +uniform bool is_outline; +uniform vec2 screen_size; // 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; @@ -48,6 +50,15 @@ void main() world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0; gl_Position = projection_matrix * position; + if (is_outline) { + vec3 n = normalize((view_normal_matrix * v_normal).xyz); + vec2 dir = normalize(n.xy); + if (dot(dir, dir) > 0.0) { + //set outline thickness + float px = 3.0; + gl_Position.xy += dir * (px * 2.0 / screen_size) * gl_Position.w; + } + } // 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); color_clip_plane_dot = dot(world_pos, color_clip_plane); diff --git a/resources/shaders/110/ssao.fs b/resources/shaders/110/ssao.fs index 43b52a3f29..5aada05883 100644 --- a/resources/shaders/110/ssao.fs +++ b/resources/shaders/110/ssao.fs @@ -11,6 +11,7 @@ uniform sampler2D normal_texture; uniform vec2 inv_tex_size; uniform float z_near; uniform float z_far; +uniform bool is_outline; varying vec2 tex_coord; @@ -22,6 +23,10 @@ float linearize_depth(float depth) void main() { + if (is_outline) { + gl_FragColor = vec4(texture2D(color_texture, tex_coord).rgb, 1.0); + return; + } vec3 base = texture2D(color_texture, tex_coord).rgb; float depth_center = linearize_depth(texture2D(depth_texture, tex_coord).r); diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs index 8ebb1d8a60..728b7f942c 100644 --- a/resources/shaders/140/gouraud.fs +++ b/resources/shaders/140/gouraud.fs @@ -232,6 +232,8 @@ void main() s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0))); s = max(s, DetectSilho(fragCoord.xy + vec2(0, i))); } + if (s < 0.01) + discard; out_color = vec4(mix(color.rgb, getBackfaceColor(color.rgb), s), color.a); } #ifdef ENABLE_ENVIRONMENT_MAP diff --git a/resources/shaders/140/gouraud.vs b/resources/shaders/140/gouraud.vs index 72dd4ff1bf..a31e751964 100644 --- a/resources/shaders/140/gouraud.vs +++ b/resources/shaders/140/gouraud.vs @@ -30,6 +30,8 @@ uniform mat4 projection_matrix; uniform mat3 view_normal_matrix; uniform mat4 volume_world_matrix; uniform SlopeDetection slope; +uniform bool is_outline; +uniform vec2 screen_size; // 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; @@ -75,6 +77,15 @@ void main() world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0; gl_Position = projection_matrix * position; + if (is_outline) { + vec3 n = normalize((view_normal_matrix * v_normal).xyz); + vec2 dir = normalize(n.xy); + if (dot(dir, dir) > 0.0) { + //set outline thickness + float px = 3.0; + gl_Position.xy += dir * (px * 2.0 / screen_size) * gl_Position.w; + } + } // 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); color_clip_plane_dot = dot(world_pos, color_clip_plane); diff --git a/resources/shaders/140/phong.fs b/resources/shaders/140/phong.fs index 894e3eb863..bbde72592c 100644 --- a/resources/shaders/140/phong.fs +++ b/resources/shaders/140/phong.fs @@ -277,6 +277,8 @@ void main() s = max(s, DetectSilho(fragCoord.xy + vec2(i, 0))); s = max(s, DetectSilho(fragCoord.xy + vec2(0, i))); } + if (s < 0.01) + discard; out_color = vec4(mix(shaded_color.rgb, getBackfaceColor(shaded_color.rgb), s), shaded_color.a); } #ifdef ENABLE_ENVIRONMENT_MAP diff --git a/resources/shaders/140/phong.vs b/resources/shaders/140/phong.vs index 2ccbaf16ee..c7570edb95 100644 --- a/resources/shaders/140/phong.vs +++ b/resources/shaders/140/phong.vs @@ -14,6 +14,8 @@ uniform mat4 projection_matrix; uniform mat3 view_normal_matrix; uniform mat4 volume_world_matrix; uniform SlopeDetection slope; +uniform bool is_outline; +uniform vec2 screen_size; // 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; @@ -48,6 +50,15 @@ void main() world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0; gl_Position = projection_matrix * position; + if (is_outline) { + vec3 n = normalize((view_normal_matrix * v_normal).xyz); + vec2 dir = normalize(n.xy); + if (dot(dir, dir) > 0.0) { + //set outline thickness + float px = 3.0; + gl_Position.xy += dir * (px * 2.0 / screen_size) * gl_Position.w; + } + } // 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); color_clip_plane_dot = dot(world_pos, color_clip_plane); diff --git a/resources/shaders/140/ssao.fs b/resources/shaders/140/ssao.fs index 86ea6a54bf..b3b6df6877 100644 --- a/resources/shaders/140/ssao.fs +++ b/resources/shaders/140/ssao.fs @@ -10,6 +10,7 @@ uniform sampler2D depth_texture; uniform sampler2D normal_texture; uniform float z_near; uniform float z_far; +uniform bool is_outline; in vec2 tex_coord; out vec4 frag_color; @@ -22,6 +23,10 @@ float linearize_depth(float depth) void main() { + if (is_outline) { + frag_color = vec4(texture(color_texture, tex_coord).rgb, 1.0); + return; + } ivec2 pixel = ivec2(gl_FragCoord.xy); float center_depth = linearize_depth(texelFetch(depth_texture, pixel, 0).r); diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 84709dd13b..335dd6b825 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -495,7 +495,29 @@ void GLVolume::render_with_outline(const GUI::Size& cnv_size) simple_render(shader, model_objects, colors); return; } - + // 0th. render pass, render the model using stencil buffer + glsafe(::glEnable(GL_STENCIL_TEST)); + glsafe(::glStencilMask(0xFF)); + glsafe(::glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE)); + glsafe(::glClearStencil(0)); + glsafe(::glClear(GL_STENCIL_BUFFER_BIT)); + glsafe(::glStencilFunc(GL_ALWAYS, 0xFF, 0xFF)); + if (tverts_range == std::make_pair(0, -1)) + model.render(shader); + else + model.render(this->tverts_range, shader); + glsafe(::glStencilFunc(GL_NOTEQUAL, 0xFF, 0xFF)); + glsafe(::glStencilMask(0x00)); + shader->set_uniform("is_outline", true); + shader->set_uniform("screen_size", Vec2f{cnv_size.get_width(), cnv_size.get_height()}); + if (tverts_range == std::make_pair(0, -1)) + model.render(shader); + else + model.render(this->tverts_range, shader); + shader->set_uniform("is_outline", false); + glsafe(::glStencilMask(0xFF)); + glsafe(::glDisable(GL_STENCIL_TEST)); + // render the outline using depth buffer and discard the pixels that are not on the outline // 1st. render pass, render the model into a separate render target that has only depth buffer GLuint depth_fbo = 0; GLuint depth_tex = 0;