diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index d8508129322..48376f4cb78 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -5765,7 +5765,8 @@ static std::optional top_surface_image_co zone.generic_solver_mix_model), sample_z_mm, top_surface_image_contoning_texture_sample_pitch_mm(plan), - raw_top_surface_depth_override); + raw_top_surface_depth_override, + TextureMappingZone::DefaultFilamentOverhangContrastPct); if (!offset_context) return std::nullopt; @@ -12305,7 +12306,11 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, float(this->height), std::nullopt, surface_fill.params.texture_mapping_top_surface_min_width_mm, - background); + background, + std::nullopt, + std::nullopt, + std::nullopt, + TextureMappingZone::DefaultFilamentOverhangContrastPct); } } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 7dff61f818c..b5df6263880 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -6887,7 +6887,7 @@ static float apply_texture_tone_gamma_for_gcode(float channel, float tone_gamma) return clamp01f_for_gcode(std::pow(safe_channel, 1.f / safe_gamma)); } -static void apply_texture_contrast_to_mapped_components_for_gcode(std::vector &component_weights, +static void apply_filament_overhang_contrast_to_mapped_components_for_gcode(std::vector &component_weights, float contrast_factor, size_t mapped_component_count) { @@ -6906,7 +6906,7 @@ static void apply_texture_contrast_to_mapped_components_for_gcode(std::vector apply_texture_contrast_to_rgb_for_gcode(const std::array &rgb, float contrast_factor) +static std::array apply_filament_overhang_contrast_to_rgb_for_gcode(const std::array &rgb, float contrast_factor) { const float clamped_contrast = std::clamp(contrast_factor, 0.25f, 3.f); if (std::abs(clamped_contrast - 1.f) <= 1e-5f) @@ -8277,7 +8277,7 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode( const GCodeGenericMixCandidateSet *calibrated_side_candidates, std::map *generic_mix_candidate_cache, std::map *uv_texture_triangle_cache, - float texture_contrast_pct, + float texture_filament_overhang_contrast_pct, float texture_tone_gamma, bool layer_aware_weighting, float layer_z_mm, @@ -8310,7 +8310,7 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode( const bool use_layer_weighting = layer_aware_weighting && std::isfinite(layer_z_mm); const float safe_layer_z_falloff_mm = std::max(layer_z_falloff_mm, 1e-3f); - const float contrast_factor = std::clamp(texture_contrast_pct, 25.f, 300.f) / 100.f; + const float contrast_factor = std::clamp(texture_filament_overhang_contrast_pct, 25.f, 300.f) / 100.f; const float tone_gamma = (!std::isfinite(texture_tone_gamma) || texture_tone_gamma <= 0.f) ? 1.f : std::clamp(texture_tone_gamma, 0.5f, 3.f); const float physical_sample_pitch_mm = @@ -8849,7 +8849,7 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode( target[1] = apply_texture_tone_gamma_for_gcode(target[1], tone_gamma); target[2] = apply_texture_tone_gamma_for_gcode(target[2], tone_gamma); } - target = apply_texture_contrast_to_rgb_for_gcode(target, contrast_factor); + target = apply_filament_overhang_contrast_to_rgb_for_gcode(target, contrast_factor); return effective_solver_mode == int(TextureMappingZone::GenericSolverRGB) ? target : oklab_from_srgb_for_gcode(target); @@ -9076,7 +9076,7 @@ static VertexColorOverhangWeightField build_vertex_color_weight_field_for_gcode( } if (!has_binary_dither && !has_raw_component_weights && !has_calibrated_side_candidates && std::abs(contrast_factor - 1.f) > 1e-5f) - apply_texture_contrast_to_mapped_components_for_gcode(desired, contrast_factor, mapped_component_count); + apply_filament_overhang_contrast_to_mapped_components_for_gcode(desired, contrast_factor, mapped_component_count); for (size_t component_idx = 0; component_idx < component_count; ++component_idx) { const float v = clamp01f_for_gcode(desired[component_idx]); @@ -9557,7 +9557,6 @@ std::optional GCode::texture_mapping_seam_hiding_hint(const const bool compact_offset_mode = halftone_dithering_enabled ? false : zone->compact_offset_mode || dithering_enabled; const bool nonlinear_offset_adjustment = zone->nonlinear_offset_adjustment; const bool use_legacy_fixed_color_mode = zone->use_legacy_fixed_color_mode; - const float texture_contrast_pct = std::clamp(zone->contrast_pct, 25.f, 300.f); const float texture_tone_gamma = (!std::isfinite(zone->tone_gamma) || zone->tone_gamma <= 0.f) ? 1.f : @@ -9568,6 +9567,10 @@ std::optional GCode::texture_mapping_seam_hiding_hint(const vertex_color_match_mode && !raw_texture_mapping_mode && zone->transmission_distance_calibration_mode == int(TextureMappingZone::TDCalibrationCalibratedNearestMeasuredSample); + const float texture_filament_overhang_contrast_pct = + calibrated_side_mode ? + TextureMappingZone::DefaultFilamentOverhangContrastPct : + std::clamp(zone->filament_overhang_contrast_pct, 25.f, 300.f); std::vector component_strength_factors; component_strength_factors.reserve(component_ids.size()); std::vector component_minimum_offset_factors; @@ -9652,7 +9655,7 @@ std::optional GCode::texture_mapping_seam_hiding_hint(const for (const float minimum_offset_factor : component_minimum_offset_factors) component_key_stream << "|mo" << int(std::lround(std::clamp(minimum_offset_factor, 0.f, 1.f) * 1000.f)); component_key_stream << "|lf" << (use_legacy_fixed_color_mode ? 1 : 0); - component_key_stream << "|ct" << int(std::lround(texture_contrast_pct)); + component_key_stream << "|ct" << int(std::lround(texture_filament_overhang_contrast_pct)); component_key_stream << "|tg" << int(std::lround(texture_tone_gamma * 100.f)); component_key_stream << "|hr" << (high_resolution_texture_sampling ? 1 : 0); component_key_stream << "|hs" << (high_speed_image_texture_sampling ? 1 : 0); @@ -9731,7 +9734,7 @@ std::optional GCode::texture_mapping_seam_hiding_hint(const calibrated_side_candidates_ptr, &m_generic_solver_mix_candidate_cache, &m_uv_texture_triangle_cache, - texture_contrast_pct, + texture_filament_overhang_contrast_pct, texture_tone_gamma, true, float(layer->print_z), diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index 3e018bb182a..ce059e3ca41 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -56,7 +56,7 @@ struct PrimeTowerTextureRenderSettings int generic_solver_lookup_mode = TextureMappingZone::DefaultGenericSolverLookupMode; int generic_solver_mode = TextureMappingZone::DefaultGenericSolverMode; int generic_solver_mix_model = TextureMappingZone::DefaultGenericSolverMixModel; - float contrast_pct = 100.f; + float filament_overhang_contrast_pct = TextureMappingZone::DefaultFilamentOverhangContrastPct; float tone_gamma = 1.f; float global_strength = 1.f; float max_line_width = 0.95f; @@ -573,7 +573,7 @@ private: return {}; } - static void apply_contrast(std::vector &weights, float contrast_factor, size_t mapped_count) + static void apply_filament_overhang_contrast(std::vector &weights, float contrast_factor, size_t mapped_count) { const size_t count = std::min(mapped_count, weights.size()); if (count == 0) @@ -638,7 +638,7 @@ private: if (weights.size() != component_ids.size() || component_idx >= weights.size()) return sample_image_tool_visibility(tool, u, v, back, solver_tools); - apply_contrast(weights, std::clamp(contrast_pct, 25.f, 300.f) / 100.f, mapped_count); + apply_filament_overhang_contrast(weights, std::clamp(filament_overhang_contrast_pct, 25.f, 300.f) / 100.f, mapped_count); return std::clamp(weights[component_idx], 0.f, 1.f); } diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp index 75dbe96c48d..88d87a121cb 100644 --- a/src/libslic3r/LayerRegion.cpp +++ b/src/libslic3r/LayerRegion.cpp @@ -505,8 +505,25 @@ static std::optional perimeter_texture_make_reco if (num_physical == 0) return std::nullopt; + const std::optional filament_overhang_contrast_override = + zone.top_surface_contoning_perimeters_active() ? + std::optional(TextureMappingZone::DefaultFilamentOverhangContrastPct) : + std::nullopt; std::optional context = - build_texture_mapping_offset_context_for_layer(*print_object, *layer, zone, texture_zone_id, 0, base_outer_width_mm); + build_texture_mapping_offset_context_for_layer(*print_object, + *layer, + zone, + texture_zone_id, + 0, + base_outer_width_mm, + std::nullopt, + std::nullopt, + std::nullopt, + std::nullopt, + std::nullopt, + std::nullopt, + std::nullopt, + filament_overhang_contrast_override); if (!context || print->canceled() || context->component_ids.empty()) return std::nullopt; @@ -2598,7 +2615,17 @@ static SurfaceCollection perimeter_path_modulated_surfaces(const LayerRegion zone, texture_zone_id, 0, - base_outer_width_mm); + base_outer_width_mm, + std::nullopt, + std::nullopt, + std::nullopt, + std::nullopt, + std::nullopt, + std::nullopt, + std::nullopt, + zone.top_surface_contoning_perimeters_active() ? + std::optional(TextureMappingZone::DefaultFilamentOverhangContrastPct) : + std::nullopt); if (!built_context) return slices; context = &*built_context; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index b5380f6cf5e..f136feb12c1 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -3510,7 +3510,10 @@ void Print::_make_wipe_tower() texture.generic_solver_lookup_mode = settings_zone->generic_solver_lookup_mode; texture.generic_solver_mode = settings_zone->generic_solver_mode; texture.generic_solver_mix_model = settings_zone->generic_solver_mix_model; - texture.contrast_pct = settings_zone->contrast_pct; + texture.filament_overhang_contrast_pct = + settings_zone->transmission_distance_calibration_mode == int(TextureMappingZone::TDCalibrationCalibratedNearestMeasuredSample) ? + TextureMappingZone::DefaultFilamentOverhangContrastPct : + settings_zone->filament_overhang_contrast_pct; texture.tone_gamma = settings_zone->tone_gamma; texture.filament_strengths_pct = settings_zone->filament_strengths_pct; texture.filament_minimum_offsets_pct = settings_zone->filament_minimum_offsets_pct; diff --git a/src/libslic3r/TextureMapping.cpp b/src/libslic3r/TextureMapping.cpp index 9d5899b1e0e..ab3959645e6 100644 --- a/src/libslic3r/TextureMapping.cpp +++ b/src/libslic3r/TextureMapping.cpp @@ -2451,7 +2451,7 @@ bool TextureMappingZone::operator==(const TextureMappingZone &rhs) const dithering_method == rhs.dithering_method && std::abs(dithering_resolution_mm - rhs.dithering_resolution_mm) <= eps && std::abs(halftone_dot_size_mm - rhs.halftone_dot_size_mm) <= eps && - std::abs(contrast_pct - rhs.contrast_pct) <= eps && + std::abs(filament_overhang_contrast_pct - rhs.filament_overhang_contrast_pct) <= eps && high_resolution_sampling == rhs.high_resolution_sampling && std::abs(tone_gamma - rhs.tone_gamma) <= eps && transmission_distance_calibration_mode == rhs.transmission_distance_calibration_mode && @@ -2894,7 +2894,11 @@ std::string TextureMappingManager::serialize_entries() std::clamp(finite_or(zone.halftone_dot_size_mm, TextureMappingZone::DefaultHalftoneDotSizeMm), TextureMappingZone::MinHalftoneDotSizeMm, TextureMappingZone::MaxHalftoneDotSizeMm); - texture["contrast_pct"] = std::clamp(finite_or(zone.contrast_pct, 100.f), 25.f, 300.f); + texture["filament_overhang_contrast_pct"] = + std::clamp(finite_or(zone.filament_overhang_contrast_pct, + TextureMappingZone::DefaultFilamentOverhangContrastPct), + 25.f, + 300.f); texture["high_resolution_sampling"] = true; texture["tone_gamma"] = normalize_tone_gamma(zone.tone_gamma); texture["transmission_distance_calibration"] = @@ -3284,7 +3288,12 @@ void TextureMappingManager::load_entries(const std::string &serialized, TextureMappingZone::MaxHalftoneDotSizeMm); if (zone.dithering_enabled) zone.compact_offset_mode = true; - zone.contrast_pct = std::clamp(texture.value("contrast_pct", 100.f), 25.f, 300.f); + zone.filament_overhang_contrast_pct = + std::clamp(texture.value("filament_overhang_contrast_pct", + texture.value("contrast_pct", + TextureMappingZone::DefaultFilamentOverhangContrastPct)), + 25.f, + 300.f); zone.high_resolution_sampling = true; zone.tone_gamma = normalize_tone_gamma(texture.value("tone_gamma", 1.f)); zone.transmission_distance_calibration_mode = transmission_distance_calibration_mode_from_json(texture); diff --git a/src/libslic3r/TextureMapping.hpp b/src/libslic3r/TextureMapping.hpp index f6b68015f4e..44a411415cc 100644 --- a/src/libslic3r/TextureMapping.hpp +++ b/src/libslic3r/TextureMapping.hpp @@ -259,7 +259,7 @@ struct TextureMappingZone static constexpr float MinHalftoneDotSizeMm = 0.08f; static constexpr float MaxHalftoneDotSizeMm = 50.f; static constexpr float DefaultHalftoneDotSizeMm = 2.f; - static constexpr float DefaultContrastPct = 100.f; + static constexpr float DefaultFilamentOverhangContrastPct = 100.f; static constexpr bool DefaultHighResolutionSampling = true; static constexpr float DefaultToneGamma = 1.f; static constexpr int DefaultTransmissionDistanceCalibrationMode = int(TDCalibrationAbsolute); @@ -533,7 +533,7 @@ struct TextureMappingZone int dithering_method = DefaultDitheringMethod; float dithering_resolution_mm = DefaultDitheringResolutionMm; float halftone_dot_size_mm = DefaultHalftoneDotSizeMm; - float contrast_pct = DefaultContrastPct; + float filament_overhang_contrast_pct = DefaultFilamentOverhangContrastPct; bool high_resolution_sampling = DefaultHighResolutionSampling; float tone_gamma = DefaultToneGamma; int transmission_distance_calibration_mode = DefaultTransmissionDistanceCalibrationMode; @@ -840,7 +840,7 @@ struct TextureMappingZone dithering_method = DefaultDitheringMethod; dithering_resolution_mm = DefaultDitheringResolutionMm; halftone_dot_size_mm = DefaultHalftoneDotSizeMm; - contrast_pct = DefaultContrastPct; + filament_overhang_contrast_pct = DefaultFilamentOverhangContrastPct; high_resolution_sampling = DefaultHighResolutionSampling; tone_gamma = DefaultToneGamma; transmission_distance_calibration_mode = DefaultTransmissionDistanceCalibrationMode; diff --git a/src/libslic3r/TextureMappingOffset.cpp b/src/libslic3r/TextureMappingOffset.cpp index 5868f7bac9a..0978333373b 100644 --- a/src/libslic3r/TextureMappingOffset.cpp +++ b/src/libslic3r/TextureMappingOffset.cpp @@ -1013,7 +1013,7 @@ float apply_texture_tone_gamma(float channel, float tone_gamma) return clamp01f(std::pow(safe_channel, 1.f / safe_gamma)); } -void apply_texture_contrast_to_components(std::vector &component_weights, +void apply_filament_overhang_contrast_to_components(std::vector &component_weights, float contrast_factor, size_t mapped_component_count) { @@ -1032,7 +1032,7 @@ void apply_texture_contrast_to_components(std::vector &component_weights, } } -std::array apply_texture_contrast_to_rgb(const std::array &rgb, float contrast_factor) +std::array apply_filament_overhang_contrast_to_rgb(const std::array &rgb, float contrast_factor) { const float clamped_contrast = std::clamp(contrast_factor, 0.25f, 3.f); if (std::abs(clamped_contrast - 1.f) <= 1e-5f) @@ -1058,7 +1058,7 @@ std::array texture_sample_target_rgb(const WeightedTextureSample &samp target[1] = apply_texture_tone_gamma(target[1], tone_gamma); target[2] = apply_texture_tone_gamma(target[2], tone_gamma); } - return apply_texture_contrast_to_rgb(target, contrast_factor); + return apply_filament_overhang_contrast_to_rgb(target, contrast_factor); } std::array generic_solver_oklab_axis_weights(const std::array &target_oklab) @@ -1696,7 +1696,7 @@ std::vector component_weights_for_sample(const WeightedTextureSample &sam } if (!has_raw_component_weights && !has_calibrated_side_candidates && std::abs(contrast_factor - 1.f) > 1e-5f) - apply_texture_contrast_to_components(desired, contrast_factor, mapped_component_count); + apply_filament_overhang_contrast_to_components(desired, contrast_factor, mapped_component_count); for (float &v : desired) v = clamp01f(v); return desired; @@ -1720,7 +1720,7 @@ TextureMappingOffsetWeightField build_texture_mapping_offset_weight_field(const float dither_cell_size_mm, const std::vector& component_strength_factors, const std::vector& component_minimum_offset_factors, - float texture_contrast_pct, + float texture_filament_overhang_contrast_pct, float texture_tone_gamma, float layer_z_mm, float layer_z_falloff_mm, @@ -1754,7 +1754,7 @@ TextureMappingOffsetWeightField build_texture_mapping_offset_weight_field(const return {}; const float safe_layer_z_falloff_mm = std::max(layer_z_falloff_mm, 1e-3f); - const float contrast_factor = std::clamp(texture_contrast_pct, 25.f, 300.f) / 100.f; + const float contrast_factor = std::clamp(texture_filament_overhang_contrast_pct, 25.f, 300.f) / 100.f; const float tone_gamma = (!std::isfinite(texture_tone_gamma) || texture_tone_gamma <= 0.f) ? 1.f : std::clamp(texture_tone_gamma, 0.5f, 3.f); const float default_physical_sample_pitch_mm = @@ -3446,7 +3446,8 @@ std::optional build_texture_mapping_offset_context_ std::optional> image_background_rgba_override, std::optional sample_z_mm_override, std::optional texture_sample_pitch_mm_override, - std::optional raw_top_surface_depth_override) + std::optional raw_top_surface_depth_override, + std::optional filament_overhang_contrast_pct_override) { const Print *print = print_object.print(); if (print == nullptr) @@ -3502,7 +3503,10 @@ std::optional build_texture_mapping_offset_context_ const int generic_solver_mix_model = std::clamp(zone.generic_solver_mix_model, int(TextureMappingZone::GenericSolverPigmentPainter), int(TextureMappingZone::GenericSolverPrusaFdmMixer)); - const float texture_contrast_pct = std::clamp(zone.contrast_pct, 25.f, 300.f); + const float requested_filament_overhang_contrast_pct = + filament_overhang_contrast_pct_override ? + *filament_overhang_contrast_pct_override : + zone.filament_overhang_contrast_pct; const float texture_tone_gamma = (!std::isfinite(zone.tone_gamma) || zone.tone_gamma <= 0.f) ? 1.f : @@ -3631,6 +3635,10 @@ std::optional build_texture_mapping_offset_context_ vertex_color_match_mode && !raw_texture_mapping_mode && zone.transmission_distance_calibration_mode == int(TextureMappingZone::TDCalibrationCalibratedNearestMeasuredSample); + const float texture_filament_overhang_contrast_pct = + calibrated_side_mode ? + TextureMappingZone::DefaultFilamentOverhangContrastPct : + std::clamp(requested_filament_overhang_contrast_pct, 25.f, 300.f); std::vector component_strength_factors; component_strength_factors.reserve(component_ids.size()); std::vector component_minimum_offset_factors; @@ -3670,7 +3678,7 @@ std::optional build_texture_mapping_offset_context_ generic_solver_lookup_mode, generic_solver_mode, generic_solver_mix_model, zone.use_legacy_fixed_color_mode, dithering_enabled, dithering_method, dither_pitch_mm, dither_cell_size_mm, component_strength_factors, - component_minimum_offset_factors, texture_contrast_pct, texture_tone_gamma, + component_minimum_offset_factors, texture_filament_overhang_contrast_pct, texture_tone_gamma, sample_z_mm, layer_sample_falloff_mm, high_resolution_texture_sampling, zone.high_speed_image_texture_sampling, texture_sample_pitch_mm_override, image_background_rgba_override, calibrated_side_candidates_ptr, diff --git a/src/libslic3r/TextureMappingOffset.hpp b/src/libslic3r/TextureMappingOffset.hpp index 6a8c377bdf3..4877b36eaba 100644 --- a/src/libslic3r/TextureMappingOffset.hpp +++ b/src/libslic3r/TextureMappingOffset.hpp @@ -121,7 +121,8 @@ std::optional build_texture_mapping_offset_context_ std::optional> image_background_rgba_override = std::nullopt, std::optional sample_z_mm_override = std::nullopt, std::optional texture_sample_pitch_mm_override = std::nullopt, - std::optional raw_top_surface_depth_override = std::nullopt); + std::optional raw_top_surface_depth_override = std::nullopt, + std::optional filament_overhang_contrast_pct_override = std::nullopt); std::vector sample_weight_field_components(const TextureMappingOffsetWeightField &weight_field, float x_mm, diff --git a/src/slic3r/GUI/MMUPaintedTexturePreview.cpp b/src/slic3r/GUI/MMUPaintedTexturePreview.cpp index c2bf675b9e2..2784385c0df 100644 --- a/src/slic3r/GUI/MMUPaintedTexturePreview.cpp +++ b/src/slic3r/GUI/MMUPaintedTexturePreview.cpp @@ -90,7 +90,7 @@ struct TexturePreviewSimulationSettings float dithering_resolution_mm = TextureMappingZone::DefaultDitheringResolutionMm; float halftone_dot_size_mm = TextureMappingZone::DefaultHalftoneDotSizeMm; float texture_preview_mm_per_pixel = TextureMappingZone::DefaultDitheringResolutionMm; - float contrast_pct = 100.f; + float filament_overhang_contrast_pct = TextureMappingZone::DefaultFilamentOverhangContrastPct; float tone_gamma = 1.f; int generic_solver_lookup_mode = int(TextureMappingZone::GenericSolverClosestMix); int generic_solver_mode = TextureMappingZone::DefaultGenericSolverMode; @@ -2311,7 +2311,7 @@ float apply_texture_tone_gamma(float channel, float tone_gamma) return clamp01(std::pow(safe_channel, 1.f / safe_gamma)); } -void apply_texture_contrast_to_mapped_components(std::vector &component_weights, +void apply_filament_overhang_contrast_to_mapped_components(std::vector &component_weights, float contrast_factor, size_t mapped_component_count) { @@ -2330,7 +2330,7 @@ void apply_texture_contrast_to_mapped_components(std::vector &component_w } } -std::array apply_texture_contrast_to_rgb(const std::array &rgb, float contrast_factor) +std::array apply_filament_overhang_contrast_to_rgb(const std::array &rgb, float contrast_factor) { const float clamped_contrast = std::clamp(contrast_factor, 0.25f, 3.f); if (std::abs(clamped_contrast - 1.f) <= 1e-5f) @@ -2482,7 +2482,7 @@ std::array texture_preview_target_rgb(const TexturePreviewSimulationSe target[1] = apply_texture_tone_gamma(target[1], settings.tone_gamma); target[2] = apply_texture_tone_gamma(target[2], settings.tone_gamma); } - return apply_texture_contrast_to_rgb(target, std::clamp(settings.contrast_pct, 25.f, 300.f) / 100.f); + return apply_filament_overhang_contrast_to_rgb(target, std::clamp(settings.filament_overhang_contrast_pct, 25.f, 300.f) / 100.f); } std::array texture_preview_target_color(const TexturePreviewSimulationSettings &settings, @@ -2936,10 +2936,10 @@ std::vector component_weights_for_texture_preview(const TexturePreviewSim } } - const float contrast_factor = std::clamp(settings.contrast_pct, 25.f, 300.f) / 100.f; + const float contrast_factor = std::clamp(settings.filament_overhang_contrast_pct, 25.f, 300.f) / 100.f; if (!texture_preview_has_side_surface_calibrated_candidates(settings) && std::abs(contrast_factor - 1.f) > 1e-5f) - apply_texture_contrast_to_mapped_components(desired, contrast_factor, mapped_component_count); + apply_filament_overhang_contrast_to_mapped_components(desired, contrast_factor, mapped_component_count); if (!texture_preview_has_side_surface_calibrated_candidates(settings) && settings.compact_offset_mode) { @@ -2972,6 +2972,7 @@ std::array fallback_contoning_flat_surface_rgb_for_texture_preview( local_settings.dithering_enabled = false; local_settings.compact_offset_mode = false; local_settings.contoning_flat_surface_quantization = false; + local_settings.filament_overhang_contrast_pct = TextureMappingZone::DefaultFilamentOverhangContrastPct; std::vector continuous_weights = component_weights_for_texture_preview(local_settings, sample_rgba, false); continuous_weights.resize(component_count, 0.f); @@ -2982,7 +2983,7 @@ std::array fallback_contoning_flat_surface_rgb_for_texture_preview( } if (total_weight <= k_epsilon) { - const std::array target_rgb = texture_preview_target_rgb(settings, sample_rgba); + const std::array target_rgb = texture_preview_target_rgb(local_settings, sample_rgba); const std::array target_oklab = oklab_from_srgb(target_rgb); const std::array axis_weights = { 1.f, 4.f, 4.f }; size_t best_idx = 0; @@ -3044,7 +3045,9 @@ std::array contoning_flat_surface_rgb_for_texture_preview( int root, int total_units) { - const std::array target_rgb = texture_preview_target_rgb(settings, sample_rgba); + TexturePreviewSimulationSettings local_settings = settings; + local_settings.filament_overhang_contrast_pct = TextureMappingZone::DefaultFilamentOverhangContrastPct; + const std::array target_rgb = texture_preview_target_rgb(local_settings, sample_rgba); if (settings.contoning_flat_surface_td_adjustment && !ordered_candidates.empty()) { const std::vector surface_to_deep = solve_color_solver_ordered_stack_for_target(ordered_candidates, target_rgb, ColorSolverMode::OklabSoftCap4Dark4); @@ -3079,7 +3082,7 @@ std::array contoning_flat_surface_rgb_for_texture_preview( if (nearest.best_idx < candidates.size()) return candidates[nearest.best_idx].rgb; } - return fallback_contoning_flat_surface_rgb_for_texture_preview(settings, sample_rgba, total_units); + return fallback_contoning_flat_surface_rgb_for_texture_preview(local_settings, sample_rgba, total_units); } std::vector raw_offset_print_width_weights_for_texture_preview(const TexturePreviewSimulationSettings &settings, @@ -3203,7 +3206,10 @@ std::optional texture_preview_simulation_setti settings.compact_offset_mode = halftone_dithering_enabled ? false : zone->compact_offset_mode || settings.dithering_enabled; settings.use_legacy_fixed_color_mode = zone->use_legacy_fixed_color_mode; - settings.contrast_pct = std::clamp(zone->contrast_pct, 25.f, 300.f); + settings.filament_overhang_contrast_pct = + zone->transmission_distance_calibration_mode == int(TextureMappingZone::TDCalibrationCalibratedNearestMeasuredSample) ? + TextureMappingZone::DefaultFilamentOverhangContrastPct : + std::clamp(zone->filament_overhang_contrast_pct, 25.f, 300.f); settings.tone_gamma = (!std::isfinite(zone->tone_gamma) || zone->tone_gamma <= 0.f) ? 1.f : std::clamp(zone->tone_gamma, 0.5f, 3.f); @@ -3408,7 +3414,7 @@ size_t texture_preview_simulation_signature(const ModelVolume &model_volume, if (settings.contoning_flat_surface_calibrated_stack_model.valid()) mix(std::hash{}(settings.contoning_flat_surface_calibrated_stack_model.cache_key())); } - mix(std::hash{}(int(std::lround(settings.contrast_pct * 100.f)))); + mix(std::hash{}(int(std::lround(settings.filament_overhang_contrast_pct * 100.f)))); mix(std::hash{}(int(std::lround(settings.tone_gamma * 1000.f)))); mix(std::hash{}(int(std::lround(settings.minimum_visibility_offset_factor * 100000.f)))); for (const unsigned int id : settings.component_ids) @@ -4279,6 +4285,8 @@ const GUI::GLTexture *simulated_texture_preview_texture_for_filament(const Model contoning_flat_surface_raw_top_stack_preview && contoning_flat_surface_quantization && model_volume_has_raw_top_surface_stack_preview_data_for_zone_impl(model_volume, *zone); + if (settings->contoning_flat_surface_quantization || settings->contoning_flat_surface_pattern_blend) + settings->filament_overhang_contrast_pct = TextureMappingZone::DefaultFilamentOverhangContrastPct; if ((contoning_flat_surface_quantization || contoning_flat_surface_pattern_blend) && zone->texture_mapping_mode == int(TextureMappingZone::TextureMappingRawValues) && !settings->contoning_flat_surface_raw_top_stack_preview) @@ -6456,7 +6464,10 @@ static size_t texture_preview_settings_signature_impl(size_t num_physical, signature_mix(std::hash{}(zone.generic_solver_lookup_mode)); signature_mix(std::hash{}(zone.generic_solver_mode)); signature_mix(std::hash{}(TextureMappingZone::DefaultGenericSolverMixModel)); - signature_mix_float(zone.contrast_pct, 100.f); + signature_mix_float(zone.transmission_distance_calibration_mode == int(TextureMappingZone::TDCalibrationCalibratedNearestMeasuredSample) ? + TextureMappingZone::DefaultFilamentOverhangContrastPct : + zone.filament_overhang_contrast_pct, + 100.f); signature_mix_float(zone.tone_gamma); for (const float strength_pct : zone.filament_strengths_pct) signature_mix_float(strength_pct, 100.f); @@ -6618,7 +6629,10 @@ static void texture_preview_mix_zone_baked_model_settings(size_t &signature, signature_mix(std::hash{}(zone.generic_solver_lookup_mode)); signature_mix(std::hash{}(zone.generic_solver_mode)); signature_mix(std::hash{}(TextureMappingZone::DefaultGenericSolverMixModel)); - signature_mix_float(zone.contrast_pct, 100.f); + signature_mix_float(zone.transmission_distance_calibration_mode == int(TextureMappingZone::TDCalibrationCalibratedNearestMeasuredSample) ? + TextureMappingZone::DefaultFilamentOverhangContrastPct : + zone.filament_overhang_contrast_pct, + 100.f); signature_mix_float(zone.tone_gamma); signature_mix(std::hash{}(zone.linear_gradient_mode)); signature_mix_float(zone.linear_gradient_radius_mm, 1000.f); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e3ff52c7bec..c18d2035ee8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2495,6 +2495,7 @@ public: const std::vector &component_transmission_distances_mm, int transmission_distance_calibration_mode, float tone_gamma, + float filament_overhang_contrast_pct, bool force_sequential_filaments, bool auto_adjust_filament_selection, bool reduce_outer_surface_texture, @@ -2955,6 +2956,25 @@ public: m_nonlinear_offset_adjustment_checkbox->SetToolTip( _L("Adjusts line-width offsets using a surface-visibility model derived from Kuipers et al. 2018.")); experimental_box->Add(m_nonlinear_offset_adjustment_checkbox, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, gap); + auto *filament_overhang_contrast_row = new wxBoxSizer(wxHORIZONTAL); + filament_overhang_contrast_row->Add(new wxStaticText(experimental_page, wxID_ANY, _L("Filament overhang contrast")), + 0, + wxALIGN_CENTER_VERTICAL | wxRIGHT, + gap); + m_filament_overhang_contrast_spin = new wxSpinCtrl(experimental_page, + wxID_ANY, + wxEmptyString, + wxDefaultPosition, + wxSize(FromDIP(70), -1), + wxSP_ARROW_KEYS | wxALIGN_RIGHT, + 25, + 300, + std::clamp(int(std::lround(filament_overhang_contrast_pct)), 25, 300)); + m_filament_overhang_contrast_spin->Enable( + transmission_distance_calibration_mode != int(TextureMappingZone::TDCalibrationCalibratedNearestMeasuredSample)); + filament_overhang_contrast_row->Add(m_filament_overhang_contrast_spin, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap / 2); + filament_overhang_contrast_row->Add(new wxStaticText(experimental_page, wxID_ANY, _L("%")), 0, wxALIGN_CENTER_VERTICAL); + experimental_box->Add(filament_overhang_contrast_row, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, gap); m_compact_offset_mode_checkbox = new wxCheckBox(experimental_page, wxID_ANY, _L("Compact Offset Mode")); m_compact_offset_mode_checkbox->SetValue(compact_offset_mode); m_compact_offset_mode_checkbox->SetToolTip( @@ -3841,6 +3861,13 @@ public: } float tone_gamma() const { return float(std::clamp(m_tone_gamma_spin ? m_tone_gamma_spin->GetValue() : 1.0, 0.5, 3.0)); } + float filament_overhang_contrast_pct() const + { + const int value = m_filament_overhang_contrast_spin != nullptr ? + m_filament_overhang_contrast_spin->GetValue() : + int(TextureMappingZone::DefaultFilamentOverhangContrastPct); + return float(std::clamp(value, 25, 300)); + } int transmission_distance_calibration_mode() const { if (m_transmission_distance_calibration_mode_choice == nullptr) @@ -5016,6 +5043,8 @@ private: for (wxSpinCtrl *spin : m_strength_spins) if (spin) spin->Enable(manual_controls_enabled); + if (m_filament_overhang_contrast_spin != nullptr) + m_filament_overhang_contrast_spin->Enable(manual_controls_enabled); if (m_strength_offsets_reset_button != nullptr) m_strength_offsets_reset_button->Enable(manual_controls_enabled); if (m_strength_offsets_panel != nullptr) @@ -5708,6 +5737,7 @@ private: wxCheckBox *m_reduce_outer_surface_texture_checkbox {nullptr}; wxCheckBox *m_seam_hiding_checkbox {nullptr}; wxCheckBox *m_nonlinear_offset_adjustment_checkbox {nullptr}; + wxSpinCtrl *m_filament_overhang_contrast_spin {nullptr}; wxCheckBox *m_use_modulated_overhang_geometry_for_support_checkbox {nullptr}; wxChoice *m_modulation_mode_choice {nullptr}; std::vector m_modulation_mode_choice_values; @@ -10128,22 +10158,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) mode_row->Add(mode_choice, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap); editor_sizer->Add(mode_row, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, gap); - auto *contrast_row = new wxWrapSizer(wxHORIZONTAL, wxWRAPSIZER_DEFAULT_FLAGS); - contrast_row->Add(new wxStaticText(editor, wxID_ANY, _L("Texture contrast")), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap); - auto *contrast_spin = new ::SpinInput(editor, - wxEmptyString, - wxEmptyString, - wxDefaultPosition, - wxSize(FromDIP(86), -1), - wxSP_ARROW_KEYS, - 25, - 300, - std::clamp(int(std::lround(entry.contrast_pct)), 25, 300), - 5); - contrast_row->Add(contrast_spin, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap / 2); - contrast_row->Add(new wxStaticText(editor, wxID_ANY, _L("%")), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap); - editor_sizer->Add(contrast_row, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, gap); - ::CheckBox *preview_colors_chk = nullptr; auto *preview_colors_row = make_sidebar_checkbox_row(editor, preview_colors_chk, @@ -10178,7 +10192,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) linear_gradient_stops_bar, linear_gradient_mode_choice, linear_gradient_radius_spin, linear_gradient_radius_percent_chk, surface_pattern_from_selection, linear_gradient_mode_from_selection, mode_choice, - show_direction_arrow_chk, contrast_spin, apply_zone, update_color_calibration_warning_text]() { + show_direction_arrow_chk, apply_zone, update_color_calibration_warning_text]() { if (mgr_ptr == nullptr) return; auto &rows = mgr_ptr->zones(); @@ -10228,7 +10242,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) texture_mapping_color_mode_from_selection(mode_choice->GetSelection(), updated.filament_color_mode) : updated.filament_color_mode; updated.show_linear_gradient_direction_arrow = show_direction_arrow_chk != nullptr && show_direction_arrow_chk->GetValue(); - updated.contrast_pct = contrast_spin != nullptr ? std::clamp(float(contrast_spin->GetValue()), 25.f, 300.f) : updated.contrast_pct; updated.high_resolution_sampling = true; update_color_calibration_warning_text(updated); apply_zone(std::move(updated)); @@ -10244,17 +10257,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) }); } - contrast_spin->Bind(wxEVT_CHAR_HOOK, [contrast_spin, apply_controls](wxKeyEvent &evt) { - const int key = evt.GetKeyCode(); - if (key == WXK_UP || key == WXK_NUMPAD_UP || key == WXK_DOWN || key == WXK_NUMPAD_DOWN) { - const int direction = (key == WXK_UP || key == WXK_NUMPAD_UP) ? 1 : -1; - contrast_spin->SetValue(std::clamp(contrast_spin->GetValue() + direction * 5, 25, 300)); - apply_controls(); - return; - } - evt.Skip(); - }); - auto update_pattern_visibility = [this, editor_sizer, filaments_row, linear_gradient_mode_row, linear_gradient_mode_choice, linear_gradient_stops_bar, linear_gradient_row, linear_gradient_point_row, linear_gradient_buttons_row, linear_gradient_radius_row, show_direction_arrow_row, mode_row, contrast_row, preview_colors_row, color_calibration_warning_text, offset_btn, advanced_btn, surface_choice, row, editor, update_texture_mapping_area_height, set_linear_gradient_picker_button_labels, sync_linear_gradient_stop_controls]() { + auto update_pattern_visibility = [this, editor_sizer, filaments_row, linear_gradient_mode_row, linear_gradient_mode_choice, linear_gradient_stops_bar, linear_gradient_row, linear_gradient_point_row, linear_gradient_buttons_row, linear_gradient_radius_row, show_direction_arrow_row, mode_row, preview_colors_row, color_calibration_warning_text, offset_btn, advanced_btn, surface_choice, row, editor, update_texture_mapping_area_height, set_linear_gradient_picker_button_labels, sync_linear_gradient_stop_controls]() { const int selection = surface_choice == nullptr ? 0 : surface_choice->GetSelection(); const bool image_texture = selection == 0; const bool linear_gradient = selection == 1; @@ -10269,7 +10272,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) editor_sizer->Show(linear_gradient_radius_row, radial_gradient, true); editor_sizer->Show(show_direction_arrow_row, linear_gradient, true); editor_sizer->Show(mode_row, image_texture, true); - editor_sizer->Show(contrast_row, image_texture, true); editor_sizer->Show(preview_colors_row, image_texture, true); if (color_calibration_warning_text != nullptr) editor_sizer->Show(color_calibration_warning_text, !color_calibration_warning_text->GetLabel().empty(), true); @@ -10344,7 +10346,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) linear_gradient_mode_from_selection, mode_choice, surface_choice, - contrast_spin, set_sidebar_checkbox_value, update_color_calibration_warning_text, surface_pattern_from_selection, @@ -10405,7 +10406,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) updated.filament_color_mode = mode_choice != nullptr ? texture_mapping_color_mode_from_selection(mode_choice->GetSelection(), updated.filament_color_mode) : updated.filament_color_mode; - updated.contrast_pct = contrast_spin != nullptr ? std::clamp(float(contrast_spin->GetValue()), 25.f, 300.f) : updated.contrast_pct; updated.high_resolution_sampling = true; if (updated.is_image_texture() && updated.auto_adjust_filament_selection) { @@ -10484,12 +10484,6 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) evt.Skip(); }); } - contrast_spin->Bind(wxEVT_SPINCTRL, [apply_controls](wxCommandEvent &) { apply_controls(); }); - contrast_spin->Bind(wxEVT_TEXT_ENTER, [apply_controls](wxCommandEvent &) { apply_controls(); }); - contrast_spin->Bind(wxEVT_KILL_FOCUS, [apply_controls](wxFocusEvent &evt) { - apply_controls(); - evt.Skip(); - }); auto make_linear_gradient_anchor = [this](const GLGizmoTextureGradientPointPicker::Pick &pick) { TextureMappingZone::LinearGradientAnchor anchor; anchor.valid = true; @@ -10840,6 +10834,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) transmission_distances, updated.transmission_distance_calibration_mode, updated.tone_gamma, + updated.filament_overhang_contrast_pct, updated.force_sequential_filaments, updated.auto_adjust_filament_selection, updated.reduce_outer_surface_texture, @@ -10927,6 +10922,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) } updated.texture_mapping_mode = dlg.texture_mapping_mode(); updated.tone_gamma = dlg.tone_gamma(); + updated.filament_overhang_contrast_pct = dlg.filament_overhang_contrast_pct(); updated.transmission_distance_calibration_mode = dlg.transmission_distance_calibration_mode(); updated.force_sequential_filaments = dlg.force_sequential_filaments(); if (updated.force_sequential_filaments && ids.size() >= 2) {