diff --git a/resources/shaders/ES/background.fs b/resources/shaders/ES/background.fs new file mode 100644 index 0000000000..f255f00444 --- /dev/null +++ b/resources/shaders/ES/background.fs @@ -0,0 +1,13 @@ +#version 110 + +precision highp float; + +uniform vec4 top_color; +uniform vec4 bottom_color; + +varying vec2 tex_coord; + +void main() +{ + gl_FragColor = mix(bottom_color, top_color, tex_coord.y); +} diff --git a/resources/shaders/ES/background.vs b/resources/shaders/ES/background.vs new file mode 100644 index 0000000000..9b56ab43a2 --- /dev/null +++ b/resources/shaders/ES/background.vs @@ -0,0 +1,12 @@ +#version 110 + +attribute vec3 v_position; +attribute vec2 v_tex_coord; + +varying vec2 tex_coord; + +void main() +{ + tex_coord = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} diff --git a/resources/shaders/ES/flat.fs b/resources/shaders/ES/flat.fs new file mode 100644 index 0000000000..89fbbe55d5 --- /dev/null +++ b/resources/shaders/ES/flat.fs @@ -0,0 +1,10 @@ +#version 110 + +precision highp float; + +uniform vec4 uniform_color; + +void main() +{ + gl_FragColor = uniform_color; +} diff --git a/resources/shaders/ES/flat.vs b/resources/shaders/ES/flat.vs new file mode 100644 index 0000000000..d9063f0c70 --- /dev/null +++ b/resources/shaders/ES/flat.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/ES/flat_clip.fs b/resources/shaders/ES/flat_clip.fs new file mode 100644 index 0000000000..88db3c3e06 --- /dev/null +++ b/resources/shaders/ES/flat_clip.fs @@ -0,0 +1,17 @@ +#version 110 + +precision highp float; + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +uniform vec4 uniform_color; + +varying vec3 clipping_planes_dots; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + + gl_FragColor = uniform_color; +} diff --git a/resources/shaders/ES/flat_clip.vs b/resources/shaders/ES/flat_clip.vs new file mode 100644 index 0000000000..cdf7d4b3b2 --- /dev/null +++ b/resources/shaders/ES/flat_clip.vs @@ -0,0 +1,23 @@ +#version 110 + +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; + +varying vec3 clipping_planes_dots; + +void main() +{ + // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. + vec4 world_pos = volume_world_matrix * vec4(v_position, 1.0); + clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); + + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/ES/flat_texture.fs b/resources/shaders/ES/flat_texture.fs new file mode 100644 index 0000000000..132233765c --- /dev/null +++ b/resources/shaders/ES/flat_texture.fs @@ -0,0 +1,12 @@ +#version 110 + +precision highp float; + +uniform sampler2D uniform_texture; + +varying vec2 tex_coord; + +void main() +{ + gl_FragColor = texture2D(uniform_texture, tex_coord); +} diff --git a/resources/shaders/ES/flat_texture.vs b/resources/shaders/ES/flat_texture.vs new file mode 100644 index 0000000000..dc4868b04d --- /dev/null +++ b/resources/shaders/ES/flat_texture.vs @@ -0,0 +1,15 @@ +#version 110 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +attribute vec3 v_position; +attribute vec2 v_tex_coord; + +varying 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/ES/gouraud.fs b/resources/shaders/ES/gouraud.fs new file mode 100644 index 0000000000..c4d2c57d28 --- /dev/null +++ b/resources/shaders/ES/gouraud.fs @@ -0,0 +1,89 @@ +#version 110 +#extension GL_NV_fragdepth : enable + +precision highp float; + +const vec3 ZERO = vec3(0.0, 0.0, 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; +}; + +uniform vec4 uniform_color; +uniform SlopeDetection slope; + +uniform bool offset_depth_buffer; + +#ifdef ENABLE_ENVIRONMENT_MAP + uniform sampler2D environment_tex; + uniform bool use_environment_tex; +#endif // ENABLE_ENVIRONMENT_MAP + +uniform PrintVolumeDetection print_volume; + +varying vec3 clipping_planes_dots; + +// x = diffuse, y = specular; +varying vec2 intensity; + +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); + 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); + } + 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; + +#ifdef ENABLE_ENVIRONMENT_MAP + 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); + else +#endif + 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); +} diff --git a/resources/shaders/ES/gouraud.vs b/resources/shaders/ES/gouraud.vs new file mode 100644 index 0000000000..70f71f886b --- /dev/null +++ b/resources/shaders/ES/gouraud.vs @@ -0,0 +1,77 @@ +#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 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 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 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; + +attribute vec3 v_position; +attribute vec3 v_normal; + +// x = diffuse, y = specular; +varying vec2 intensity; + +varying vec3 clipping_planes_dots; + +varying vec4 world_pos; +varying float world_normal_z; +varying vec3 eye_normal; + +void main() +{ + // First transform the normal into camera space and normalize the result. + 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; + 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; + + // Point in homogenous coordinates. + 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 * v_normal)).z : 0.0; + + 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/ES/gouraud_light.fs b/resources/shaders/ES/gouraud_light.fs new file mode 100644 index 0000000000..261682a3c1 --- /dev/null +++ b/resources/shaders/ES/gouraud_light.fs @@ -0,0 +1,14 @@ +#version 110 + +precision highp float; + +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/ES/gouraud_light.vs b/resources/shaders/ES/gouraud_light.vs new file mode 100644 index 0000000000..a03653b8a3 --- /dev/null +++ b/resources/shaders/ES/gouraud_light.vs @@ -0,0 +1,45 @@ +#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 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +attribute vec3 v_position; +attribute vec3 v_normal; + +// x = tainted, y = specular; +varying vec2 intensity; + +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; + + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/ES/gouraud_light_instanced.fs b/resources/shaders/ES/gouraud_light_instanced.fs new file mode 100644 index 0000000000..970185a00e --- /dev/null +++ b/resources/shaders/ES/gouraud_light_instanced.fs @@ -0,0 +1,12 @@ +#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/ES/gouraud_light_instanced.vs b/resources/shaders/ES/gouraud_light_instanced.vs new file mode 100644 index 0000000000..87748ce6f0 --- /dev/null +++ b/resources/shaders/ES/gouraud_light_instanced.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 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +// vertex attributes +attribute vec3 v_position; +attribute vec3 v_normal; +// instance attributes +attribute vec3 i_offset; +attribute vec2 i_scales; + +// x = tainted, y = specular; +varying vec2 intensity; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 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; + vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0); + vec4 eye_position = view_model_matrix * world_position; + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_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; + + gl_Position = projection_matrix * eye_position; +} diff --git a/resources/shaders/ES/imgui.fs b/resources/shaders/ES/imgui.fs new file mode 100644 index 0000000000..8f9a476960 --- /dev/null +++ b/resources/shaders/ES/imgui.fs @@ -0,0 +1,13 @@ +#version 110 + +precision highp float; + +uniform sampler2D Texture; + +varying vec2 Frag_UV; +varying vec4 Frag_Color; + +void main() +{ + gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st); +} \ No newline at end of file diff --git a/resources/shaders/ES/imgui.vs b/resources/shaders/ES/imgui.vs new file mode 100644 index 0000000000..100813e2b5 --- /dev/null +++ b/resources/shaders/ES/imgui.vs @@ -0,0 +1,17 @@ +#version 110 + +uniform mat4 ProjMtx; + +attribute vec2 Position; +attribute vec2 UV; +attribute vec4 Color; + +varying vec2 Frag_UV; +varying vec4 Frag_Color; + +void main() +{ + Frag_UV = UV; + Frag_Color = Color; + gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/ES/mm_contour.fs b/resources/shaders/ES/mm_contour.fs new file mode 100644 index 0000000000..591e49c8ec --- /dev/null +++ b/resources/shaders/ES/mm_contour.fs @@ -0,0 +1,16 @@ +#version 110 +#extension GL_NV_fragdepth : enable + +precision highp float; + +const float EPSILON = 0.0001; + +uniform vec4 uniform_color; + +void main() +{ + gl_FragColor = uniform_color; + // 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/ES/mm_contour.vs b/resources/shaders/ES/mm_contour.vs new file mode 100644 index 0000000000..d9063f0c70 --- /dev/null +++ b/resources/shaders/ES/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/ES/mm_gouraud.fs b/resources/shaders/ES/mm_gouraud.fs new file mode 100644 index 0000000000..6643a5fd9f --- /dev/null +++ b/resources/shaders/ES/mm_gouraud.fs @@ -0,0 +1,66 @@ +#version 110 +#extension GL_OES_standard_derivatives : enable + +precision highp float; + +#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 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); +const float EPSILON = 0.0001; + +uniform vec4 uniform_color; + +uniform bool volume_mirrored; + +uniform mat4 view_model_matrix; +uniform mat3 normal_matrix; + +varying vec3 clipping_planes_dots; +varying vec4 model_pos; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + vec3 color = uniform_color.rgb; + float alpha = uniform_color.a; + + vec3 triangle_normal = normalize(cross(dFdx(model_pos.xyz), dFdy(model_pos.xyz))); +#ifdef FLIP_TRIANGLE_NORMALS + triangle_normal = -triangle_normal; +#endif + + if (volume_mirrored) + triangle_normal = -triangle_normal; + + // First transform the normal into camera space and normalize the result. + 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. + float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); + + // x = diffuse, y = specular; + vec2 intensity = vec2(0.0); + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec3 position = (view_model_matrix * model_pos).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); +} diff --git a/resources/shaders/ES/mm_gouraud.vs b/resources/shaders/ES/mm_gouraud.vs new file mode 100644 index 0000000000..10c25239f9 --- /dev/null +++ b/resources/shaders/ES/mm_gouraud.vs @@ -0,0 +1,28 @@ +#version 110 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +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; + +varying vec3 clipping_planes_dots; +varying vec4 model_pos; + +void main() +{ + model_pos = vec4(v_position, 1.0); + // Point in homogenous coordinates. + vec4 world_pos = volume_world_matrix * model_pos; + + gl_Position = projection_matrix * view_model_matrix * model_pos; + // 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/ES/printbed.fs b/resources/shaders/ES/printbed.fs new file mode 100644 index 0000000000..6396f36070 --- /dev/null +++ b/resources/shaders/ES/printbed.fs @@ -0,0 +1,36 @@ +#version 110 + +precision highp float; + +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 bool transparent_background; +uniform bool svg_source; + +varying vec2 tex_coord; + +vec4 svg_color() +{ + // takes foreground from texture + vec4 fore_color = texture2D(texture, tex_coord); + + // calculates radial gradient + vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - 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() +{ + // takes foreground from texture + vec4 color = texture2D(texture, tex_coord); + return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); +} + +void main() +{ + gl_FragColor = svg_source ? svg_color() : non_svg_color(); +} \ No newline at end of file diff --git a/resources/shaders/ES/printbed.vs b/resources/shaders/ES/printbed.vs new file mode 100644 index 0000000000..dc4868b04d --- /dev/null +++ b/resources/shaders/ES/printbed.vs @@ -0,0 +1,15 @@ +#version 110 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +attribute vec3 v_position; +attribute vec2 v_tex_coord; + +varying 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/ES/toolpaths_cog.fs b/resources/shaders/ES/toolpaths_cog.fs new file mode 100644 index 0000000000..85f44e0ef2 --- /dev/null +++ b/resources/shaders/ES/toolpaths_cog.fs @@ -0,0 +1,21 @@ +#version 110 + +precision highp float; + +const vec4 BLACK = vec4(vec3(0.1), 1.0); +const vec4 WHITE = vec4(vec3(1.0), 1.0); + +const float emission_factor = 0.25; + +uniform vec3 world_center; + +// x = tainted, y = specular; +varying vec2 intensity; +varying vec3 world_position; + +void main() +{ + vec3 delta = world_position - world_center; + vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE; + gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0); +} diff --git a/resources/shaders/ES/toolpaths_cog.vs b/resources/shaders/ES/toolpaths_cog.vs new file mode 100644 index 0000000000..38d2f79444 --- /dev/null +++ b/resources/shaders/ES/toolpaths_cog.vs @@ -0,0 +1,47 @@ +#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 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +attribute vec3 v_position; +attribute vec3 v_normal; + +// x = tainted, y = specular; +varying vec2 intensity; +varying vec3 world_position; + +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; + + world_position = v_position; + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/ES/variable_layer_height.fs b/resources/shaders/ES/variable_layer_height.fs new file mode 100644 index 0000000000..cedbe03c6e --- /dev/null +++ b/resources/shaders/ES/variable_layer_height.fs @@ -0,0 +1,44 @@ +#version 110 +#extension GL_OES_standard_derivatives : enable + +precision highp float; + +#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; +varying vec2 intensity; + +varying float object_z; + +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(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.), + texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod); + // Mix the final color. + gl_FragColor = 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/ES/variable_layer_height.vs b/resources/shaders/ES/variable_layer_height.vs new file mode 100644 index 0000000000..e6c88fa809 --- /dev/null +++ b/resources/shaders/ES/variable_layer_height.vs @@ -0,0 +1,60 @@ +#version 110 + +#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 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; +uniform mat4 volume_world_matrix; +uniform float object_max_z; + +attribute vec3 v_position; +attribute vec3 v_normal; +attribute vec2 v_tex_coord; + +// x = tainted, y = specular; +varying vec2 intensity; + +varying float object_z; + +void main() +{ + // ===================================================== + // NOTE: + // when object_max_z > 0.0 we are rendering the overlay + // when object_max_z == 0.0 we are rendering the volumes + // ===================================================== + + // First transform the normal into camera space and normalize the result. + vec3 normal = (object_max_z > 0.0) ? vec3(0.0, 0.0, 1.0) : 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. + object_z = (object_max_z > 0.0) ? object_max_z * v_tex_coord.y : (volume_world_matrix * vec4(v_position, 1.0)).z; + + gl_Position = projection_matrix * position; +} diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index c33abaddec..94830a70a2 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -55,8 +55,10 @@ #define ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) // Enable removal of legacy OpenGL calls #define ENABLE_LEGACY_OPENGL_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) +// Enable OpenGL ES +#define ENABLE_OPENGL_ES (1 && ENABLE_LEGACY_OPENGL_REMOVAL) // Enable OpenGL core profile context (tested against Mesa 20.1.8 on Windows) -#define ENABLE_GL_CORE_PROFILE (1 && ENABLE_LEGACY_OPENGL_REMOVAL) +#define ENABLE_GL_CORE_PROFILE (1 && ENABLE_LEGACY_OPENGL_REMOVAL && !ENABLE_OPENGL_ES) // Shows an imgui dialog with GLModel statistics data #define ENABLE_GLMODEL_STATISTICS (0 && ENABLE_LEGACY_OPENGL_REMOVAL) // Enable show non-manifold edges diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index c9ef93916c..b100449e79 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -903,13 +903,25 @@ void GLVolumeCollection::load_object_auxiliary( #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL +#if ENABLE_OPENGL_ES +int GLVolumeCollection::load_wipe_tower_preview( + float pos_x, float pos_y, float width, float depth, float height, + float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh) +#else int GLVolumeCollection::load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width) +#endif // ENABLE_OPENGL_ES +#else +#if ENABLE_OPENGL_ES +int GLVolumeCollection::load_wipe_tower_preview( + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, + float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh) #else int GLVolumeCollection::load_wipe_tower_preview( int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width) +#endif // ENABLE_OPENGL_ES #endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #else #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL @@ -979,6 +991,10 @@ int GLVolumeCollection::load_wipe_tower_preview( volumes.emplace_back(new GLVolume(color)); GLVolume& v = *volumes.back(); #if ENABLE_LEGACY_OPENGL_REMOVAL +#if ENABLE_OPENGL_ES + if (out_mesh != nullptr) + *out_mesh = mesh; +#endif // ENABLE_OPENGL_ES v.model.init_from(mesh); v.model.set_color(color); #else diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 3f6b1361d5..a1471d4e9f 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -638,11 +638,21 @@ public: size_t timestamp); #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL +#if ENABLE_OPENGL_ES + int load_wipe_tower_preview( + float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr); +#else int load_wipe_tower_preview( float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width); +#endif // ENABLE_OPENGL_ES +#else +#if ENABLE_OPENGL_ES + int load_wipe_tower_preview( + int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr); #else int load_wipe_tower_preview( int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width); +#endif // ENABLE_OPENGL_ES #endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #else std::vector load_object( diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index e8636a2151..2894a154d3 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1221,9 +1221,16 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const // get vertices/normals data from vertex buffers on gpu for (size_t i = 0; i < t_buffer.vertices.vbos.size(); ++i) { const size_t floats_count = t_buffer.vertices.sizes[i] / sizeof(float); - VertexBuffer vertices(floats_count); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, t_buffer.vertices.vbos[i])); +#if ENABLE_OPENGL_ES + const VertexBuffer vertices = *static_cast(::glMapBufferRange(GL_ARRAY_BUFFER, 0, + static_cast(t_buffer.vertices.sizes[i]), GL_MAP_READ_BIT)); + glcheck(); + glsafe(::glUnmapBuffer(GL_ARRAY_BUFFER)); +#else + VertexBuffer vertices(floats_count); glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, static_cast(t_buffer.vertices.sizes[i]), static_cast(vertices.data()))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); const size_t vertices_count = floats_count / floats_per_vertex; for (size_t j = 0; j < vertices_count; ++j) { @@ -1271,9 +1278,17 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const // get indices data from index buffer on gpu glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer.ibo)); for (size_t j = 0; j < render_path.sizes.size(); ++j) { +#if ENABLE_OPENGL_ES + const IndexBuffer indices = *static_cast(::glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + static_cast(render_path.offsets[j]), static_cast(render_path.sizes[j] * sizeof(IBufferType)), + GL_MAP_READ_BIT)); + glcheck(); + glsafe(::glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); +#else IndexBuffer indices(render_path.sizes[j]); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(render_path.offsets[j]), static_cast(render_path.sizes[j] * sizeof(IBufferType)), static_cast(indices.data()))); +#endif // ENABLE_OPENGL_ES const size_t triangles_count = render_path.sizes[j] / 3; for (size_t k = 0; k < triangles_count; ++k) { @@ -2682,14 +2697,30 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // gets the vertex index from the index buffer on gpu const IBuffer& i_buffer = buffer.indices[sub_path.first.b_id]; - IBufferType index = 0; glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); +#if ENABLE_OPENGL_ES + IBufferType index = *static_cast(::glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + static_cast(offset * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), + GL_MAP_READ_BIT)); + glcheck(); + glsafe(::glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); +#else + IBufferType index = 0; glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(offset * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&index))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); // gets the position from the vertices buffer on gpu glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); - glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(index * buffer.vertices.vertex_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); +#if ENABLE_OPENGL_ES + sequential_view->current_position = *static_cast(::glMapBufferRange(GL_ARRAY_BUFFER, + static_cast(index * buffer.vertices.vertex_size_bytes()), + static_cast(buffer.vertices.position_size_bytes()), GL_MAP_READ_BIT)); + glcheck(); + glsafe(::glUnmapBuffer(GL_ARRAY_BUFFER)); +#else + glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(index* buffer.vertices.vertex_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); sequential_view->current_offset = Vec3f::Zero(); @@ -2896,10 +2927,22 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // extract indices from index buffer std::array indices{ 0, 0, 0, 0, 0, 0 }; glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); +#if ENABLE_OPENGL_ES + IBufferType* index_ptr = static_cast(::glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + static_cast(offset * sizeof(IBufferType)), static_cast(14 * sizeof(IBufferType)), + GL_MAP_READ_BIT)); + glcheck(); + indices[0] = *(index_ptr + 0); + indices[1] = *(index_ptr + 7); + indices[2] = *(index_ptr + 1); + indices[4] = *(index_ptr + 13); + glsafe(::glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); +#else glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 0) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[0]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 7) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[1]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 1) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[2]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 13) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[4]))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); indices[3] = indices[0]; indices[5] = indices[1]; @@ -2944,10 +2987,22 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // extract indices from index buffer std::array indices{ 0, 0, 0, 0, 0, 0 }; glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); +#if ENABLE_OPENGL_ES + IBufferType* index_ptr = static_cast(::glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, + static_cast(offset * sizeof(IBufferType)), static_cast(17 * sizeof(IBufferType)), + GL_MAP_READ_BIT)); + glcheck(); + indices[0] = *(index_ptr + 2); + indices[1] = *(index_ptr + 4); + indices[2] = *(index_ptr + 10); + indices[5] = *(index_ptr + 16); + glsafe(::glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER)); +#else glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 2) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[0]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 4) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[1]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 10) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[2]))); glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast((offset + 16) * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&indices[5]))); +#endif // ENABLE_OPENGL_ES glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); indices[3] = indices[0]; indices[4] = indices[2]; @@ -3029,7 +3084,14 @@ void GCodeViewer::render_toolpaths() shader.set_uniform("gap_size", 0.0f); #endif // ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + for (size_t i = 0; i < path.sizes.size(); ++i) { + glsafe(::glDrawElements(GL_LINES, (GLsizei)path.sizes[i], GL_UNSIGNED_SHORT, (const void*)path.offsets[i])); + } +#else glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#endif // ENABLE_OPENGL_ES + #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_lines_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -3047,7 +3109,15 @@ void GCodeViewer::render_toolpaths() assert(! path.sizes.empty()); assert(! path.offsets.empty()); shader.set_uniform(uniform_color, path.color); + +#if ENABLE_OPENGL_ES + for (size_t i = 0; i < path.sizes.size(); ++i) { + glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)path.sizes[i], GL_UNSIGNED_SHORT, (const void*)path.offsets[i])); + } +#else glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); +#endif // ENABLE_OPENGL_ES + #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_triangles_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 3c73f7ed9e..1f701925ef 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1216,7 +1216,11 @@ bool GLCanvas3D::init() return false; glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 1.0f)); +#if ENABLE_OPENGL_ES + glsafe(::glClearDepthf(1.0f)); +#else glsafe(::glClearDepth(1.0f)); +#endif // ENABLE_OPENGL_ES glsafe(::glDepthFunc(GL_LESS)); @@ -2055,6 +2059,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (volume->is_wipe_tower) { // There is only one wipe tower. assert(volume_idx_wipe_tower_old == -1); +#if ENABLE_OPENGL_ES + m_wipe_tower_mesh.clear(); +#endif // ENABLE_OPENGL_ES volume_idx_wipe_tower_old = (int)volume_id; } if (!m_reload_delayed) { @@ -2294,13 +2301,25 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL +#if ENABLE_OPENGL_ES + int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( + x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), + brim_width, &m_wipe_tower_mesh); +#else int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), brim_width); +#endif // ENABLE_OPENGL_ES +#else +#if ENABLE_OPENGL_ES + int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( + 1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), + brim_width, &m_wipe_tower_mesh); #else int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview( 1000, x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower), brim_width); +#endif // ENABLE_OPENGL_ES #endif // ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL #else #if ENABLE_WIPETOWER_OBJECTID_1000_REMOVAL @@ -6444,6 +6463,43 @@ Vec3d GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) if (m_canvas == nullptr) return Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); +#if ENABLE_OPENGL_ES + if (z == nullptr) { + const Camera& camera = wxGetApp().plater()->get_camera(); + std::vector hits; + for (GLVolume* v : m_volumes.volumes) { + if (v->is_active) { + const MeshRaycaster raycaster(v->is_wipe_tower ? m_wipe_tower_mesh : m_model->objects[v->object_idx()]->volumes[v->volume_idx()]->mesh()); + Vec3f hit_position; + Vec3f hit_normal; + const Transform3d trafo = v->world_matrix(); + if (raycaster.unproject_on_mesh(mouse_pos.cast(), trafo, camera, hit_position, hit_normal)) + hits.emplace_back(trafo * hit_position.cast()); + } + } + if (hits.empty()) + return _mouse_to_bed_3d(mouse_pos); + else { + const Vec3d camera_position = camera.get_position(); + std::sort(hits.begin(), hits.end(), [&camera_position](const Vec3d& h1, const Vec3d& h2) { + return (h1 - camera_position).squaredNorm() < (h2 - camera_position).squaredNorm(); + }); + return hits.front(); + } + } + else { + const Camera& camera = wxGetApp().plater()->get_camera(); + const Matrix4d modelview = camera.get_view_matrix().matrix(); + const Matrix4d projection = camera.get_projection_matrix().matrix(); + const Vec4i viewport(camera.get_viewport().data()); + + const int y = viewport[3] - mouse_pos.y(); + + Vec3d out; + igl::unproject(Vec3d(mouse_pos.x(), y, *z), modelview, projection, viewport, out); + return out; + } +#else const Camera& camera = wxGetApp().plater()->get_camera(); const Matrix4d modelview = camera.get_view_matrix().matrix(); const Matrix4d projection = camera.get_projection_matrix().matrix(); @@ -6459,6 +6515,7 @@ Vec3d GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) Vec3d out; igl::unproject(Vec3d(mouse_pos.x(), y, mouse_z), modelview, projection, viewport, out); return out; +#endif // ENABLE_OPENGL_ES } Vec3d GLCanvas3D::_mouse_to_bed_3d(const Point& mouse_pos) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index f20de2621e..164bbed343 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -498,6 +498,9 @@ private: bool m_event_handlers_bound{ false }; GLVolumeCollection m_volumes; +#if ENABLE_OPENGL_ES + TriangleMesh m_wipe_tower_mesh; +#endif // ENABLE_OPENGL_ES GCodeViewer m_gcode_viewer; RenderTimer m_render_timer; diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index 177af97be6..4e3da6accf 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -128,11 +128,11 @@ namespace GUI { glsafe(::glScaled(gui_scale, gui_scale, 1.0)); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glPushAttrib(GL_ENABLE_BIT)); glsafe(::glLineStipple(4, 0xAAAA)); glsafe(::glEnable(GL_LINE_STIPPLE)); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_GL_CORE_PROFILE @@ -225,9 +225,9 @@ namespace GUI { glsafe(::glEnd()); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glPopAttrib()); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 884bc38cdb..0842d49657 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -34,7 +34,11 @@ std::pair GLShadersManager::init() bool valid = true; #if ENABLE_LEGACY_OPENGL_REMOVAL +#if ENABLE_OPENGL_ES + const std::string prefix = "ES/"; +#else const std::string prefix = GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1) ? "140/" : "110/"; +#endif // ENABLE_OPENGL_ES // imgui shader valid &= append_shader("imgui", { prefix + "imgui.vs", prefix + "imgui.fs" }); // basic shader, used to render all what was previously rendered using the immediate mode diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 4619be2210..99e6c54ed9 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -334,10 +334,10 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glEnable(GL_TEXTURE_2D)); glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)tex_id)); @@ -381,9 +381,9 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glDisable(GL_TEXTURE_2D)); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glDisable(GL_BLEND)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index d71495a34f..e343faa180 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -210,11 +210,11 @@ void GLGizmoPainterBase::render_cursor_circle() glsafe(::glScaled(gui_scale, gui_scale, 1.0)); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glPushAttrib(GL_ENABLE_BIT)); glsafe(::glLineStipple(4, 0xAAAA)); glsafe(::glEnable(GL_LINE_STIPPLE)); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL if (!m_circle.is_initialized() || !m_old_center.isApprox(center) || std::abs(m_old_cursor_radius - radius) > EPSILON) { @@ -292,9 +292,9 @@ void GLGizmoPainterBase::render_cursor_circle() glsafe(::glEnd()); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if !ENABLE_GL_CORE_PROFILE +#if !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES glsafe(::glPopAttrib()); -#endif // !ENABLE_GL_CORE_PROFILE +#endif // !ENABLE_GL_CORE_PROFILE && !ENABLE_OPENGL_ES #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 3ad4d2d83c..96362c74e8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -742,11 +742,11 @@ void GLGizmoSimplify::on_render() glsafe(::glMultMatrixd(trafo_matrix.data())); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL auto* gouraud_shader = wxGetApp().get_shader("gouraud_light"); -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES bool depth_test_enabled = ::glIsEnabled(GL_DEPTH_TEST); #else glsafe(::glPushAttrib(GL_DEPTH_TEST)); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES glsafe(::glEnable(GL_DEPTH_TEST)); gouraud_shader->start_using(); #if ENABLE_LEGACY_OPENGL_REMOVAL @@ -779,12 +779,12 @@ void GLGizmoSimplify::on_render() #endif // ENABLE_LEGACY_OPENGL_REMOVAL contour_shader->stop_using(); } -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES if (depth_test_enabled) glsafe(::glEnable(GL_DEPTH_TEST)); #else glsafe(::glPopAttrib()); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 35d0c3d39e..b667864ac1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -222,23 +222,23 @@ void InstancesHider::render_cut() const glsafe(::glColor4fv(color.data())); } #endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES bool depth_test_enabled = ::glIsEnabled(GL_DEPTH_TEST); #else glsafe(::glPushAttrib(GL_DEPTH_TEST)); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES glsafe(::glDisable(GL_DEPTH_TEST)); #if ENABLE_LEGACY_OPENGL_REMOVAL clipper->render_cut(mv->is_model_part() ? ColorRGBA(0.8f, 0.3f, 0.0f, 1.0f) : color_from_model_volume(*mv)); #else clipper->render_cut(); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES if (depth_test_enabled) glsafe(::glEnable(GL_DEPTH_TEST)); #else glsafe(::glPopAttrib()); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index acdbcab630..18d548c7ec 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -1471,7 +1471,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) draw_data->ScaleClipRects(io.DisplayFramebufferScale); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES // Backup GL state GLenum last_active_texture; glsafe(::glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture)); GLuint last_program; glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program)); @@ -1526,7 +1526,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glEnable(GL_TEXTURE_2D)); glsafe(::glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)); glsafe(::glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL // Setup viewport, orthographic projection matrix @@ -1665,7 +1665,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) #endif // ENABLE_LEGACY_OPENGL_REMOVAL } -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES // Restore modified GL state glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture)); glsafe(::glActiveTexture(last_active_texture)); @@ -1698,7 +1698,7 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]))); 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])); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES #if ENABLE_LEGACY_OPENGL_REMOVAL shader->stop_using(); diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index b0bf682dba..3f6b869537 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -78,7 +78,7 @@ bool OpenGLManager::GLInfo::is_mesa() const return boost::icontains(m_version, "mesa"); } #endif // _WIN32 -#endif // ENABLE_OPENGL_ES +#endif // ENABLE_GL_CORE_PROFILE int OpenGLManager::GLInfo::get_max_tex_size() const { @@ -136,8 +136,16 @@ static bool version_greater_or_equal_to(const std::string& version, unsigned int if (tokens.empty()) return false; +#if ENABLE_OPENGL_ES + const std::string version_container = (tokens.size() > 1 && boost::istarts_with(tokens[1], "ES")) ? tokens[2] : tokens[0]; +#endif // ENABLE_OPENGL_ES + std::vector numbers; +#if ENABLE_OPENGL_ES + boost::split(numbers, version_container, boost::is_any_of("."), boost::token_compress_on); +#else boost::split(numbers, tokens[0], boost::is_any_of("."), boost::token_compress_on); +#endif // ENABLE_OPENGL_ES unsigned int gl_major = 0; unsigned int gl_minor = 0; @@ -192,6 +200,8 @@ std::string OpenGLManager::GLInfo::to_string(bool for_github) const out << b_start << "GL version: " << b_end << m_version << line_end; #if ENABLE_GL_CORE_PROFILE out << b_start << "Profile: " << b_end << (is_core_profile() ? "Core" : "Compatibility") << line_end; +#else + out << b_start << "Profile: " << b_end << "Compatibility" << line_end; #endif // ENABLE_GL_CORE_PROFILE out << b_start << "Vendor: " << b_end << m_vendor << line_end; out << b_start << "Renderer: " << b_end << m_renderer << line_end; @@ -268,9 +278,9 @@ OpenGLManager::~OpenGLManager() bool OpenGLManager::init_gl() { if (!m_gl_initialized) { -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES glewExperimental = true; -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES GLenum err = glewInit(); if (err != GLEW_OK) { BOOST_LOG_TRIVIAL(error) << "Unable to init glew library: " << glewGetErrorString(err); @@ -279,7 +289,7 @@ bool OpenGLManager::init_gl() #if ENABLE_GL_CORE_PROFILE do { - // glewInit() generates an OpenGL GL_INVALID_ENUM error + // glewInit() generates an OpenGL GL_INVALID_ENUM error when using core profile err = ::glGetError(); } while (err != GL_NO_ERROR); #endif // ENABLE_GL_CORE_PROFILE @@ -304,21 +314,26 @@ bool OpenGLManager::init_gl() else s_framebuffers_type = EFramebufferType::Unknown; -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + bool valid_version = s_gl_info.is_version_greater_or_equal_to(2, 0); +#elif ENABLE_GL_CORE_PROFILE bool valid_version = s_gl_info.is_core_profile() ? s_gl_info.is_version_greater_or_equal_to(3, 3) : s_gl_info.is_version_greater_or_equal_to(2, 0); #else bool valid_version = s_gl_info.is_version_greater_or_equal_to(2, 0); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES if (!valid_version) { // Complain about the OpenGL version. wxString message = from_u8((boost::format( -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + _utf8(L("PrusaSlicer requires OpenGL ES 2.0 capable graphics driver to run correctly, \n" + "while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); +#elif ENABLE_GL_CORE_PROFILE _utf8(L("PrusaSlicer requires OpenGL %s capable graphics driver to run correctly, \n" "while OpenGL version %s, render %s, vendor %s was detected."))) % (s_gl_info.is_core_profile() ? "3.3" : "2.0") % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); #else _utf8(L("PrusaSlicer requires OpenGL 2.0 capable graphics driver to run correctly, \n" "while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES message += "\n"; message += _L("You may need to update your graphics card driver."); #ifdef _WIN32 @@ -345,13 +360,17 @@ bool OpenGLManager::init_gl() wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas) { if (m_context == nullptr) { -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_OPENGL_ES + wxGLContextAttrs attrs; + attrs.ES2().MajorVersion(2).EndList(); + m_context = new wxGLContext(&canvas, nullptr, &attrs); +#elif ENABLE_GL_CORE_PROFILE wxGLContextAttrs attrs; attrs.CoreProfile().ForwardCompatible().OGLVersion(3, 3).EndList(); m_context = new wxGLContext(&canvas, nullptr, &attrs); #else m_context = new wxGLContext(&canvas); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_OPENGL_ES #ifdef __APPLE__ // Part of hack to remove crash when closing the application on OSX 10.9.5 when building against newer wxWidgets @@ -365,7 +384,7 @@ wxGLContext* OpenGLManager::init_glcontext(wxGLCanvas& canvas) wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) { -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES wxGLAttributes attribList; attribList.PlatformDefaults().RGBA().DoubleBuffer().MinRGBA(8, 8, 8, 8).Depth(24).SampleBuffers(1).Samplers(4).EndList(); #else @@ -384,7 +403,7 @@ wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) WX_GL_SAMPLES, 4, 0 }; -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES if (s_multisample == EMultisampleState::Unknown) { detect_multisample(attribList); @@ -392,26 +411,26 @@ wxGLCanvas* OpenGLManager::create_wxglcanvas(wxWindow& parent) // std::cout << "Multisample " << (can_multisample() ? "enabled" : "disabled") << std::endl; } - if (!can_multisample()) -#if ENABLE_GL_CORE_PROFILE - { +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES + if (!can_multisample()) { attribList.Reset(); attribList.PlatformDefaults().RGBA().DoubleBuffer().MinRGBA(8, 8, 8, 8).Depth(24).EndList(); } return new wxGLCanvas(&parent, attribList, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS); #else + if (!can_multisample()) attribList[12] = 0; return new wxGLCanvas(&parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES } -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES void OpenGLManager::detect_multisample(const wxGLAttributes& attribList) #else void OpenGLManager::detect_multisample(int* attribList) -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES { int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; bool enable_multisample = wxVersion >= 30003; diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index 6f3b990651..fcbc54cb21 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -6,9 +6,9 @@ class wxWindow; class wxGLCanvas; class wxGLContext; -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES class wxGLAttributes; -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES namespace Slic3r { namespace GUI { @@ -49,6 +49,14 @@ public: bool is_mesa() const; #endif // _WIN32 #endif // ENABLE_OPENGL_ES + bool is_es() { + return +#if ENABLE_OPENGL_ES + true; +#else + false; +#endif // ENABLE_OPENGL_ES + } int get_max_tex_size() const; float get_max_anisotropy() const; @@ -112,11 +120,11 @@ public: static const GLInfo& get_gl_info() { return s_gl_info; } private: -#if ENABLE_GL_CORE_PROFILE +#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES static void detect_multisample(const wxGLAttributes& attribList); #else static void detect_multisample(int* attribList); -#endif // ENABLE_GL_CORE_PROFILE +#endif // ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES }; } // namespace GUI