Compositor: Add extension modes to displacement node
The node uses anisotropic sampling (which is currently not supported for the extension mode), so extension modes are only rendered in the node if any other interpolation method, but anisotropic is selected. Pull Request: https://projects.blender.org/blender/blender/pulls/143367
This commit is contained in:
committed by
Omar Emara
parent
d77c98d1d4
commit
481c524734
@@ -27,7 +27,7 @@
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 48
|
||||
#define BLENDER_FILE_SUBVERSION 49
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -2019,6 +2019,26 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 49)) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type != NTREE_COMPOSIT) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type_legacy != CMP_NODE_DISPLACE) {
|
||||
continue;
|
||||
}
|
||||
if (node->storage == nullptr) {
|
||||
continue;
|
||||
}
|
||||
NodeDisplaceData *data = static_cast<NodeDisplaceData *>(node->storage);
|
||||
data->extension_x = CMP_NODE_EXTENSION_MODE_CLIP;
|
||||
data->extension_y = CMP_NODE_EXTENSION_MODE_CLIP;
|
||||
}
|
||||
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.
|
||||
|
||||
@@ -1595,6 +1595,8 @@ typedef struct NodeScaleData {
|
||||
|
||||
typedef struct NodeDisplaceData {
|
||||
short interpolation;
|
||||
char extension_x;
|
||||
char extension_y;
|
||||
} NodeDisplaceData;
|
||||
|
||||
typedef struct NodePlaneTrackDeformData {
|
||||
|
||||
@@ -6682,6 +6682,18 @@ static void def_cmp_displace(BlenderRNA * /*brna*/, StructRNA *srna)
|
||||
RNA_def_property_enum_items(prop, cmp_interpolation_items);
|
||||
RNA_def_property_ui_text(prop, "Interpolation", "Interpolation method");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "extension_x", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "extension_x");
|
||||
RNA_def_property_enum_items(prop, cmp_extension_mode_items);
|
||||
RNA_def_property_ui_text(prop, "X Extension Mode", "The extension mode applied to the X axis");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
|
||||
prop = RNA_def_property(srna, "extension_y", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "extension_y");
|
||||
RNA_def_property_enum_items(prop, cmp_extension_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Y Extension Mode", "The extension mode applied to the Y axis");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_cmp_scale(BlenderRNA * /*brna*/, StructRNA *srna)
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
#include "BLI_assert.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_types.hh"
|
||||
|
||||
#include "GPU_shader.hh"
|
||||
@@ -64,12 +66,22 @@ static void cmp_node_init_displace(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
NodeDisplaceData *data = MEM_callocN<NodeDisplaceData>(__func__);
|
||||
data->interpolation = CMP_NODE_INTERPOLATION_ANISOTROPIC;
|
||||
data->extension_x = CMP_NODE_EXTENSION_MODE_CLIP;
|
||||
data->extension_y = CMP_NODE_EXTENSION_MODE_CLIP;
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
static void cmp_buts_displace(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
layout->prop(ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
uiLayout &column_interpolation_extension_modes = layout->column(true);
|
||||
|
||||
column_interpolation_extension_modes.prop(
|
||||
ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
if (RNA_enum_get(ptr, "interpolation") != CMP_NODE_INTERPOLATION_ANISOTROPIC) {
|
||||
uiLayout &row = column_interpolation_extension_modes.row(true);
|
||||
row.prop(ptr, "extension_x", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
row.prop(ptr, "extension_y", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace blender::compositor;
|
||||
@@ -98,6 +110,8 @@ class DisplaceOperation : public NodeOperation {
|
||||
void execute_gpu()
|
||||
{
|
||||
const Interpolation interpolation = this->get_interpolation();
|
||||
const ExtensionMode extension_x = this->get_extension_mode_x();
|
||||
const ExtensionMode extension_y = this->get_extension_mode_y();
|
||||
GPUShader *shader = context().get_shader(this->get_shader_name(interpolation));
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
@@ -111,7 +125,8 @@ class DisplaceOperation : public NodeOperation {
|
||||
interpolation, Interpolation::Bilinear, Interpolation::Bicubic);
|
||||
GPU_texture_filter_mode(input_image, use_bilinear);
|
||||
}
|
||||
GPU_texture_extend_mode(input_image, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
|
||||
GPU_texture_extend_mode_x(input_image, map_extension_mode_to_extend_mode(extension_x));
|
||||
GPU_texture_extend_mode_y(input_image, map_extension_mode_to_extend_mode(extension_y));
|
||||
input_image.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const Result &input_displacement = get_input("Vector");
|
||||
@@ -144,6 +159,8 @@ class DisplaceOperation : public NodeOperation {
|
||||
const Result &y_scale = get_input("Y Scale");
|
||||
|
||||
const Interpolation interpolation = this->get_interpolation();
|
||||
const ExtensionMode extension_x = this->get_extension_mode_x();
|
||||
const ExtensionMode extension_y = this->get_extension_mode_y();
|
||||
const Domain domain = compute_domain();
|
||||
Result &output = get_result("Image");
|
||||
output.allocate_texture(domain);
|
||||
@@ -154,8 +171,15 @@ class DisplaceOperation : public NodeOperation {
|
||||
this->compute_anisotropic(size, image, output, input_displacement, x_scale, y_scale);
|
||||
}
|
||||
else {
|
||||
this->compute_interpolation(
|
||||
interpolation, size, image, output, input_displacement, x_scale, y_scale);
|
||||
this->compute_interpolation(interpolation,
|
||||
size,
|
||||
image,
|
||||
output,
|
||||
input_displacement,
|
||||
x_scale,
|
||||
y_scale,
|
||||
extension_x,
|
||||
extension_y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,26 +189,16 @@ class DisplaceOperation : public NodeOperation {
|
||||
Result &output,
|
||||
const Result &input_displacement,
|
||||
const Result &x_scale,
|
||||
const Result &y_scale) const
|
||||
const Result &y_scale,
|
||||
const ExtensionMode &extension_mode_x,
|
||||
const ExtensionMode &extension_mode_y) const
|
||||
{
|
||||
parallel_for(size, [&](const int2 base_texel) {
|
||||
const float2 coordinates = compute_coordinates(
|
||||
base_texel, size, input_displacement, x_scale, y_scale);
|
||||
switch (interpolation) {
|
||||
/* The anisotropic case requires gradient computation and is handled separately. */
|
||||
case Interpolation::Anisotropic:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
case Interpolation::Nearest:
|
||||
output.store_pixel(base_texel, image.sample_nearest_zero(coordinates));
|
||||
break;
|
||||
case Interpolation::Bilinear:
|
||||
output.store_pixel(base_texel, image.sample_bilinear_zero(coordinates));
|
||||
break;
|
||||
case Interpolation::Bicubic:
|
||||
output.store_pixel(base_texel, image.sample_cubic_wrap(coordinates, false, false));
|
||||
break;
|
||||
}
|
||||
output.store_pixel(
|
||||
base_texel,
|
||||
image.sample(coordinates, interpolation, extension_mode_x, extension_mode_y));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -307,6 +321,36 @@ class DisplaceOperation : public NodeOperation {
|
||||
return Interpolation::Nearest;
|
||||
}
|
||||
|
||||
ExtensionMode get_extension_mode_x()
|
||||
{
|
||||
switch (static_cast<CMPExtensionMode>(node_storage(bnode()).extension_x)) {
|
||||
case CMP_NODE_EXTENSION_MODE_CLIP:
|
||||
return ExtensionMode::Clip;
|
||||
case CMP_NODE_EXTENSION_MODE_REPEAT:
|
||||
return ExtensionMode::Repeat;
|
||||
case CMP_NODE_EXTENSION_MODE_EXTEND:
|
||||
return ExtensionMode::Extend;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return ExtensionMode::Clip;
|
||||
}
|
||||
|
||||
ExtensionMode get_extension_mode_y()
|
||||
{
|
||||
switch (static_cast<CMPExtensionMode>(node_storage(bnode()).extension_y)) {
|
||||
case CMP_NODE_EXTENSION_MODE_CLIP:
|
||||
return ExtensionMode::Clip;
|
||||
case CMP_NODE_EXTENSION_MODE_REPEAT:
|
||||
return ExtensionMode::Repeat;
|
||||
case CMP_NODE_EXTENSION_MODE_EXTEND:
|
||||
return ExtensionMode::Extend;
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return ExtensionMode::Clip;
|
||||
}
|
||||
|
||||
bool is_identity()
|
||||
{
|
||||
const Result &input_image = get_input("Image");
|
||||
|
||||
Reference in New Issue
Block a user