Compositor: Add High Precision option to Kuwahara #115763
|
@ -25,6 +25,7 @@ void KuwaharaNode::convert_to_operations(NodeConverter &converter,
|
|||
switch (data->variation) {
|
||||
case CMP_NODE_KUWAHARA_CLASSIC: {
|
||||
KuwaharaClassicOperation *kuwahara_classic = new KuwaharaClassicOperation();
|
||||
kuwahara_classic->set_data(data);
|
||||
converter.add_operation(kuwahara_classic);
|
||||
converter.map_input_socket(get_input_socket(0), kuwahara_classic->get_input_socket(0));
|
||||
converter.map_input_socket(get_input_socket(1), kuwahara_classic->get_input_socket(1));
|
||||
|
|
|
@ -54,8 +54,10 @@ void KuwaharaClassicOperation::execute_pixel_sampled(float output[4],
|
|||
size_reader_->read_sampled(size, x, y, sampler);
|
||||
const int kernel_size = int(math::max(0.0f, size[0]));
|
||||
|
||||
/* Naive implementation is more accurate for small kernel sizes. */
|
||||
if (kernel_size >= 4) {
|
||||
/* For high radii, we accelerate the filter using a summed area table, making the filter
|
||||
* execute in constant time as opposed to having quadratic complexity. Except if high precision
|
||||
* is enabled, since summed area tables are less precise. */
|
||||
if (!data_->high_precision && size[0] > 5.0f) {
|
||||
for (int q = 0; q < 4; q++) {
|
||||
/* A fancy expression to compute the sign of the quadrant q. */
|
||||
int2 sign = int2((q % 2) * 2 - 1, ((q / 2) * 2 - 1));
|
||||
|
@ -172,10 +174,13 @@ void KuwaharaClassicOperation::update_memory_buffer_partial(MemoryBuffer *output
|
|||
float4 mean_of_squared_color[4] = {float4(0.0f), float4(0.0f), float4(0.0f), float4(0.0f)};
|
||||
int quadrant_pixel_count[4] = {0, 0, 0, 0};
|
||||
|
||||
const int kernel_size = int(math::max(0.0f, *size_image->get_elem(x, y)));
|
||||
const float size = *size_image->get_elem(x, y);
|
||||
const int kernel_size = int(math::max(0.0f, size));
|
||||
|
||||
/* Naive implementation is more accurate for small kernel sizes. */
|
||||
if (kernel_size >= 4) {
|
||||
/* For high radii, we accelerate the filter using a summed area table, making the filter
|
||||
* execute in constant time as opposed to having quadratic complexity. Except if high precision
|
||||
* is enabled, since summed area tables are less precise. */
|
||||
if (!data_->high_precision && size > 5.0f) {
|
||||
for (int q = 0; q < 4; q++) {
|
||||
/* A fancy expression to compute the sign of the quadrant q. */
|
||||
int2 sign = int2((q % 2) * 2 - 1, ((q / 2) * 2 - 1));
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
namespace blender::compositor {
|
||||
|
||||
class KuwaharaClassicOperation : public MultiThreadedOperation {
|
||||
const NodeKuwaharaData *data_;
|
||||
SocketReader *image_reader_;
|
||||
SocketReader *size_reader_;
|
||||
SocketReader *sat_reader_;
|
||||
|
@ -17,6 +18,11 @@ class KuwaharaClassicOperation : public MultiThreadedOperation {
|
|||
public:
|
||||
KuwaharaClassicOperation();
|
||||
|
||||
void set_data(const NodeKuwaharaData *data)
|
||||
{
|
||||
data_ = data;
|
||||
}
|
||||
|
||||
void init_execution() override;
|
||||
void deinit_execution() override;
|
||||
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
|
|
@ -1067,6 +1067,8 @@ typedef struct NodeKuwaharaData {
|
|||
int uniformity;
|
||||
float sharpness;
|
||||
float eccentricity;
|
||||
char high_precision;
|
||||
char _pad[3];
|
||||
} NodeKuwaharaData;
|
||||
|
||||
typedef struct NodeAntiAliasingData {
|
||||
|
|
|
@ -8582,6 +8582,14 @@ static void def_cmp_kuwahara(StructRNA *srna)
|
|||
RNA_def_property_ui_text(prop, "", "Variation of Kuwahara filter to use");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_high_precision", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "high_precision", 1);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"High Precision",
|
||||
"Uses a more precise but slower method. Use if the output contains undesirable noise");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "uniformity", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "uniformity");
|
||||
RNA_def_property_range(prop, 0.0, 50.0);
|
||||
|
|
|
@ -57,7 +57,10 @@ static void node_composit_buts_kuwahara(uiLayout *layout, bContext * /*C*/, Poin
|
|||
|
||||
const int variation = RNA_enum_get(ptr, "variation");
|
||||
|
||||
if (variation == CMP_NODE_KUWAHARA_ANISOTROPIC) {
|
||||
if (variation == CMP_NODE_KUWAHARA_CLASSIC) {
|
||||
uiItemR(col, ptr, "use_high_precision", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
}
|
||||
else if (variation == CMP_NODE_KUWAHARA_ANISOTROPIC) {
|
||||
uiItemR(col, ptr, "uniformity", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "sharpness", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
uiItemR(col, ptr, "eccentricity", UI_ITEM_NONE, nullptr, ICON_NONE);
|
||||
|
@ -88,9 +91,12 @@ class ConvertKuwaharaOperation : public NodeOperation {
|
|||
void execute_classic()
|
||||
{
|
||||
/* For high radii, we accelerate the filter using a summed area table, making the filter
|
||||
* execute in constant time as opposed to the trivial quadratic complexity. */
|
||||
* execute in constant time as opposed to having quadratic complexity. Except if high precision
|
||||
* is enabled, since summed area tables are less precise. */
|
||||
Result &size_input = get_input("Size");
|
||||
if (size_input.is_single_value() && size_input.get_float_value() > 5.0f) {
|
||||
if (!node_storage(bnode()).high_precision &&
|
||||
(size_input.is_texture() || size_input.get_float_value() > 5.0f))
|
||||
{
|
||||
execute_classic_summed_area_table();
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue