diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index a5450642245..0012948ad08 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -33,17 +33,6 @@ enum_devices = ( "Use GPU compute device for rendering, configured in the system tab in the user preferences"), ) -enum_feature_set = ( - ('SUPPORTED', - "Supported", - "Only use finished and supported features"), - ('EXPERIMENTAL', - "Experimental", - "Use experimental and incomplete features that might be broken or change in the future", - 'ERROR', - 1), -) - enum_bvh_layouts = ( ('BVH2', "BVH2", "", 1), ('EMBREE', "Embree", "", 4), @@ -395,13 +384,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): items=enum_devices, default='CPU', ) - feature_set: EnumProperty( - name="Feature Set", - description="Feature set to use for rendering", - items=enum_feature_set, - default='SUPPORTED', - update=update_render_engine, - ) shading_system: BoolProperty( name="Open Shading Language", description="Use Open Shading Language", @@ -806,22 +788,20 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): dicing_rate: FloatProperty( name="Dicing Rate", - description="Size of a micropolygon in pixels", + description="Multiplier for per object adaptive subdivision size", min=0.1, max=1000.0, soft_min=0.5, default=1.0, - subtype='PIXEL' ) preview_dicing_rate: FloatProperty( name="Viewport Dicing Rate", - description="Size of a micropolygon in pixels during preview render", + description="Multiplier for per object adaptive subdivision size in the viewport", min=0.1, max=1000.0, soft_min=0.5, default=8.0, - subtype='PIXEL' ) max_subdivisions: IntProperty( name="Max Subdivisions", - description="Stop subdividing when this level is reached even if the dice rate would produce finer tessellation", + description="Stop subdividing when this level is reached even if the dicing rate would produce finer tessellation", min=0, max=16, default=12, @@ -1378,19 +1358,6 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): default=False, ) - use_adaptive_subdivision: BoolProperty( - name="Use Adaptive Subdivision", - description="Use adaptive render time subdivision", - default=False, - ) - - dicing_rate: FloatProperty( - name="Dicing Scale", - description="Multiplier for scene dicing rate (located in the Subdivision panel)", - min=0.1, max=1000.0, soft_min=0.5, - default=1.0, - ) - shadow_terminator_offset: FloatProperty( name="Shadow Terminator Shading Offset", description="Push the shadow terminator towards the light to hide artifacts on low poly geometry", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index e4af0466b01..fc181744180 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -524,10 +524,6 @@ class CYCLES_RENDER_PT_subdivision(CyclesButtonsPanel, Panel): bl_label = "Subdivision" bl_options = {'DEFAULT_CLOSED'} - @classmethod - def poll(cls, context): - return (context.scene.render.engine == 'CYCLES') and (context.scene.cycles.feature_set == 'EXPERIMENTAL') - def draw(self, context): layout = self.layout layout.use_property_split = True @@ -2450,9 +2446,6 @@ def draw_device(self, context): from . import engine cscene = scene.cycles - col = layout.column() - col.prop(cscene, "feature_set") - col = layout.column() col.active = show_device_active(context) col.prop(cscene, "device") diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index 55a3ee6bf85..b5798288b0b 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -834,9 +834,20 @@ static void create_subd_mesh(Scene *scene, } /* Set subd parameters. */ - PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles"); - const float subd_dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate); + Mesh::SubdivisionAdaptiveSpace space = Mesh::SUBDIVISION_ADAPTIVE_SPACE_PIXEL; + switch (subsurf_mod.adaptive_space()) { + case BL::SubsurfModifier::adaptive_space_OBJECT: + space = Mesh::SUBDIVISION_ADAPTIVE_SPACE_OBJECT; + break; + case BL::SubsurfModifier::adaptive_space_PIXEL: + space = Mesh::SUBDIVISION_ADAPTIVE_SPACE_PIXEL; + break; + } + const float subd_dicing_rate = (space == Mesh::SUBDIVISION_ADAPTIVE_SPACE_PIXEL) ? + max(0.1f, subsurf_mod.adaptive_pixel_size() * dicing_rate) : + subsurf_mod.adaptive_object_edge_length() * dicing_rate; + mesh->set_subd_adaptive_space(space); mesh->set_subd_dicing_rate(subd_dicing_rate); mesh->set_subd_max_level(max_subdivisions); mesh->set_subd_objecttoworld(get_transform(b_ob.matrix_world())); diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index 6247e4db89c..6401e9bc4eb 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -337,8 +337,7 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); /* No adaptive subdivision for baking, mesh needs to match Blender exactly. */ - use_adaptive_subdivision = (get_enum(cscene, "feature_set") != 0) && !b_bake_target; - use_experimental_procedural = (get_enum(cscene, "feature_set") != 0); + use_adaptive_subdivision = !b_bake_target; Integrator *integrator = scene->integrator; @@ -936,9 +935,6 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine, params.temp_dir = b_engine.temporary_directory(); } - /* feature set */ - params.experimental = (get_enum(cscene, "feature_set") != 0); - /* Headless and background rendering. */ params.headless = BlenderSession::headless; params.background = background; diff --git a/intern/cycles/blender/sync.h b/intern/cycles/blender/sync.h index 75b99f6b615..11cde3a641b 100644 --- a/intern/cycles/blender/sync.h +++ b/intern/cycles/blender/sync.h @@ -241,7 +241,6 @@ class BlenderSync { Scene *scene; bool preview; - bool use_experimental_procedural = false; bool use_adaptive_subdivision = false; bool use_developer_ui; diff --git a/intern/cycles/blender/util.h b/intern/cycles/blender/util.h index 03a1686a71b..01720d61204 100644 --- a/intern/cycles/blender/util.h +++ b/intern/cycles/blender/util.h @@ -667,17 +667,15 @@ static inline BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b static BL::SubsurfModifier object_subdivision_modifier(BL::Object &b_ob, const bool preview) { - PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles"); - - if (cobj.data && !b_ob.modifiers.empty()) { + if (!b_ob.modifiers.empty()) { BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length() - 1]; const bool enabled = preview ? mod.show_viewport() : mod.show_render(); - if (enabled && mod.type() == BL::Modifier::type_SUBSURF && - RNA_boolean_get(&cobj, "use_adaptive_subdivision")) - { + if (enabled && mod.type() == BL::Modifier::type_SUBSURF) { BL::SubsurfModifier subsurf(mod); - return subsurf; + if (subsurf.use_adaptive_subdivision()) { + return subsurf; + } } } diff --git a/intern/cycles/scene/geometry.cpp b/intern/cycles/scene/geometry.cpp index f31a2f6c20d..ebb29be436e 100644 --- a/intern/cycles/scene/geometry.cpp +++ b/intern/cycles/scene/geometry.cpp @@ -805,8 +805,10 @@ void GeometryManager::device_update(Device *device, SubdParams subd_params(mesh); subd_params.dicing_rate = mesh->get_subd_dicing_rate(); subd_params.max_level = mesh->get_subd_max_level(); - subd_params.objecttoworld = mesh->get_subd_objecttoworld(); - subd_params.camera = dicing_camera; + if (mesh->get_subd_adaptive_space() == Mesh::SUBDIVISION_ADAPTIVE_SPACE_PIXEL) { + subd_params.objecttoworld = mesh->get_subd_objecttoworld(); + subd_params.camera = dicing_camera; + } mesh->tessellate(subd_params); } diff --git a/intern/cycles/scene/mesh.cpp b/intern/cycles/scene/mesh.cpp index f7487442137..b1036d13b72 100644 --- a/intern/cycles/scene/mesh.cpp +++ b/intern/cycles/scene/mesh.cpp @@ -305,6 +305,14 @@ NODE_DEFINE(Mesh) SOCKET_INT_ARRAY(subd_ptex_offset, "Subdivision Face PTex Offset", array()); /* Subdivisions parameters */ + static NodeEnum subd_adaptive_space_enum; + subd_adaptive_space_enum.insert("pixel", SUBDIVISION_ADAPTIVE_SPACE_PIXEL); + subd_adaptive_space_enum.insert("object", SUBDIVISION_ADAPTIVE_SPACE_OBJECT); + + SOCKET_ENUM(subd_adaptive_space, + "Subdivision Adaptive Space", + subd_adaptive_space_enum, + SUBDIVISION_ADAPTIVE_SPACE_PIXEL); SOCKET_FLOAT(subd_dicing_rate, "Subdivision Dicing Rate", 1.0f) SOCKET_INT(subd_max_level, "Max Subdivision Level", 1); SOCKET_TRANSFORM(subd_objecttoworld, "Subdivision Object Transform", transform_identity()); @@ -316,7 +324,8 @@ bool Mesh::need_tesselation() { return (subdivision_type != SUBDIVISION_NONE) && (verts_is_modified() || subd_dicing_rate_is_modified() || - subd_objecttoworld_is_modified() || subd_max_level_is_modified()); + subd_adaptive_space_is_modified() || subd_objecttoworld_is_modified() || + subd_max_level_is_modified()); } Mesh::Mesh(const NodeType *node_type, Type geom_type_) diff --git a/intern/cycles/scene/mesh.h b/intern/cycles/scene/mesh.h index cb442db6f80..e340ce83a97 100644 --- a/intern/cycles/scene/mesh.h +++ b/intern/cycles/scene/mesh.h @@ -135,6 +135,11 @@ class Mesh : public Geometry { SUBDIVISION_FVAR_LINEAR_ALL, }; + enum SubdivisionAdaptiveSpace { + SUBDIVISION_ADAPTIVE_SPACE_PIXEL, + SUBDIVISION_ADAPTIVE_SPACE_OBJECT, + }; + NODE_SOCKET_API(SubdivisionType, subdivision_type) NODE_SOCKET_API(SubdivisionBoundaryInterpolation, subdivision_boundary_interpolation) NODE_SOCKET_API(SubdivisionFVarInterpolation, subdivision_fvar_interpolation) @@ -161,6 +166,7 @@ class Mesh : public Geometry { NODE_SOCKET_API_ARRAY(array, subd_vert_creases_weight) /* Subdivisions parameters */ + NODE_SOCKET_API(SubdivisionAdaptiveSpace, subd_adaptive_space) NODE_SOCKET_API(float, subd_dicing_rate) NODE_SOCKET_API(int, subd_max_level) NODE_SOCKET_API(Transform, subd_objecttoworld) diff --git a/intern/cycles/session/session.h b/intern/cycles/session/session.h index cf8a675b571..9f397770d4f 100644 --- a/intern/cycles/session/session.h +++ b/intern/cycles/session/session.h @@ -44,7 +44,6 @@ class SessionParams { bool headless; bool background; - bool experimental; int samples; bool use_sample_subset; int sample_subset_offset; @@ -73,7 +72,6 @@ class SessionParams { headless = false; background = false; - experimental = false; samples = 1024; use_sample_subset = false; sample_subset_offset = 0; @@ -97,10 +95,10 @@ class SessionParams { /* Modified means we have to recreate the session, any parameter changes * that can be handled by an existing Session are omitted. */ return !(device == params.device && headless == params.headless && - background == params.background && experimental == params.experimental && - pixel_size == params.pixel_size && threads == params.threads && - use_profiling == params.use_profiling && shadingsystem == params.shadingsystem && - use_auto_tile == params.use_auto_tile && tile_size == params.tile_size); + background == params.background && pixel_size == params.pixel_size && + threads == params.threads && use_profiling == params.use_profiling && + shadingsystem == params.shadingsystem && use_auto_tile == params.use_auto_tile && + tile_size == params.tile_size); } }; diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index f7903bb90e6..932b26bcc7a 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 91 +#define BLENDER_FILE_SUBVERSION 92 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/BKE_scene.hh b/source/blender/blenkernel/BKE_scene.hh index 5b43e9340f3..7b6986ada01 100644 --- a/source/blender/blenkernel/BKE_scene.hh +++ b/source/blender/blenkernel/BKE_scene.hh @@ -220,14 +220,6 @@ bool BKE_scene_uses_cycles(const Scene *scene); bool BKE_scene_uses_shader_previews(const Scene *scene); -/** - * Return whether the Cycles experimental feature is enabled. It is invalid to call without first - * ensuring that Cycles is the active render engine (e.g. with #BKE_scene_uses_cycles). - * - * \note We cannot use `const` as RNA_id_pointer_create is not using a const ID. - */ -bool BKE_scene_uses_cycles_experimental_features(Scene *scene); - void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src); void BKE_scene_disable_color_management(Scene *scene); diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc index 40a061d0a57..3d1578418f1 100644 --- a/source/blender/blenkernel/intern/scene.cc +++ b/source/blender/blenkernel/intern/scene.cc @@ -2801,20 +2801,6 @@ enum eCyclesFeatureSet { CYCLES_FEATURES_EXPERIMENTAL = 1, }; -bool BKE_scene_uses_cycles_experimental_features(Scene *scene) -{ - BLI_assert(BKE_scene_uses_cycles(scene)); - PointerRNA scene_ptr = RNA_id_pointer_create(&scene->id); - PointerRNA cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles"); - - if (RNA_pointer_is_null(&cycles_ptr)) { - /* The pointer only exists if Cycles is enabled. */ - return false; - } - - return RNA_enum_get(&cycles_ptr, "feature_set") == CYCLES_FEATURES_EXPERIMENTAL; -} - void BKE_scene_base_flag_to_objects(const Scene *scene, ViewLayer *view_layer) { BKE_view_layer_synced_ensure(scene, view_layer); diff --git a/source/blender/blenloader/intern/versioning_500.cc b/source/blender/blenloader/intern/versioning_500.cc index 08eb2ba0a11..e561723e5f5 100644 --- a/source/blender/blenloader/intern/versioning_500.cc +++ b/source/blender/blenloader/intern/versioning_500.cc @@ -2658,6 +2658,44 @@ static void sequencer_remove_listbase_pointers(Scene &scene) blender::seq::meta_stack_set(&scene, last_meta_stack->parent_strip); } +static void do_version_adaptive_subdivision(Main *bmain) +{ + /* Move cycles properties natively into subdivision surface modifier. */ + bool experimental_features = false; + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + IDProperty *idprop = version_cycles_properties_from_ID(&scene->id); + if (idprop) { + experimental_features |= version_cycles_property_boolean(idprop, "feature_set", false); + } + } + + LISTBASE_FOREACH (Object *, object, &bmain->objects) { + bool use_adaptive_subdivision = false; + float dicing_rate = 1.0f; + + IDProperty *idprop = version_cycles_properties_from_ID(&object->id); + if (idprop) { + if (experimental_features) { + use_adaptive_subdivision = version_cycles_property_boolean( + idprop, "use_adaptive_subdivision", false); + } + dicing_rate = version_cycles_property_float(idprop, "dicing_rate", 1.0f); + } + + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Subsurf) { + SubsurfModifierData *smd = (SubsurfModifierData *)md; + if (use_adaptive_subdivision) { + smd->flags |= eSubsurfModifierFlag_UseAdaptiveSubdivision; + smd->adaptive_space = SUBSURF_ADAPTIVE_SPACE_PIXEL; + smd->adaptive_pixel_size = dicing_rate; + smd->adaptive_object_edge_length = 0.01f; + } + } + } + } +} + void blo_do_versions_500(FileData *fd, Library * /*lib*/, Main *bmain) { using namespace blender; @@ -3625,6 +3663,10 @@ void blo_do_versions_500(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 92)) { + do_version_adaptive_subdivision(bmain); + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index c30dfcc865d..5ec3f24f122 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -615,6 +615,9 @@ .uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES, \ .quality = 3, \ .boundary_smooth = SUBSURF_BOUNDARY_SMOOTH_ALL, \ + .adaptive_space = SUBSURF_ADAPTIVE_SPACE_PIXEL, \ + .adaptive_pixel_size = 1.0f, \ + .adaptive_object_edge_length = 0.01f, \ } #define _DNA_DEFAULT_SurfaceModifierData \ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 2c8a08e42fd..a36099f0027 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -234,8 +234,14 @@ typedef enum { eSubsurfModifierFlag_UseCrease = (1 << 4), eSubsurfModifierFlag_UseCustomNormals = (1 << 5), eSubsurfModifierFlag_UseRecursiveSubdivision = (1 << 6), + eSubsurfModifierFlag_UseAdaptiveSubdivision = (1 << 7), } SubsurfModifierFlag; +typedef enum { + SUBSURF_ADAPTIVE_SPACE_PIXEL = 0, + SUBSURF_ADAPTIVE_SPACE_OBJECT = 1, +} eSubsurfAdaptiveSpace; + typedef enum { SUBSURF_TYPE_CATMULL_CLARK = 0, SUBSURF_TYPE_SIMPLE = 1, @@ -268,7 +274,11 @@ typedef struct SubsurfModifierData { short quality; /** #eSubsurfBoundarySmooth. */ short boundary_smooth; - char _pad[2]; + /* Adaptive subdivision. */ + /** #eSubsurfAdaptiveSpace */ + short adaptive_space; + float adaptive_pixel_size; + float adaptive_object_edge_length; } SubsurfModifierData; typedef struct LatticeModifierData { diff --git a/source/blender/makesrna/intern/rna_modifier.cc b/source/blender/makesrna/intern/rna_modifier.cc index 2a3ab3231aa..d6370472d02 100644 --- a/source/blender/makesrna/intern/rna_modifier.cc +++ b/source/blender/makesrna/intern/rna_modifier.cc @@ -2451,6 +2451,21 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem prop_adaptive_space_items[] = { + {SUBSURF_ADAPTIVE_SPACE_PIXEL, + "PIXEL", + 0, + "Pixel", + "Subdivide polygons to reach a specified pixel size on screen"}, + {SUBSURF_ADAPTIVE_SPACE_OBJECT, + "OBJECT", + 0, + "Object", + "Subdivide to reach a specified edge length in object space. This is required to use " + "adaptive subdivision for instanced meshes"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + StructRNA *srna; PropertyRNA *prop; @@ -2510,6 +2525,32 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) "levels of subdivision (smoothest possible shape)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_adaptive_subdivision", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, nullptr, "flags", eSubsurfModifierFlag_UseAdaptiveSubdivision); + RNA_def_property_ui_text( + prop, "Use Adaptive Subdivision", "Adaptively subdivide mesh based on camera distance"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "adaptive_space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_adaptive_space_items); + RNA_def_property_ui_text(prop, "Adaptive Space", "How to adaptively subdivide the mesh"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "adaptive_pixel_size", PROP_FLOAT, PROP_PIXEL); + RNA_def_property_ui_text( + prop, "Pixel Size", "Target polygon pixel size for adaptive subdivision"); + RNA_def_property_range(prop, 0.1f, 1000.0f); + RNA_def_property_ui_range(prop, 0.5f, 1000.0f, 10, 3); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "adaptive_object_edge_length", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_ui_text( + prop, "Edge Length", "Target object space edge length for adaptive subdivision"); + RNA_def_property_range(prop, 0.0001f, 1000.0f); + RNA_def_property_ui_range(prop, 0.001f, 1000.0f, 10, 3); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + rna_def_modifier_panel_open_prop(srna, "open_adaptive_subdivision_panel", 0); rna_def_modifier_panel_open_prop(srna, "open_advanced_panel", 1); diff --git a/source/blender/modifiers/intern/MOD_subsurf.cc b/source/blender/modifiers/intern/MOD_subsurf.cc index 021f0f95ebf..fc43e000276 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.cc +++ b/source/blender/modifiers/intern/MOD_subsurf.cc @@ -19,6 +19,7 @@ #include "DNA_defaults.h" #include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -315,7 +316,6 @@ static void deform_matrices(ModifierData *md, } } -#ifdef WITH_CYCLES static bool get_show_adaptive_options(const bContext *C, Panel *panel) { /* Don't show adaptive options if cycles isn't the active engine. */ @@ -331,15 +331,8 @@ static bool get_show_adaptive_options(const bContext *C, Panel *panel) return false; } - /* Don't show adaptive options if the cycles experimental feature set is disabled. */ - Scene *scene = CTX_data_scene(C); - if (!BKE_scene_uses_cycles_experimental_features(scene)) { - return false; - } - return true; } -#endif static void panel_draw(const bContext *C, Panel *panel) { @@ -348,27 +341,6 @@ static void panel_draw(const bContext *C, Panel *panel) PointerRNA ob_ptr; PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); - /* Only test for adaptive subdivision if built with cycles. */ - bool show_adaptive_options = false; - bool ob_use_adaptive_subdivision = false; - PointerRNA cycles_ptr = {}; - PointerRNA ob_cycles_ptr = {}; -#ifdef WITH_CYCLES - Scene *scene = CTX_data_scene(C); - PointerRNA scene_ptr = RNA_id_pointer_create(&scene->id); - if (BKE_scene_uses_cycles(scene)) { - cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles"); - ob_cycles_ptr = RNA_pointer_get(&ob_ptr, "cycles"); - if (!RNA_pointer_is_null(&ob_cycles_ptr)) { - show_adaptive_options = get_show_adaptive_options(C, panel); - ob_use_adaptive_subdivision = show_adaptive_options && - RNA_boolean_get(&ob_cycles_ptr, "use_adaptive_subdivision"); - } - } -#else - UNUSED_VARS(C); -#endif - layout->prop(ptr, "subdivision_type", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE); layout->use_property_split_set(true); @@ -402,31 +374,47 @@ static void panel_draw(const bContext *C, Panel *panel) } } - if (show_adaptive_options) { + if (get_show_adaptive_options(C, panel)) { PanelLayout adaptive_panel = layout->panel_prop_with_bool_header( C, ptr, "open_adaptive_subdivision_panel", - &ob_cycles_ptr, + ptr, "use_adaptive_subdivision", IFACE_("Adaptive Subdivision")); if (adaptive_panel.body) { - adaptive_panel.body->active_set(ob_use_adaptive_subdivision); - adaptive_panel.body->prop( - &ob_cycles_ptr, "dicing_rate", UI_ITEM_NONE, std::nullopt, ICON_NONE); + Scene *scene = CTX_data_scene(C); + PointerRNA scene_ptr = RNA_id_pointer_create(&scene->id); + PointerRNA cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles"); + const float render_rate = RNA_float_get(&cycles_ptr, "dicing_rate"); + const float preview_rate = RNA_float_get(&cycles_ptr, "preview_dicing_rate"); + std::string render_str, preview_str; - float render = std::max(RNA_float_get(&cycles_ptr, "dicing_rate") * - RNA_float_get(&ob_cycles_ptr, "dicing_rate"), - 0.1f); - float preview = std::max(RNA_float_get(&cycles_ptr, "preview_dicing_rate") * - RNA_float_get(&ob_cycles_ptr, "dicing_rate"), - 0.1f); + adaptive_panel.body->active_set(smd->flags & eSubsurfModifierFlag_UseAdaptiveSubdivision); + adaptive_panel.body->prop(ptr, "adaptive_space", UI_ITEM_NONE, IFACE_("Space"), ICON_NONE); + if (smd->adaptive_space == SUBSURF_ADAPTIVE_SPACE_OBJECT) { + adaptive_panel.body->prop( + ptr, "adaptive_object_edge_length", UI_ITEM_NONE, std::nullopt, ICON_NONE); + preview_str = fmt::format("{:.5g}", preview_rate * smd->adaptive_object_edge_length); + render_str = fmt::format("{:.5g}", render_rate * smd->adaptive_object_edge_length); + } + else { + adaptive_panel.body->prop( + ptr, "adaptive_pixel_size", UI_ITEM_NONE, std::nullopt, ICON_NONE); + preview_str = fmt::format("{:.2f} px", + std::max(preview_rate * smd->adaptive_pixel_size, 0.1f)); + render_str = fmt::format("{:.2f} px", + std::max(render_rate * smd->adaptive_pixel_size, 0.1f)); + } uiLayout *split = &adaptive_panel.body->split(0.4f, false); - split->column(true).label("", ICON_NONE); uiLayout *col = &split->column(true); - col->label(fmt::format(fmt::runtime(RPT_("Viewport {:.2f} px")), preview), ICON_NONE); - col->label(fmt::format(fmt::runtime(RPT_("Render {:.2f} px")), render), ICON_NONE); + col->alignment_set(blender::ui::LayoutAlign::Right); + col->label(IFACE_("Viewport"), ICON_NONE); + col->label(IFACE_("Render"), ICON_NONE); + col = &split->column(true); + col->label(preview_str, ICON_NONE); + col->label(render_str, ICON_NONE); } } @@ -438,7 +426,8 @@ static void panel_draw(const bContext *C, Panel *panel) advanced_layout->prop(ptr, "use_limit_surface", UI_ITEM_NONE, std::nullopt, ICON_NONE); uiLayout *col = &advanced_layout->column(true); - col->active_set(ob_use_adaptive_subdivision || RNA_boolean_get(ptr, "use_limit_surface")); + col->active_set((smd->flags & eSubsurfModifierFlag_UseAdaptiveSubdivision) || + RNA_boolean_get(ptr, "use_limit_surface")); col->prop(ptr, "quality", UI_ITEM_NONE, std::nullopt, ICON_NONE); advanced_layout->prop(ptr, "uv_smooth", UI_ITEM_NONE, std::nullopt, ICON_NONE); diff --git a/tests/files/render/displacement/cycles_renders/object_dicing.png b/tests/files/render/displacement/cycles_renders/object_dicing.png new file mode 100644 index 00000000000..00438d466eb --- /dev/null +++ b/tests/files/render/displacement/cycles_renders/object_dicing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be411a0745e722a6e6619ad8229d94a9fad81ac1c5fc6c876d9094073d538a9d +size 12376 diff --git a/tests/files/render/displacement/eevee_renders/object_dicing.png b/tests/files/render/displacement/eevee_renders/object_dicing.png new file mode 100644 index 00000000000..58a1466c91e --- /dev/null +++ b/tests/files/render/displacement/eevee_renders/object_dicing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d27bac6eab771812f36d2ef66c1bbbb471422533f74570ef86aed7236d20f264 +size 12270 diff --git a/tests/files/render/displacement/object_dicing.blend b/tests/files/render/displacement/object_dicing.blend new file mode 100644 index 00000000000..28ca2203974 --- /dev/null +++ b/tests/files/render/displacement/object_dicing.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11efc58c0b68cd68fb2d97b00e311407ada95b7b68a0f6d32a57415a6f9e5a16 +size 104600 diff --git a/tests/files/render/displacement/storm_hydra_renders/object_dicing.png b/tests/files/render/displacement/storm_hydra_renders/object_dicing.png new file mode 100644 index 00000000000..e5d9aca05f4 --- /dev/null +++ b/tests/files/render/displacement/storm_hydra_renders/object_dicing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2694fccb3c2215c6fb2200bc836b83706f1b99873e69ae7747c46904490c3b9c +size 659 diff --git a/tests/files/render/displacement/storm_usd_renders/object_dicing.png b/tests/files/render/displacement/storm_usd_renders/object_dicing.png new file mode 100644 index 00000000000..3268196ab15 --- /dev/null +++ b/tests/files/render/displacement/storm_usd_renders/object_dicing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d75a8011298333116d8a895023e607e1e8d21f3bc1ebc0facb48a9b682fdad74 +size 659 diff --git a/tests/files/render/displacement/workbench_renders/object_dicing.png b/tests/files/render/displacement/workbench_renders/object_dicing.png new file mode 100644 index 00000000000..c337340d0a3 --- /dev/null +++ b/tests/files/render/displacement/workbench_renders/object_dicing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cf3af879242b551cda559606090a094848e49833e8f45dae22018e8ba51915d +size 6945