diff --git a/resources/shaders/gouraud.fs b/resources/shaders/gouraud.fs index 9ab12676e..3aa2b0294 100644 --- a/resources/shaders/gouraud.fs +++ b/resources/shaders/gouraud.fs @@ -1,4 +1,4 @@ -#version 130 +#version 110 const vec3 ZERO = vec3(0.0, 0.0, 0.0); //BBS: add grey and orange @@ -26,29 +26,11 @@ struct SlopeDetection 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; @@ -106,17 +88,9 @@ void main() 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); - } - } + 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. diff --git a/resources/shaders/gouraud.vs b/resources/shaders/gouraud.vs index 9d46b5c55..79d7a63c0 100644 --- a/resources/shaders/gouraud.vs +++ b/resources/shaders/gouraud.vs @@ -1,4 +1,4 @@ -#version 130 +#version 110 #define INTENSITY_CORRECTION 0.6 @@ -43,8 +43,6 @@ varying vec4 world_pos; varying float world_normal_z; varying vec3 eye_normal; -varying vec3 barycentric_coordinates; - void main() { // First transform the normal into camera space and normalize the result. @@ -72,8 +70,4 @@ void main() 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); - - //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/gouraud_130.fs b/resources/shaders/gouraud_130.fs new file mode 100644 index 000000000..9ab12676e --- /dev/null +++ b/resources/shaders/gouraud_130.fs @@ -0,0 +1,124 @@ +#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_130.vs b/resources/shaders/gouraud_130.vs new file mode 100644 index 000000000..9d46b5c55 --- /dev/null +++ b/resources/shaders/gouraud_130.vs @@ -0,0 +1,79 @@ +#version 130 + +#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 LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION) +//#define LIGHT_FRONT_SHININESS 5.0 + +#define INTENSITY_AMBIENT 0.3 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +struct SlopeDetection +{ + bool actived; + float normal_z; + mat3 volume_world_normal_matrix; +}; + +uniform mat4 volume_world_matrix; +uniform SlopeDetection slope; + +// 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; + +// x = diffuse, y = specular; +varying vec2 intensity; + +varying 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; + +void main() +{ + // First transform the normal into camera space and normalize the result. + eye_normal = normalize(gl_NormalMatrix * gl_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); + + // 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; + // Point in homogenous coordinates. + world_pos = volume_world_matrix * gl_Vertex; + + // 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; + + 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); + + //compute the Barycentric Coordinates + int vertexMod3 = gl_VertexID % 3; + barycentric_coordinates = vec3(float(vertexMod3 == 0), float(vertexMod3 == 1), float(vertexMod3 == 2)); +} diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 1e7bc76f1..a2475c70f 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -45,11 +45,20 @@ std::pair GLShadersManager::init() // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); // used to render objects in 3d editor - valid &= append_shader("gouraud", { "gouraud.vs", "gouraud.fs" } + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 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" } #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" }); // used to render highlight contour around selected triangles inside the multi-material gizmo