Compare commits

...
Author SHA1 Message Date
Hanif Koh e266c7b234 Draw the Toolpaths Top-Down When the Camera Looks Down on the Print
The segments come in print order, bottom layer first, which seen from above is back to
front: every hidden fragment is shaded before the one that covers it, and on an integrated
GPU that overdraw is most of the frame. Drawing the instances last to first whenever the
camera looks down lets the depth test reject the hidden fragments instead. Side views and
views from below keep the print order, and the shadow-caster pass is unchanged.
2026-09-25 03:29:25 +08:00
Kris Austin 0db1dc6480 build: keep header dependencies through a compiler cache hit on clang-cl (#15875)
For clang-cl, CMake sets the depfile flags to the gcc-style -MD, -MT and -MF,
passed through as -clang: arguments. ccache does not parse those, so a cache
hit writes only the object. Ninja has no depfile to read, so it records zero
header dependencies for that object and does not rebuild it after a header
edit. The stale object is still linked into the library and the DLL. sccache
0.15.0 reproduces the depfile on a hit and is unaffected.

Use /showIncludes instead. CMake already does that for MSVC, and ccache
reproduces it on a hit. A make-rules override sets the flags, because CMake
includes the override after Platform/Windows-Clang.cmake. It is forwarded to
each dependency because every one configures as its own CMake project, and it
is only set when the file exists, because scripts/flatpak/make_deps_tar.sh
packs deps/ alone.

In a build with a warm cache, 678 of 790 objects had no recorded headers.
Object code does not change. One GUI translation unit compiled both ways is
byte-identical apart from the COFF timestamp.
2026-09-24 14:06:24 -03:00
Kris Austin 42009cf385 fix: Linux Flatpak crash rendering plate thumbnails while slicing or saving (#15873) 2026-09-24 13:41:56 -03:00
Kris Austin 9859d788d4 fix: installed vendor profiles only update when OTA is enabled (#15831)
* preset updater: refresh installed vendors from resources regardless of enable_ota

Since c4fea8ad24 the resources check in check_installed_vendor_profiles()
sat behind enabled_config_update, which now follows enable_ota, a hidden
flag that defaults to off. The hotfix a93c6ea67b then made that gate skip
installed vendors entirely, so a new build's newer vendor profiles were
never installed over an existing vendor unless OTA had been turned on.
Before the gating the update URL always had a default, so the comparison
effectively always ran.

The resources shipped with a build are not an over-the-air update. Judge
installed vendors against them, and drop the ones no longer enabled,
regardless of the flag; enable_ota keeps gating the online sync.

* preset updater: stop reinstalling the filament library on every launch

check_installed_vendor_profiles() put OrcaFilamentLibrary on the install
list unconditionally, so every launch recopied the whole vendor from
resources and, in a build that ships the profile JSONs rather than a
preset cache, then re-parsed and re-cached it: about 0.3 s of a dev
build's startup, and a 3 MB copy in a release build, for a vendor that
had not changed.

The library was special-cased because it is never in the enabled-vendor
list. Treat it like the default bundle instead: always wanted, and
reinstalled only when the resources carry a newer version.
2026-09-24 09:05:41 -03:00
9 changed files with 75 additions and 23 deletions
+3
View File
@@ -70,6 +70,9 @@ if (POLICY CMP0092)
cmake_policy(SET CMP0092 NEW)
endif ()
# project() reads this, so set it first.
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/ClangClShowIncludes.cmake")
project(OrcaSlicer)
# Backward compatibility for old CMake versions
+10
View File
@@ -0,0 +1,10 @@
# ccache does not parse the -clang: arguments CMake uses for clang-cl's gcc-style
# depfile, so a cache hit writes the object and no depfile, and Ninja then records
# no headers for that object. ccache reproduces /showIncludes output on a hit.
foreach (_lang C CXX)
if (CMAKE_${_lang}_COMPILER_ID STREQUAL "Clang" AND
CMAKE_${_lang}_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
set(CMAKE_DEPFILE_FLAGS_${_lang} "/showIncludes")
set(CMAKE_${_lang}_DEPFILE_FORMAT msvc)
endif ()
endforeach ()
+10
View File
@@ -38,6 +38,14 @@ if(POLICY CMP0135) # DOWNLOAD_EXTRACT_TIMESTAMP
cmake_policy(SET CMP0135 NEW)
endif()
# project() reads this, so set it first. scripts/flatpak/make_deps_tar.sh packs deps/
# without cmake/, so the file is missing in a Flatpak build.
set(_rules_override "${CMAKE_CURRENT_LIST_DIR}/../cmake/modules/ClangClShowIncludes.cmake")
if (EXISTS "${_rules_override}")
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_rules_override}")
endif ()
unset(_rules_override)
project(OrcaSlicer-deps)
# Backward compatibility for old CMake versions
@@ -220,6 +228,7 @@ if (NOT IS_CROSS_COMPILE OR NOT APPLE)
-DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER}
-DCMAKE_C_COMPILER_LAUNCHER:STRING=${CMAKE_C_COMPILER_LAUNCHER}
-DCMAKE_CXX_COMPILER_LAUNCHER:STRING=${CMAKE_CXX_COMPILER_LAUNCHER}
-DCMAKE_USER_MAKE_RULES_OVERRIDE:STRING=${CMAKE_USER_MAKE_RULES_OVERRIDE}
-DCMAKE_TOOLCHAIN_FILE:STRING=${CMAKE_TOOLCHAIN_FILE}
-DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS}
-DCMAKE_SHARED_LINKER_FLAGS:STRING=${CMAKE_SHARED_LINKER_FLAGS}
@@ -267,6 +276,7 @@ else()
-DCMAKE_IGNORE_PREFIX_PATH:STRING=${CMAKE_IGNORE_PREFIX_PATH}
-DCMAKE_C_COMPILER_LAUNCHER:STRING=${CMAKE_C_COMPILER_LAUNCHER}
-DCMAKE_CXX_COMPILER_LAUNCHER:STRING=${CMAKE_CXX_COMPILER_LAUNCHER}
-DCMAKE_USER_MAKE_RULES_OVERRIDE:STRING=${CMAKE_USER_MAKE_RULES_OVERRIDE}
-DBUILD_SHARED_LIBS:BOOL=OFF
${_cmake_osx_arch}
"${_configs_line}"
+6 -1
View File
@@ -34,6 +34,10 @@ static const char* Segments_Vertex_Shader =
// ORCA: 0 during the shadow caster pass - the bias below shifts eye_position but not
// world_position, so the caster would write a depth the receiver never looks up.
"uniform float bias_scale;\n"
// draw the instances last to first, top layers before the ones they hide, so that early depth
// rejection discards most of the hidden fragments; set when the camera looks down on the print
"uniform int reverse_order;\n"
"uniform int instance_count;\n"
"in int vertex_id;\n"
"out vec3 color;\n"
"// ORCA: realistic view - the light the shadow map is able to block, kept apart from the\n"
@@ -59,7 +63,8 @@ static const char* Segments_Vertex_Shader =
" return top_diffuse + front_diffuse + top_specular;\n"
"}\n"
"void main() {\n"
" int id_a = int(texelFetch(segment_index_tex, gl_InstanceID).r);\n"
" int instance = (reverse_order != 0) ? instance_count - 1 - gl_InstanceID : gl_InstanceID;\n"
" int id_a = int(texelFetch(segment_index_tex, instance).r);\n"
" int id_b = id_a + 1;\n"
" vec3 pos_a = texelFetch(position_tex, id_a).xyz;\n"
" vec3 pos_b = texelFetch(position_tex, id_b).xyz;\n"
+11
View File
@@ -763,6 +763,8 @@ void ViewerImpl::init(const std::string& opengl_context_version)
m_uni_segments_height_width_angle_tex_id = glGetUniformLocation(m_segments_shader_id, "height_width_angle_tex");
m_uni_segments_colors_tex_id = glGetUniformLocation(m_segments_shader_id, "color_tex");
m_uni_segments_segment_index_tex_id = glGetUniformLocation(m_segments_shader_id, "segment_index_tex");
m_uni_segments_reverse_order_id = glGetUniformLocation(m_segments_shader_id, "reverse_order");
m_uni_segments_instance_count_id = glGetUniformLocation(m_segments_shader_id, "instance_count");
// ORCA: realistic view
m_uni_segments_shadow_map_id = glGetUniformLocation(m_segments_shader_id, "shadow_map");
m_uni_segments_shadow_light_vp_id = glGetUniformLocation(m_segments_shader_id, "shadow_light_vp");
@@ -2090,6 +2092,15 @@ void ViewerImpl::render_segments(const Mat4x4& view_matrix, const Mat4x4& projec
glsafe(glUniformMatrix4fv(m_uni_segments_view_matrix_id, 1, GL_FALSE, view_matrix.data()));
glsafe(glUniformMatrix4fv(m_uni_segments_projection_matrix_id, 1, GL_FALSE, projection_matrix.data()));
glsafe(glUniform3fv(m_uni_segments_camera_position_id, 1, camera_position.data()));
// The segments come in print order, bottom layer first. Seen from above, that is back to front,
// and every hidden fragment is shaded before the one that covers it. Drawing them last to first
// lets the depth test reject the hidden ones instead. The camera looks down when the world's
// up axis points towards it, which is the view matrix's (2, 2) entry being positive.
const bool top_down = !m_rendering_shadow_casters && view_matrix[10] > 0.0f;
glsafe(glUniform1i(m_uni_segments_reverse_order_id, top_down ? 1 : 0));
#ifndef ENABLE_OPENGL_ES
glsafe(glUniform1i(m_uni_segments_instance_count_id, static_cast<int>(m_enabled_segments_count)));
#endif // ENABLE_OPENGL_ES
// ORCA: realistic view. The depth pass writes the map it would otherwise read, so it shades
// with the lookup off.
glsafe(glUniform1i(m_uni_segments_shadow_map_id, m_shadow_map_texture_unit));
+2
View File
@@ -362,6 +362,8 @@ private:
int m_uni_segments_height_width_angle_tex_id{ -1 };
int m_uni_segments_colors_tex_id{ -1 };
int m_uni_segments_segment_index_tex_id{ -1 };
int m_uni_segments_reverse_order_id{ -1 };
int m_uni_segments_instance_count_id{ -1 };
int m_uni_segments_shadow_map_id{ -1 };
int m_uni_segments_shadow_light_vp_id{ -1 };
int m_uni_segments_shadow_intensity_id{ -1 };
+13
View File
@@ -2354,6 +2354,13 @@ void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data,
render_thumbnail(thumbnail_data, w, h, thumbnail_params, model_objects, m_volumes, camera_type, camera_view_angle_type, for_picking, ban_light);
}
bool GLCanvas3D::_set_shown_canvas_current()
{
// Thumbnails also render outside render(), where another library's GL context (e.g. WebKitGTK's) can be current.
// Inside render(), the shown canvas is the one already bound.
return wxGetApp().plater()->get_current_canvas3D()->_set_current();
}
void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data,
unsigned int w,
unsigned int h,
@@ -2365,6 +2372,9 @@ void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_data,
bool for_picking,
bool ban_light)
{
if (!_set_shown_canvas_current())
return;
GLShaderProgram* shader = nullptr;
if (for_picking)
shader = wxGetApp().get_shader("flat");
@@ -2403,6 +2413,9 @@ void GLCanvas3D::render_thumbnail(ThumbnailData & thumbnail_d
bool for_picking,
bool ban_light)
{
if (!_set_shown_canvas_current())
return;
GLShaderProgram *shader = wxGetApp().get_shader("thumbnail");
switch (OpenGLManager::get_framebuffers_type()) {
case OpenGLManager::EFramebufferType::Arb: {
+1
View File
@@ -1320,6 +1320,7 @@ private:
bool _init_collapse_toolbar();
bool _set_current();
bool _set_shown_canvas_current();
void _resize(unsigned int w, unsigned int h);
//BBS: add part plate related logic
+19 -22
View File
@@ -1098,35 +1098,32 @@ void PresetUpdater::priv::check_installed_vendor_profiles() const
const auto enabled_vendors = app_config->vendors();
std::set<std::string> bundles;
// Orca: always install filament library
bundles.insert(PresetBundle::ORCA_FILAMENT_LIBRARY);
// A vendor is named by its profile or, where the build ships preset caches
// instead of the raw profile JSONs, by its cache alone.
for (const std::string &vendor_name : vendor_names_in(rsrc_path)) {
if (bundles.find(vendor_name) != bundles.end())continue;
const auto is_vendor_enabled = (vendor_name == PresetBundle::ORCA_DEFAULT_BUNDLE) // always update configs from resource to vendor for ORCA_DEFAULT_BUNDLE
// enabled_vendors lists the vendors whose printer models the user picked, and
// neither of these two is ever in it.
const auto is_vendor_enabled = (vendor_name == PresetBundle::ORCA_DEFAULT_BUNDLE)
|| (vendor_name == PresetBundle::ORCA_FILAMENT_LIBRARY)
|| (enabled_vendors.find(vendor_name) != enabled_vendors.end());
if (is_vendor_installed(vendor_name)) {
if (enabled_config_update) {
if (is_vendor_enabled) {
// Orca: whichever form of the vendor resources ships at the newer
// version is the one installing lays down, and the one to judge
// what is installed against.
Semver resource_ver = resource_vendor_version(vendor_name);
// Orca: a vendor installed as a preset cache has no profile
// beside it; the version it was installed at is in the cache.
Semver vendor_ver = installed_vendor_version(vendor_name);
if (is_vendor_enabled) {
// Orca: whichever form of the vendor resources ships at the newer
// version is the one installing lays down, and the one to judge
// what is installed against.
Semver resource_ver = resource_vendor_version(vendor_name);
// Orca: a vendor installed as a preset cache has no profile
// beside it; the version it was installed at is in the cache.
Semver vendor_ver = installed_vendor_version(vendor_name);
if (vendor_ver < resource_ver) {
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:found vendor " << vendor_name << " newer version "
<< resource_ver.to_string() << " from resource, old version " << vendor_ver.to_string();
bundles.insert(vendor_name);
}
} else {
// need to be removed because not installed
remove_installed_vendor(vendor_name);
if (vendor_ver < resource_ver) {
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:found vendor " << vendor_name << " newer version "
<< resource_ver.to_string() << " from resource, old version " << vendor_ver.to_string();
bundles.insert(vendor_name);
}
} else {
// need to be removed because not installed
remove_installed_vendor(vendor_name);
}
} else if (is_vendor_enabled) {
bundles.insert(vendor_name);