Compositor: Turn Anti-Alias node options into inputs
This patch turns the options of the Anti-Alias node into inputs. In the process, the [0, 1] limit of the Contrast Limit input was lifted to allow normalized arbitrary positive limits. Reference #137223. Pull Request: https://projects.blender.org/blender/blender/pulls/137717
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 35
|
||||
#define BLENDER_FILE_SUBVERSION 36
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -258,11 +258,6 @@
|
||||
#define CMP_CHAN_RGB 1
|
||||
#define CMP_CHAN_A 2
|
||||
|
||||
/* Default SMAA configuration values. */
|
||||
#define CMP_DEFAULT_SMAA_THRESHOLD 1.0f
|
||||
#define CMP_DEFAULT_SMAA_CONTRAST_LIMIT 0.2f
|
||||
#define CMP_DEFAULT_SMAA_CORNER_ROUNDING 0.25f
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
@@ -799,6 +799,16 @@ static void write_compositor_legacy_properties(bNodeTree &node_tree)
|
||||
NodeDenoise *storage = static_cast<NodeDenoise *>(node->storage);
|
||||
write_input_to_property_bool_char("HDR", storage->hdr);
|
||||
}
|
||||
|
||||
if (node->type_legacy == CMP_NODE_ANTIALIASING) {
|
||||
NodeAntiAliasingData *storage = static_cast<NodeAntiAliasingData *>(node->storage);
|
||||
write_input_to_property_float("Threshold", storage->threshold);
|
||||
write_input_to_property_float("Corner Rounding", storage->corner_rounding);
|
||||
|
||||
/* Contrast limit was previously divided by 10. */
|
||||
const bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, "Contrast Limit");
|
||||
storage->contrast_limit = input->default_value_typed<bNodeSocketValueFloat>()->value / 10.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2619,6 +2619,73 @@ static void do_version_denoise_node_options_to_inputs_animation(bNodeTree *node_
|
||||
});
|
||||
}
|
||||
|
||||
/* The options were converted into inputs. */
|
||||
static void do_version_anti_alias_node_options_to_inputs(bNodeTree *node_tree, bNode *node)
|
||||
{
|
||||
NodeAntiAliasingData *storage = static_cast<NodeAntiAliasingData *>(node->storage);
|
||||
if (!storage) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blender::bke::node_find_socket(*node, SOCK_IN, "Threshold")) {
|
||||
bNodeSocket *input = blender::bke::node_add_static_socket(
|
||||
*node_tree, *node, SOCK_IN, SOCK_FLOAT, PROP_FACTOR, "Threshold", "Threshold");
|
||||
input->default_value_typed<bNodeSocketValueFloat>()->value = storage->threshold;
|
||||
}
|
||||
|
||||
if (!blender::bke::node_find_socket(*node, SOCK_IN, "Contrast Limit")) {
|
||||
bNodeSocket *input = blender::bke::node_add_static_socket(
|
||||
*node_tree, *node, SOCK_IN, SOCK_FLOAT, PROP_NONE, "Contrast Limit", "Contrast Limit");
|
||||
/* Contrast limit was previously divided by 10. */
|
||||
input->default_value_typed<bNodeSocketValueFloat>()->value = storage->contrast_limit * 10.0f;
|
||||
}
|
||||
|
||||
if (!blender::bke::node_find_socket(*node, SOCK_IN, "Corner Rounding")) {
|
||||
bNodeSocket *input = blender::bke::node_add_static_socket(
|
||||
*node_tree, *node, SOCK_IN, SOCK_FLOAT, PROP_FACTOR, "Corner Rounding", "Corner Rounding");
|
||||
input->default_value_typed<bNodeSocketValueFloat>()->value = storage->corner_rounding;
|
||||
}
|
||||
}
|
||||
|
||||
/* The options were converted into inputs. */
|
||||
static void do_version_anti_alias_node_options_to_inputs_animation(bNodeTree *node_tree,
|
||||
bNode *node)
|
||||
{
|
||||
/* Compute the RNA path of the node. */
|
||||
char escaped_node_name[sizeof(node->name) * 2 + 1];
|
||||
BLI_str_escape(escaped_node_name, node->name, sizeof(escaped_node_name));
|
||||
const std::string node_rna_path = fmt::format("nodes[\"{}\"]", escaped_node_name);
|
||||
|
||||
BKE_fcurves_id_cb(&node_tree->id, [&](ID * /*id*/, FCurve *fcurve) {
|
||||
/* The FCurve does not belong to the node since its RNA path doesn't start with the node's RNA
|
||||
* path. */
|
||||
if (!blender::StringRef(fcurve->rna_path).startswith(node_rna_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Change the RNA path of the FCurve from the old properties to the new inputs, adjusting the
|
||||
* values of the FCurves frames when needed. */
|
||||
char *old_rna_path = fcurve->rna_path;
|
||||
if (BLI_str_endswith(fcurve->rna_path, "threshold")) {
|
||||
fcurve->rna_path = BLI_sprintfN("%s.%s", node_rna_path.c_str(), "inputs[1].default_value");
|
||||
}
|
||||
else if (BLI_str_endswith(fcurve->rna_path, "contrast_limit")) {
|
||||
fcurve->rna_path = BLI_sprintfN("%s.%s", node_rna_path.c_str(), "inputs[2].default_value");
|
||||
/* Contrast limit was previously divided by 10. */
|
||||
adjust_fcurve_key_frame_values(
|
||||
fcurve, PROP_FLOAT, [&](const float value) { return value * 10.0f; });
|
||||
}
|
||||
else if (BLI_str_endswith(fcurve->rna_path, "corner_rounding")) {
|
||||
fcurve->rna_path = BLI_sprintfN("%s.%s", node_rna_path.c_str(), "inputs[3].default_value");
|
||||
}
|
||||
|
||||
/* The RNA path was changed, free the old path. */
|
||||
if (fcurve->rna_path != old_rna_path) {
|
||||
MEM_freeN(old_rna_path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void do_version_viewer_shortcut(bNodeTree *node_tree)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (bNode *, node, &node_tree->nodes) {
|
||||
@@ -3242,6 +3309,19 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain)
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 36)) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, node_tree, id) {
|
||||
if (node_tree->type == NTREE_COMPOSIT) {
|
||||
LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) {
|
||||
if (node->type_legacy == CMP_NODE_ANTIALIASING) {
|
||||
do_version_anti_alias_node_options_to_inputs_animation(node_tree, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
||||
@@ -7983,6 +8063,19 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 36)) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, node_tree, id) {
|
||||
if (node_tree->type == NTREE_COMPOSIT) {
|
||||
LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) {
|
||||
if (node->type_legacy == CMP_NODE_ANTIALIASING) {
|
||||
do_version_anti_alias_node_options_to_inputs(node_tree, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
/* Always run this versioning (keep at the bottom of the function). Meshes are written with the
|
||||
* legacy format which always needs to be converted to the new format on file load. To be moved
|
||||
* to a subversion check in 5.0. */
|
||||
|
||||
@@ -1164,9 +1164,9 @@ typedef struct NodeKuwaharaData {
|
||||
} NodeKuwaharaData;
|
||||
|
||||
typedef struct NodeAntiAliasingData {
|
||||
float threshold;
|
||||
float contrast_limit;
|
||||
float corner_rounding;
|
||||
float threshold DNA_DEPRECATED;
|
||||
float contrast_limit DNA_DEPRECATED;
|
||||
float corner_rounding DNA_DEPRECATED;
|
||||
} NodeAntiAliasingData;
|
||||
|
||||
/** \note Only for do-version code. */
|
||||
|
||||
@@ -3806,6 +3806,27 @@ static void rna_NodeSplit_factor_set(PointerRNA *ptr, const int value)
|
||||
&input_rna_pointer, "default_value", blender::math::clamp(value / 100.0f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
static float rna_NodeAntiAlias_contrast_limit_get(PointerRNA *ptr)
|
||||
{
|
||||
bNode *node = static_cast<bNode *>(ptr->data);
|
||||
bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, "Contrast Limit");
|
||||
PointerRNA input_rna_pointer = RNA_pointer_create_discrete(
|
||||
ptr->owner_id, &RNA_NodeSocket, input);
|
||||
/* Contrast limit was previously divided by 10. */
|
||||
return blender::math::clamp(
|
||||
RNA_float_get(&input_rna_pointer, "default_value") / 10.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
static void rna_NodeAntiAlias_contrast_limit_set(PointerRNA *ptr, const float value)
|
||||
{
|
||||
bNode *node = static_cast<bNode *>(ptr->data);
|
||||
bNodeSocket *input = blender::bke::node_find_socket(*node, SOCK_IN, "Contrast Limit");
|
||||
PointerRNA input_rna_pointer = RNA_pointer_create_discrete(
|
||||
ptr->owner_id, &RNA_NodeSocket, input);
|
||||
/* Contrast limit was previously divided by 10. */
|
||||
RNA_float_set(&input_rna_pointer, "default_value", value * 10.0f);
|
||||
}
|
||||
|
||||
/* A getter that returns the value of the input socket with the given template identifier and type.
|
||||
* The RNA pointer is assumed to represent a node. */
|
||||
template<typename T, const char *identifier>
|
||||
@@ -3915,6 +3936,11 @@ static const char node_input_neighbor_threshold[] = "Neighbor Threshold";
|
||||
/* Denoise node. */
|
||||
static const char node_input_hdr[] = "HDR";
|
||||
|
||||
/* Anti-Alias node. */
|
||||
static const char node_input_threshold[] = "Threshold";
|
||||
static const char node_input_contrast_limit[] = "Contrast Limit";
|
||||
static const char node_input_corner_rounding[] = "Corner Rounding";
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* White Balance Node.
|
||||
*/
|
||||
@@ -10116,19 +10142,23 @@ static void def_cmp_antialiasing(BlenderRNA * /*brna*/, StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "NodeAntiAliasingData", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "threshold");
|
||||
RNA_def_property_float_funcs(prop,
|
||||
"rna_node_property_to_input_getter<float, node_input_threshold>",
|
||||
"rna_node_property_to_input_setter<float, node_input_threshold>",
|
||||
nullptr);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Threshold",
|
||||
"Threshold to detect edges (smaller threshold makes more sensitive detection)");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Threshold",
|
||||
"Threshold to detect edges (smaller threshold makes more sensitive "
|
||||
"detection). (Deprecated: Use Threshold input instead.)");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "contrast_limit", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "contrast_limit");
|
||||
RNA_def_property_float_funcs(prop,
|
||||
"rna_NodeAntiAlias_contrast_limit_get",
|
||||
"rna_NodeAntiAlias_contrast_limit_set",
|
||||
nullptr);
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
|
||||
RNA_def_property_ui_text(
|
||||
@@ -10136,14 +10166,22 @@ static void def_cmp_antialiasing(BlenderRNA * /*brna*/, StructRNA *srna)
|
||||
"Contrast Limit",
|
||||
"How much to eliminate spurious edges to avoid artifacts (the larger value makes less "
|
||||
"active; the value 2.0, for example, means discard a detected edge if there is a "
|
||||
"neighboring edge that has 2.0 times bigger contrast than the current one)");
|
||||
"neighboring edge that has 2.0 times bigger contrast than the current one). (Deprecated: "
|
||||
"Use Contrast Limit input instead.)");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "corner_rounding", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "corner_rounding");
|
||||
RNA_def_property_float_funcs(
|
||||
prop,
|
||||
"rna_node_property_to_input_getter<float, node_input_corner_rounding>",
|
||||
"rna_node_property_to_input_setter<float, node_input_corner_rounding>",
|
||||
nullptr);
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
|
||||
RNA_def_property_ui_text(prop, "Corner Rounding", "How much sharp corners will be rounded");
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Corner Rounding",
|
||||
"How much sharp corners will be rounded. (Deprecated: Use Corner Rounding input instead.)");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
|
||||
@@ -18,38 +18,47 @@
|
||||
|
||||
namespace blender::nodes::node_composite_antialiasing_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodeAntiAliasingData)
|
||||
|
||||
static void cmp_node_antialiasing_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>("Image")
|
||||
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
|
||||
.compositor_domain_priority(0);
|
||||
b.add_input<decl::Float>("Threshold")
|
||||
.default_value(0.2f)
|
||||
.subtype(PROP_FACTOR)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.description(
|
||||
"Specifies the threshold or sensitivity to edges. Lowering this value you will be able "
|
||||
"to detect more edges at the expense of performance")
|
||||
.compositor_expects_single_value();
|
||||
b.add_input<decl::Float>("Contrast Limit")
|
||||
.default_value(2.0f)
|
||||
.min(0.0f)
|
||||
.description(
|
||||
"If there is an neighbor edge that has a Contrast Limit times bigger contrast than "
|
||||
"current edge, current edge will be discarded. This allows to eliminate spurious "
|
||||
"crossing edges")
|
||||
.compositor_expects_single_value();
|
||||
b.add_input<decl::Float>("Corner Rounding")
|
||||
.default_value(0.25f)
|
||||
.subtype(PROP_FACTOR)
|
||||
.min(0.0f)
|
||||
.max(1.0f)
|
||||
.description("Specifies how much sharp corners will be rounded")
|
||||
.compositor_expects_single_value();
|
||||
|
||||
b.add_output<decl::Color>("Image");
|
||||
}
|
||||
|
||||
static void node_composit_init_antialiasing(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
/* All members are deprecated and needn't be set, but the data is still allocated for forward
|
||||
* compatibility. */
|
||||
NodeAntiAliasingData *data = MEM_callocN<NodeAntiAliasingData>(__func__);
|
||||
|
||||
data->threshold = CMP_DEFAULT_SMAA_THRESHOLD;
|
||||
data->contrast_limit = CMP_DEFAULT_SMAA_CONTRAST_LIMIT;
|
||||
data->corner_rounding = CMP_DEFAULT_SMAA_CORNER_ROUNDING;
|
||||
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
static void node_composit_buts_antialiasing(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiLayout *col;
|
||||
|
||||
col = uiLayoutColumn(layout, false);
|
||||
|
||||
uiItemR(col, ptr, "threshold", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
||||
uiItemR(col, ptr, "contrast_limit", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
||||
uiItemR(col, ptr, "corner_rounding", UI_ITEM_NONE, std::nullopt, ICON_NONE);
|
||||
}
|
||||
|
||||
using namespace blender::compositor;
|
||||
|
||||
class AntiAliasingOperation : public NodeOperation {
|
||||
@@ -58,33 +67,35 @@ class AntiAliasingOperation : public NodeOperation {
|
||||
|
||||
void execute() override
|
||||
{
|
||||
smaa(context(),
|
||||
get_input("Image"),
|
||||
get_result("Image"),
|
||||
get_threshold(),
|
||||
get_local_contrast_adaptation_factor(),
|
||||
get_corner_rounding());
|
||||
smaa(this->context(),
|
||||
this->get_input("Image"),
|
||||
this->get_result("Image"),
|
||||
this->get_threshold(),
|
||||
this->get_local_contrast_adaptation_factor(),
|
||||
this->get_corner_rounding());
|
||||
}
|
||||
|
||||
/* Blender encodes the threshold in the [0, 1] range, while the SMAA algorithm expects it in
|
||||
* the [0, 0.5] range. */
|
||||
/* We encode the threshold in the [0, 1] range, while the SMAA algorithm expects it in the
|
||||
* [0, 0.5] range. */
|
||||
float get_threshold()
|
||||
{
|
||||
return node_storage(bnode()).threshold / 2.0f;
|
||||
return math::clamp(this->get_input("Threshold").get_single_value_default(0.2f), 0.0f, 1.0f) /
|
||||
2.0f;
|
||||
}
|
||||
|
||||
/* Blender encodes the local contrast adaptation factor in the [0, 1] range, while the SMAA
|
||||
* algorithm expects it in the [0, 10] range. */
|
||||
float get_local_contrast_adaptation_factor()
|
||||
{
|
||||
return node_storage(bnode()).contrast_limit * 10.0f;
|
||||
return math::max(0.0f, this->get_input("Contrast Limit").get_single_value_default(2.0f));
|
||||
}
|
||||
|
||||
/* Blender encodes the corner rounding factor in the float [0, 1] range, while the SMAA algorithm
|
||||
/* We encode the corner rounding factor in the float [0, 1] range, while the SMAA algorithm
|
||||
* expects it in the integer [0, 100] range. */
|
||||
int get_corner_rounding()
|
||||
{
|
||||
return int(node_storage(bnode()).corner_rounding * 100.0f);
|
||||
return int(math::clamp(this->get_input("Corner Rounding").get_single_value_default(0.25f),
|
||||
0.0f,
|
||||
1.0f) *
|
||||
100.0f);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -107,7 +118,6 @@ void register_node_type_cmp_antialiasing()
|
||||
ntype.enum_name_legacy = "ANTIALIASING";
|
||||
ntype.nclass = NODE_CLASS_OP_FILTER;
|
||||
ntype.declare = file_ns::cmp_node_antialiasing_declare;
|
||||
ntype.draw_buttons = file_ns::node_composit_buts_antialiasing;
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
blender::bke::node_type_size(ntype, 170, 140, 200);
|
||||
ntype.initfunc = file_ns::node_composit_init_antialiasing;
|
||||
|
||||
Reference in New Issue
Block a user