diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py index acd999b1e29..4db9f8f1aa0 100644 --- a/intern/cycles/blender/addon/presets.py +++ b/intern/cycles/blender/addon/presets.py @@ -56,6 +56,7 @@ class AddPresetSampling(AddPresetBase, Operator): "cycles.denoiser", "cycles.denoising_input_passes", "cycles.denoising_prefilter", + "cycles.denoising_quality", ] preset_subdir = "cycles/sampling" @@ -80,6 +81,7 @@ class AddPresetViewportSampling(AddPresetBase, Operator): "cycles.preview_denoiser", "cycles.preview_denoising_input_passes", "cycles.preview_denoising_prefilter", + "cycles.preview_denoising_quality", "cycles.preview_denoising_start_sample", ] diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 4bff7228f53..6933f6ba32a 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -274,6 +274,21 @@ enum_denoising_prefilter = ( 3), ) +enum_denoising_quality = ( + ('HIGH', + "High", + "High quality", + 1), + ('BALANCED', + "Balanced", + "Balanced between performance and quality", + 2), + ('FAST', + "Fast", + "High performance", + 3), +) + enum_direct_light_sampling_type = ( ('MULTIPLE_IMPORTANCE_SAMPLING', "Multiple Importance Sampling", @@ -342,10 +357,16 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): ) denoising_prefilter: EnumProperty( name="Denoising Prefilter", - description="Prefilter noisy guiding (albedo and normal) passes to improve denoising quality when using OpenImageDenoiser", + description="Prefilter noisy guiding (albedo and normal) passes to improve denoising quality when using OpenImageDenoise", items=enum_denoising_prefilter, default='ACCURATE', ) + denoising_quality: EnumProperty( + name="Denoising Quality", + description="Overall denoising quality when using OpenImageDenoise", + items=enum_denoising_quality, + default='HIGH', + ) denoising_input_passes: EnumProperty( name="Denoising Input Passes", description="Passes used by the denoiser to distinguish noise from shader and geometry detail", @@ -371,10 +392,16 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): ) preview_denoising_prefilter: EnumProperty( name="Viewport Denoising Prefilter", - description="Prefilter noisy guiding (albedo and normal) passes to improve denoising quality when using OpenImageDenoiser", + description="Prefilter noisy guiding (albedo and normal) passes to improve denoising quality when using OpenImageDenoise", items=enum_denoising_prefilter, default='FAST', ) + preview_denoising_quality: EnumProperty( + name="Viewport Denoising Quality", + description="Overall denoising quality when using OpenImageDenoise", + items=enum_denoising_quality, + default='BALANCED', + ) preview_denoising_input_passes: EnumProperty( name="Viewport Denoising Input Passes", description="Passes used by the denoiser to distinguish noise from shader and geometry detail", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 88e34a9b56f..8c8a3bb9d5a 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -241,6 +241,7 @@ class CYCLES_RENDER_PT_sampling_viewport_denoise(CyclesButtonsPanel, Panel): effective_preview_denoiser = get_effective_preview_denoiser(context, has_oidn_gpu) if effective_preview_denoiser == 'OPENIMAGEDENOISE': col.prop(cscene, "preview_denoising_prefilter", text="Prefilter") + col.prop(cscene, "preview_denoising_quality", text="Quality") col.prop(cscene, "preview_denoising_start_sample", text="Start Sample") @@ -307,6 +308,7 @@ class CYCLES_RENDER_PT_sampling_render_denoise(CyclesButtonsPanel, Panel): col.prop(cscene, "denoising_input_passes", text="Passes") if cscene.denoiser == 'OPENIMAGEDENOISE': col.prop(cscene, "denoising_prefilter", text="Prefilter") + col.prop(cscene, "denoising_quality", text="Quality") if cscene.denoiser == 'OPENIMAGEDENOISE': row = col.row() diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index 5e41683e8da..84bb1588cd7 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -987,9 +987,8 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene, denoising.use_gpu = get_boolean(cscene, "denoising_use_gpu"); denoising.prefilter = (DenoiserPrefilter)get_enum( cscene, "denoising_prefilter", DENOISER_PREFILTER_NUM, DENOISER_PREFILTER_NONE); - /* This currently only affects NVIDIA and the difference in quality is too small to justify - * exposing a setting to the user. */ - denoising.quality = DENOISER_QUALITY_HIGH; + denoising.quality = (DenoiserQuality)get_enum( + cscene, "denoising_quality", DENOISER_QUALITY_NUM, DENOISER_QUALITY_HIGH); input_passes = (DenoiserInput)get_enum( cscene, "denoising_input_passes", DENOISER_INPUT_NUM, DENOISER_INPUT_RGB_ALBEDO_NORMAL); @@ -1009,9 +1008,8 @@ DenoiseParams BlenderSync::get_denoise_params(BL::Scene &b_scene, denoising.use_gpu = get_boolean(cscene, "preview_denoising_use_gpu"); denoising.prefilter = (DenoiserPrefilter)get_enum( cscene, "preview_denoising_prefilter", DENOISER_PREFILTER_NUM, DENOISER_PREFILTER_FAST); - /* This currently only affects NVIDIA and the difference in quality is too small to justify - * exposing a setting to the user. */ - denoising.quality = DENOISER_QUALITY_BALANCED; + denoising.quality = (DenoiserQuality)get_enum( + cscene, "preview_denoising_quality", DENOISER_QUALITY_NUM, DENOISER_QUALITY_BALANCED); denoising.start_sample = get_int(cscene, "preview_denoising_start_sample"); input_passes = (DenoiserInput)get_enum( diff --git a/intern/cycles/device/denoise.cpp b/intern/cycles/device/denoise.cpp index dc5d3373298..3833a1214b9 100644 --- a/intern/cycles/device/denoise.cpp +++ b/intern/cycles/device/denoise.cpp @@ -55,6 +55,7 @@ const NodeEnum *DenoiseParams::get_quality_enum() if (quality_enum.empty()) { quality_enum.insert("high", DENOISER_QUALITY_HIGH); quality_enum.insert("balanced", DENOISER_QUALITY_BALANCED); + quality_enum.insert("fast", DENOISER_QUALITY_FAST); } return &quality_enum; diff --git a/intern/cycles/device/denoise.h b/intern/cycles/device/denoise.h index ad7a31fea60..73ad9890566 100644 --- a/intern/cycles/device/denoise.h +++ b/intern/cycles/device/denoise.h @@ -43,6 +43,7 @@ enum DenoiserPrefilter { enum DenoiserQuality { DENOISER_QUALITY_HIGH = 1, DENOISER_QUALITY_BALANCED = 2, + DENOISER_QUALITY_FAST = 3, DENOISER_QUALITY_NUM, }; diff --git a/intern/cycles/integrator/denoiser_oidn.cpp b/intern/cycles/integrator/denoiser_oidn.cpp index 07ece3cc769..b8c3fd90d15 100644 --- a/intern/cycles/integrator/denoiser_oidn.cpp +++ b/intern/cycles/integrator/denoiser_oidn.cpp @@ -164,17 +164,7 @@ class OIDNDenoiseContext { oidn_filter.setProgressMonitorFunction(oidn_progress_monitor_function, denoiser_); oidn_filter.set("hdr", true); oidn_filter.set("srgb", false); - -# if OIDN_VERSION_MAJOR >= 2 - switch (denoise_params_.quality) { - case DENOISER_QUALITY_BALANCED: - oidn_filter.set("quality", OIDN_QUALITY_BALANCED); - break; - case DENOISER_QUALITY_HIGH: - default: - oidn_filter.set("quality", OIDN_QUALITY_HIGH); - } -# endif + set_quality(oidn_filter); if (denoise_params_.prefilter == DENOISER_PREFILTER_NONE || denoise_params_.prefilter == DENOISER_PREFILTER_ACCURATE) @@ -211,6 +201,7 @@ class OIDNDenoiseContext { oidn::FilterRef oidn_filter = oidn_device.newFilter("RT"); set_pass(oidn_filter, oidn_pass); set_output_pass(oidn_filter, oidn_pass); + set_quality(oidn_filter); oidn_filter.commit(); oidn_filter.execute(); @@ -413,6 +404,25 @@ class OIDNDenoiseContext { set_pass(oidn_filter, "output", oidn_pass); } + void set_quality(oidn::FilterRef &oidn_filter) + { +# if OIDN_VERSION_MAJOR >= 2 + switch (denoise_params_.quality) { + case DENOISER_QUALITY_FAST: +# if OIDN_VERSION >= 20300 + oidn_filter.set("quality", OIDN_QUALITY_FAST); + break; +# endif + case DENOISER_QUALITY_BALANCED: + oidn_filter.set("quality", OIDN_QUALITY_BALANCED); + break; + case DENOISER_QUALITY_HIGH: + default: + oidn_filter.set("quality", OIDN_QUALITY_HIGH); + } +# endif + } + /* Scale output pass to match adaptive sampling per-pixel scale, as well as bring alpha channel * back. */ void postprocess_output(const OIDNPass &oidn_input_pass, const OIDNPass &oidn_output_pass) diff --git a/intern/cycles/integrator/denoiser_oidn_gpu.cpp b/intern/cycles/integrator/denoiser_oidn_gpu.cpp index 4e7852f86ab..b516aa65be1 100644 --- a/intern/cycles/integrator/denoiser_oidn_gpu.cpp +++ b/intern/cycles/integrator/denoiser_oidn_gpu.cpp @@ -197,6 +197,11 @@ OIDNFilter OIDNDenoiserGPU::create_filter() # if OIDN_VERSION_MAJOR >= 2 switch (quality_) { + case DENOISER_QUALITY_FAST: +# if OIDN_VERSION >= 20300 + oidnSetFilterInt(filter, "quality", OIDN_QUALITY_FAST); + break; +# endif case DENOISER_QUALITY_BALANCED: oidnSetFilterInt(filter, "quality", OIDN_QUALITY_BALANCED); break; diff --git a/intern/cycles/scene/integrator.cpp b/intern/cycles/scene/integrator.cpp index 8cf24ab3fad..ad37c071e0c 100644 --- a/intern/cycles/scene/integrator.cpp +++ b/intern/cycles/scene/integrator.cpp @@ -139,6 +139,7 @@ NODE_DEFINE(Integrator) static NodeEnum denoiser_quality_enum; denoiser_quality_enum.insert("high", DENOISER_QUALITY_HIGH); denoiser_quality_enum.insert("balanced", DENOISER_QUALITY_BALANCED); + denoiser_quality_enum.insert("fast", DENOISER_QUALITY_FAST); /* Default to accurate denoising with OpenImageDenoise. For interactive viewport * it's best use OptiX and disable the normal pass since it does not always have