Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Castilla <manzanillawork@gmail.com>2021-09-19 21:12:53 +0300
committerManuel Castilla <manzanillawork@gmail.com>2021-09-19 22:13:51 +0300
commit276eebb274744d819dcdab8a95770dd7382c0664 (patch)
tree2f1ab6ee7c3b87eb297143c32f4a2c09bd714f0c
parentf256bfb3e26c32af12c82dbd32d4b3bcfba252f3 (diff)
Compositor: Add OIDN prefiltering option to Denoise node
It's equivalent to the OpenImageDenoise prefiltering option in Cycles. See D12043. Prefilter modes: - None: No prefiltering, use when guiding passes are noise-free. - Fast: Denoise image and guiding passes together. Improves quality when guiding passes are noisy using least amount of extra processing time. - Accurate: Prefilter noisy guiding passes before denoising image. Improves quality when guiding passes are noisy using extra processing time. Reviewed By: #compositing, jbakker, sergey Differential Revision: https://developer.blender.org/D12342
-rw-r--r--source/blender/compositor/nodes/COM_DenoiseNode.cc30
-rw-r--r--source/blender/compositor/operations/COM_DenoiseOperation.cc345
-rw-r--r--source/blender/compositor/operations/COM_DenoiseOperation.h50
-rw-r--r--source/blender/editors/space_node/drawnode.cc2
-rw-r--r--source/blender/makesdna/DNA_node_types.h9
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c25
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_denoise.c1
7 files changed, 344 insertions, 118 deletions
diff --git a/source/blender/compositor/nodes/COM_DenoiseNode.cc b/source/blender/compositor/nodes/COM_DenoiseNode.cc
index e58a9c7ba9a..cc9328414ef 100644
--- a/source/blender/compositor/nodes/COM_DenoiseNode.cc
+++ b/source/blender/compositor/nodes/COM_DenoiseNode.cc
@@ -31,6 +31,12 @@ DenoiseNode::DenoiseNode(bNode *editorNode) : Node(editorNode)
void DenoiseNode::convertToOperations(NodeConverter &converter,
const CompositorContext & /*context*/) const
{
+ if (!COM_is_denoise_supported()) {
+ converter.mapOutputSocket(getOutputSocket(0),
+ converter.addInputProxy(getInputSocket(0), false));
+ return;
+ }
+
bNode *node = this->getbNode();
NodeDenoise *denoise = (NodeDenoise *)node->storage;
@@ -39,8 +45,28 @@ void DenoiseNode::convertToOperations(NodeConverter &converter,
operation->setDenoiseSettings(denoise);
converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0));
- converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
- converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
+ if (denoise && denoise->prefilter == CMP_NODE_DENOISE_PREFILTER_ACCURATE) {
+ {
+ DenoisePrefilterOperation *normal_prefilter = new DenoisePrefilterOperation(
+ DataType::Vector);
+ normal_prefilter->set_image_name("normal");
+ converter.addOperation(normal_prefilter);
+ converter.mapInputSocket(getInputSocket(1), normal_prefilter->getInputSocket(0));
+ converter.addLink(normal_prefilter->getOutputSocket(), operation->getInputSocket(1));
+ }
+ {
+ DenoisePrefilterOperation *albedo_prefilter = new DenoisePrefilterOperation(DataType::Color);
+ albedo_prefilter->set_image_name("albedo");
+ converter.addOperation(albedo_prefilter);
+ converter.mapInputSocket(getInputSocket(2), albedo_prefilter->getInputSocket(0));
+ converter.addLink(albedo_prefilter->getOutputSocket(), operation->getInputSocket(2));
+ }
+ }
+ else {
+ converter.mapInputSocket(getInputSocket(1), operation->getInputSocket(1));
+ converter.mapInputSocket(getInputSocket(2), operation->getInputSocket(2));
+ }
+
converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket(0));
}
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.cc b/source/blender/compositor/operations/COM_DenoiseOperation.cc
index e7f2d5a740a..0c660e0b723 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.cc
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.cc
@@ -28,6 +28,137 @@ static pthread_mutex_t oidn_lock = BLI_MUTEX_INITIALIZER;
namespace blender::compositor {
+bool COM_is_denoise_supported()
+{
+#ifdef WITH_OPENIMAGEDENOISE
+ /* Always supported through Accelerate framework BNNS on macOS. */
+# ifdef __APPLE__
+ return true;
+# else
+ return BLI_cpu_support_sse41();
+# endif
+
+#else
+ return false;
+#endif
+}
+
+class DenoiseFilter {
+ private:
+#ifdef WITH_OPENIMAGEDENOISE
+ oidn::DeviceRef device;
+ oidn::FilterRef filter;
+#endif
+ bool initialized_ = false;
+
+ public:
+ ~DenoiseFilter()
+ {
+ BLI_assert(!initialized_);
+ }
+
+#ifdef WITH_OPENIMAGEDENOISE
+ void init_and_lock_denoiser(MemoryBuffer *output)
+ {
+ /* Since it's memory intensive, it's better to run only one instance of OIDN at a time.
+ * OpenImageDenoise is multithreaded internally and should use all available cores
+ * nonetheless. */
+ BLI_mutex_lock(&oidn_lock);
+
+ device = oidn::newDevice();
+ device.commit();
+ filter = device.newFilter("RT");
+ initialized_ = true;
+ set_image("output", output);
+ }
+
+ void deinit_and_unlock_denoiser()
+ {
+ BLI_mutex_unlock(&oidn_lock);
+ initialized_ = false;
+ }
+
+ void set_image(const StringRef name, MemoryBuffer *buffer)
+ {
+ BLI_assert(initialized_);
+ BLI_assert(!buffer->is_a_single_elem());
+ filter.setImage(name.data(),
+ buffer->getBuffer(),
+ oidn::Format::Float3,
+ buffer->getWidth(),
+ buffer->getHeight(),
+ 0,
+ buffer->get_elem_bytes_len());
+ }
+
+ template<typename T> void set(const StringRef option_name, T value)
+ {
+ BLI_assert(initialized_);
+ filter.set(option_name.data(), value);
+ }
+
+ void execute()
+ {
+ BLI_assert(initialized_);
+ filter.commit();
+ filter.execute();
+ }
+
+#else
+ void init_and_lock_denoiser(MemoryBuffer *UNUSED(output))
+ {
+ }
+
+ void deinit_and_unlock_denoiser()
+ {
+ }
+
+ void set_image(const StringRef UNUSED(name), MemoryBuffer *UNUSED(buffer))
+ {
+ }
+
+ template<typename T> void set(const StringRef UNUSED(option_name), T UNUSED(value))
+ {
+ }
+
+ void execute()
+ {
+ }
+#endif
+};
+
+DenoiseBaseOperation::DenoiseBaseOperation()
+{
+ flags.is_fullframe_operation = true;
+ output_rendered_ = false;
+}
+
+bool DenoiseBaseOperation::determineDependingAreaOfInterest(rcti * /*input*/,
+ ReadBufferOperation *readOperation,
+ rcti *output)
+{
+ if (isCached()) {
+ return false;
+ }
+
+ rcti newInput;
+ newInput.xmax = this->getWidth();
+ newInput.xmin = 0;
+ newInput.ymax = this->getHeight();
+ newInput.ymin = 0;
+ return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
+}
+
+void DenoiseBaseOperation::get_area_of_interest(const int UNUSED(input_idx),
+ const rcti &UNUSED(output_area),
+ rcti &r_input_area)
+{
+ r_input_area.xmin = 0;
+ r_input_area.xmax = this->getWidth();
+ r_input_area.ymin = 0;
+ r_input_area.ymax = this->getHeight();
+}
+
DenoiseOperation::DenoiseOperation()
{
this->addInputSocket(DataType::Color);
@@ -35,8 +166,6 @@ DenoiseOperation::DenoiseOperation()
this->addInputSocket(DataType::Color);
this->addOutputSocket(DataType::Color);
this->m_settings = nullptr;
- flags.is_fullframe_operation = true;
- output_rendered_ = false;
}
void DenoiseOperation::initExecution()
{
@@ -54,6 +183,25 @@ void DenoiseOperation::deinitExecution()
SingleThreadedOperation::deinitExecution();
}
+static bool are_guiding_passes_noise_free(NodeDenoise *settings)
+{
+ switch (settings->prefilter) {
+ case CMP_NODE_DENOISE_PREFILTER_NONE:
+ case CMP_NODE_DENOISE_PREFILTER_ACCURATE: /* Prefiltered with #DenoisePrefilterOperation. */
+ return true;
+ case CMP_NODE_DENOISE_PREFILTER_FAST:
+ default:
+ return false;
+ }
+}
+
+void DenoiseOperation::hash_output_params()
+{
+ if (m_settings) {
+ hash_params((int)m_settings->hdr, are_guiding_passes_noise_free(m_settings));
+ }
+}
+
MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2)
{
MemoryBuffer *tileColor = (MemoryBuffer *)this->m_inputProgramColor->initializeTileData(rect2);
@@ -69,22 +217,6 @@ MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2)
return result;
}
-bool DenoiseOperation::determineDependingAreaOfInterest(rcti * /*input*/,
- ReadBufferOperation *readOperation,
- rcti *output)
-{
- if (isCached()) {
- return false;
- }
-
- rcti newInput;
- newInput.xmax = this->getWidth();
- newInput.xmin = 0;
- newInput.ymax = this->getHeight();
- newInput.ymin = 0;
- return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
-}
-
void DenoiseOperation::generateDenoise(MemoryBuffer *output,
MemoryBuffer *input_color,
MemoryBuffer *input_normal,
@@ -96,104 +228,46 @@ void DenoiseOperation::generateDenoise(MemoryBuffer *output,
return;
}
-#ifdef WITH_OPENIMAGEDENOISE
- /* Always supported through Accelerate framework BNNS on macOS. */
-# ifndef __APPLE__
- if (BLI_cpu_support_sse41())
-# endif
- {
- /* OpenImageDenoise needs full buffers. */
- MemoryBuffer *buf_color = input_color->is_a_single_elem() ? input_color->inflate() :
- input_color;
- MemoryBuffer *buf_normal = input_normal && input_normal->is_a_single_elem() ?
- input_normal->inflate() :
- input_normal;
- MemoryBuffer *buf_albedo = input_albedo && input_albedo->is_a_single_elem() ?
- input_albedo->inflate() :
- input_albedo;
+ BLI_assert(COM_is_denoise_supported());
+ /* OpenImageDenoise needs full buffers. */
+ MemoryBuffer *buf_color = input_color->is_a_single_elem() ? input_color->inflate() : input_color;
+ MemoryBuffer *buf_normal = input_normal && input_normal->is_a_single_elem() ?
+ input_normal->inflate() :
+ input_normal;
+ MemoryBuffer *buf_albedo = input_albedo && input_albedo->is_a_single_elem() ?
+ input_albedo->inflate() :
+ input_albedo;
- /* Since it's memory intensive, it's better to run only one instance of OIDN at a time.
- * OpenImageDenoise is multithreaded internally and should use all available cores nonetheless.
- */
- BLI_mutex_lock(&oidn_lock);
+ DenoiseFilter filter;
+ filter.init_and_lock_denoiser(output);
- oidn::DeviceRef device = oidn::newDevice();
- device.commit();
+ filter.set_image("color", buf_color);
+ filter.set_image("normal", buf_normal);
+ filter.set_image("albedo", buf_albedo);
- oidn::FilterRef filter = device.newFilter("RT");
- filter.setImage("color",
- buf_color->getBuffer(),
- oidn::Format::Float3,
- buf_color->getWidth(),
- buf_color->getHeight(),
- 0,
- sizeof(float[4]));
- if (buf_normal && buf_normal->getBuffer()) {
- filter.setImage("normal",
- buf_normal->getBuffer(),
- oidn::Format::Float3,
- buf_normal->getWidth(),
- buf_normal->getHeight(),
- 0,
- sizeof(float[3]));
- }
- if (buf_albedo && buf_albedo->getBuffer()) {
- filter.setImage("albedo",
- buf_albedo->getBuffer(),
- oidn::Format::Float3,
- buf_albedo->getWidth(),
- buf_albedo->getHeight(),
- 0,
- sizeof(float[4]));
- }
- filter.setImage("output",
- output->getBuffer(),
- oidn::Format::Float3,
- buf_color->getWidth(),
- buf_color->getHeight(),
- 0,
- sizeof(float[4]));
-
- BLI_assert(settings);
- if (settings) {
- filter.set("hdr", settings->hdr);
- filter.set("srgb", false);
- }
-
- filter.commit();
- filter.execute();
- BLI_mutex_unlock(&oidn_lock);
+ BLI_assert(settings);
+ if (settings) {
+ filter.set("hdr", settings->hdr);
+ filter.set("srgb", false);
+ filter.set("cleanAux", are_guiding_passes_noise_free(settings));
+ }
- /* Copy the alpha channel, OpenImageDenoise currently only supports RGB. */
- output->copy_from(input_color, input_color->get_rect(), 3, COM_DATA_TYPE_VALUE_CHANNELS, 3);
+ filter.execute();
+ filter.deinit_and_unlock_denoiser();
- /* Delete inflated buffers. */
- if (input_color->is_a_single_elem()) {
- delete buf_color;
- }
- if (input_normal && input_normal->is_a_single_elem()) {
- delete buf_normal;
- }
- if (input_albedo && input_albedo->is_a_single_elem()) {
- delete buf_albedo;
- }
+ /* Copy the alpha channel, OpenImageDenoise currently only supports RGB. */
+ output->copy_from(input_color, input_color->get_rect(), 3, COM_DATA_TYPE_VALUE_CHANNELS, 3);
- return;
+ /* Delete inflated buffers. */
+ if (input_color->is_a_single_elem()) {
+ delete buf_color;
+ }
+ if (input_normal && input_normal->is_a_single_elem()) {
+ delete buf_normal;
+ }
+ if (input_albedo && input_albedo->is_a_single_elem()) {
+ delete buf_albedo;
}
-#endif
- /* If built without OIDN or running on an unsupported CPU, just pass through. */
- UNUSED_VARS(input_albedo, input_normal, settings);
- output->copy_from(input_color, input_color->get_rect());
-}
-
-void DenoiseOperation::get_area_of_interest(const int UNUSED(input_idx),
- const rcti &UNUSED(output_area),
- rcti &r_input_area)
-{
- r_input_area.xmin = 0;
- r_input_area.xmax = this->getWidth();
- r_input_area.ymin = 0;
- r_input_area.ymax = this->getHeight();
}
void DenoiseOperation::update_memory_buffer(MemoryBuffer *output,
@@ -206,4 +280,57 @@ void DenoiseOperation::update_memory_buffer(MemoryBuffer *output,
}
}
+DenoisePrefilterOperation::DenoisePrefilterOperation(DataType data_type)
+{
+ this->addInputSocket(data_type);
+ this->addOutputSocket(data_type);
+ image_name_ = "";
+}
+
+void DenoisePrefilterOperation::hash_output_params()
+{
+ hash_param(image_name_);
+}
+
+MemoryBuffer *DenoisePrefilterOperation::createMemoryBuffer(rcti *rect2)
+{
+ MemoryBuffer *input = (MemoryBuffer *)this->get_input_operation(0)->initializeTileData(rect2);
+ rcti rect;
+ BLI_rcti_init(&rect, 0, getWidth(), 0, getHeight());
+
+ MemoryBuffer *result = new MemoryBuffer(getOutputSocket()->getDataType(), rect);
+ generate_denoise(result, input);
+
+ return result;
+}
+
+void DenoisePrefilterOperation::generate_denoise(MemoryBuffer *output, MemoryBuffer *input)
+{
+ BLI_assert(COM_is_denoise_supported());
+
+ /* Denoising needs full buffers. */
+ MemoryBuffer *input_buf = input->is_a_single_elem() ? input->inflate() : input;
+
+ DenoiseFilter filter;
+ filter.init_and_lock_denoiser(output);
+ filter.set_image(image_name_, input_buf);
+ filter.execute();
+ filter.deinit_and_unlock_denoiser();
+
+ /* Delete inflated buffers. */
+ if (input->is_a_single_elem()) {
+ delete input_buf;
+ }
+}
+
+void DenoisePrefilterOperation::update_memory_buffer(MemoryBuffer *output,
+ const rcti &UNUSED(area),
+ Span<MemoryBuffer *> inputs)
+{
+ if (!output_rendered_) {
+ this->generate_denoise(output, inputs[0]);
+ output_rendered_ = true;
+ }
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.h b/source/blender/compositor/operations/COM_DenoiseOperation.h
index 48209c3eacf..1b053b79c2d 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.h
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.h
@@ -23,7 +23,24 @@
namespace blender::compositor {
-class DenoiseOperation : public SingleThreadedOperation {
+bool COM_is_denoise_supported();
+
+class DenoiseBaseOperation : public SingleThreadedOperation {
+ protected:
+ bool output_rendered_;
+
+ protected:
+ DenoiseBaseOperation();
+
+ public:
+ bool determineDependingAreaOfInterest(rcti *input,
+ ReadBufferOperation *readOperation,
+ rcti *output) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+};
+
+class DenoiseOperation : public DenoiseBaseOperation {
private:
/**
* \brief Cached reference to the input programs
@@ -37,8 +54,6 @@ class DenoiseOperation : public SingleThreadedOperation {
*/
NodeDenoise *m_settings;
- bool output_rendered_;
-
public:
DenoiseOperation();
/**
@@ -55,16 +70,13 @@ class DenoiseOperation : public SingleThreadedOperation {
{
this->m_settings = settings;
}
- bool determineDependingAreaOfInterest(rcti *input,
- ReadBufferOperation *readOperation,
- rcti *output) override;
- void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
void update_memory_buffer(MemoryBuffer *output,
const rcti &area,
Span<MemoryBuffer *> inputs) override;
protected:
+ void hash_output_params() override;
void generateDenoise(MemoryBuffer *output,
MemoryBuffer *input_color,
MemoryBuffer *input_normal,
@@ -74,4 +86,28 @@ class DenoiseOperation : public SingleThreadedOperation {
MemoryBuffer *createMemoryBuffer(rcti *rect) override;
};
+class DenoisePrefilterOperation : public DenoiseBaseOperation {
+ private:
+ std::string image_name_;
+
+ public:
+ DenoisePrefilterOperation(DataType data_type);
+
+ void set_image_name(StringRef name)
+ {
+ image_name_ = name;
+ }
+
+ void update_memory_buffer(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+
+ protected:
+ void hash_output_params() override;
+ MemoryBuffer *createMemoryBuffer(rcti *rect) override;
+
+ private:
+ void generate_denoise(MemoryBuffer *output, MemoryBuffer *input);
+};
+
} // namespace blender::compositor
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index 4b859de0ac9..62f40152416 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -2865,6 +2865,8 @@ static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), Po
# endif
#endif
+ uiItemL(layout, IFACE_("Prefilter:"), ICON_NONE);
+ uiItemR(layout, ptr, "prefilter", DEFAULT_FLAGS, nullptr, ICON_NONE);
uiItemR(layout, ptr, "use_hdr", DEFAULT_FLAGS, nullptr, ICON_NONE);
}
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index ee1da6be3f2..74ed22ecafd 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1167,6 +1167,7 @@ typedef struct NodeCryptomatte {
typedef struct NodeDenoise {
char hdr;
+ char prefilter;
} NodeDenoise;
typedef struct NodeAttributeClamp {
@@ -1840,6 +1841,14 @@ typedef enum CMPNodeSetAlphaMode {
CMP_NODE_SETALPHA_MODE_REPLACE_ALPHA = 1,
} CMPNodeSetAlphaMode;
+/* Denoise Node. */
+/* `NodeDenoise.prefilter` */
+typedef enum CMPNodeDenoisePrefilter {
+ CMP_NODE_DENOISE_PREFILTER_FAST = 0,
+ CMP_NODE_DENOISE_PREFILTER_NONE = 1,
+ CMP_NODE_DENOISE_PREFILTER_ACCURATE = 2
+} CMPNodeDenoisePrefilter;
+
#define CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX 64
/* Point Density shader node */
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 86e134799aa..d685692c8fa 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -8890,12 +8890,37 @@ static void def_cmp_denoise(StructRNA *srna)
{
PropertyRNA *prop;
+ static const EnumPropertyItem prefilter_items[] = {
+ {CMP_NODE_DENOISE_PREFILTER_NONE,
+ "NONE",
+ 0,
+ "None",
+ "No prefiltering, use when guiding passes are noise-free"},
+ {CMP_NODE_DENOISE_PREFILTER_FAST,
+ "FAST",
+ 0,
+ "Fast",
+ "Denoise image and guiding passes together. Improves quality when guiding passes are noisy "
+ "using least amount of extra processing time"},
+ {CMP_NODE_DENOISE_PREFILTER_ACCURATE,
+ "ACCURATE",
+ 0,
+ "Accurate",
+ "Prefilter noisy guiding passes before denoising image. Improves quality when guiding "
+ "passes are noisy using extra processing time"},
+ {0, NULL, 0, NULL, NULL}};
+
RNA_def_struct_sdna_from(srna, "NodeDenoise", "storage");
prop = RNA_def_property(srna, "use_hdr", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "hdr", 0);
RNA_def_property_ui_text(prop, "HDR", "Process HDR images");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "prefilter", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prefilter_items);
+ RNA_def_property_ui_text(prop, "", "Denoising prefilter");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_cmp_antialiasing(StructRNA *srna)
diff --git a/source/blender/nodes/composite/nodes/node_composite_denoise.c b/source/blender/nodes/composite/nodes/node_composite_denoise.c
index 040b350627e..e2c7c7b995f 100644
--- a/source/blender/nodes/composite/nodes/node_composite_denoise.c
+++ b/source/blender/nodes/composite/nodes/node_composite_denoise.c
@@ -36,6 +36,7 @@ static void node_composit_init_denonise(bNodeTree *UNUSED(ntree), bNode *node)
{
NodeDenoise *ndg = MEM_callocN(sizeof(NodeDenoise), "node denoise data");
ndg->hdr = true;
+ ndg->prefilter = CMP_NODE_DENOISE_PREFILTER_ACCURATE;
node->storage = ndg;
}