Compositor: Adds extension modes to map UV node
This commit introduces the extension modes for the map UV node. The drop-down for the extension modes is only shown if the interpolation mode is not set to anisotropic. This is due to extension modes currently not being supported for the anisotropic filtering. Pull Request: https://projects.blender.org/blender/blender/pulls/143415
This commit is contained in:
committed by
Omar Emara
parent
f03392a09a
commit
53832755ae
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_brush_types.h"
|
||||
#include "DNA_curves_types.h"
|
||||
@@ -2039,6 +2041,28 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 50)) {
|
||||
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
|
||||
if (ntree->type != NTREE_COMPOSIT) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type_legacy != CMP_NODE_MAP_UV) {
|
||||
continue;
|
||||
}
|
||||
if (node->storage != nullptr) {
|
||||
continue;
|
||||
}
|
||||
NodeMapUVData *data = MEM_callocN<NodeMapUVData>(__func__);
|
||||
data->interpolation = node->custom2;
|
||||
data->extension_x = CMP_NODE_EXTENSION_MODE_CLIP;
|
||||
data->extension_y = CMP_NODE_EXTENSION_MODE_CLIP;
|
||||
node->storage = data;
|
||||
}
|
||||
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.
|
||||
|
||||
@@ -1599,6 +1599,12 @@ typedef struct NodeDisplaceData {
|
||||
char extension_y;
|
||||
} NodeDisplaceData;
|
||||
|
||||
typedef struct NodeMapUVData {
|
||||
short interpolation;
|
||||
char extension_x;
|
||||
char extension_y;
|
||||
} NodeMapUVData;
|
||||
|
||||
typedef struct NodePlaneTrackDeformData {
|
||||
char tracking_object[64];
|
||||
char plane_track_name[64];
|
||||
|
||||
@@ -6966,12 +6966,26 @@ static void def_cmp_double_edge_mask(BlenderRNA * /*brna*/, StructRNA *srna)
|
||||
|
||||
static void def_cmp_map_uv(BlenderRNA * /*brna*/, StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
PropertyRNA *prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "custom2");
|
||||
RNA_def_struct_sdna_from(srna, "NodeMapUVData", "storage");
|
||||
|
||||
prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "interpolation");
|
||||
RNA_def_property_enum_items(prop, cmp_interpolation_items);
|
||||
RNA_def_property_ui_text(prop, "Filter Type", "");
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_NODETREE);
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* \ingroup cmpnodes
|
||||
*/
|
||||
|
||||
#include "BKE_node.hh"
|
||||
|
||||
#include "BLI_assert.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
@@ -15,6 +17,10 @@
|
||||
#include "GPU_shader.hh"
|
||||
#include "GPU_texture.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
|
||||
#include "UI_interface_layout.hh"
|
||||
#include "UI_resources.hh"
|
||||
|
||||
@@ -28,6 +34,8 @@
|
||||
|
||||
namespace blender::nodes::node_composite_map_uv_cc {
|
||||
|
||||
NODE_STORAGE_FUNCS(NodeMapUVData)
|
||||
|
||||
static void cmp_node_map_uv_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>("Image")
|
||||
@@ -49,12 +57,22 @@ static void cmp_node_map_uv_declare(NodeDeclarationBuilder &b)
|
||||
|
||||
static void node_composit_buts_map_uv(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
layout->prop(ptr, "filter_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
uiLayout &column = layout->column(true);
|
||||
column.prop(ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
if (RNA_enum_get(ptr, "interpolation") != CMP_NODE_INTERPOLATION_ANISOTROPIC) {
|
||||
uiLayout &row = column.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);
|
||||
}
|
||||
}
|
||||
|
||||
static void node_composit_init_map_uv(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
node->custom2 = CMP_NODE_INTERPOLATION_ANISOTROPIC;
|
||||
NodeMapUVData *data = MEM_callocN<NodeMapUVData>(__func__);
|
||||
data->interpolation = CMP_NODE_INTERPOLATION_BILINEAR;
|
||||
data->extension_x = CMP_NODE_EXTENSION_MODE_CLIP;
|
||||
data->extension_y = CMP_NODE_EXTENSION_MODE_CLIP;
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
using namespace blender::compositor;
|
||||
@@ -97,7 +115,11 @@ class MapUVOperation : public NodeOperation {
|
||||
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(this->get_extension_mode_x()));
|
||||
GPU_texture_extend_mode_y(input_image,
|
||||
map_extension_mode_to_extend_mode(this->get_extension_mode_y()));
|
||||
|
||||
input_image.bind_as_texture(shader, "input_tx");
|
||||
|
||||
const Result &input_uv = get_input("UV");
|
||||
@@ -134,39 +156,31 @@ class MapUVOperation : public NodeOperation {
|
||||
void execute_cpu()
|
||||
{
|
||||
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 Result &input_uv = get_input("UV");
|
||||
if (input_uv.is_single_value()) {
|
||||
this->execute_single_cpu(interpolation);
|
||||
this->execute_single_cpu(interpolation, extension_x, extension_y);
|
||||
return;
|
||||
}
|
||||
if (interpolation == Interpolation::Anisotropic) {
|
||||
this->execute_cpu_anisotropic();
|
||||
}
|
||||
else {
|
||||
this->execute_cpu_interpolation(interpolation);
|
||||
this->execute_cpu_interpolation(interpolation, extension_x, extension_y);
|
||||
}
|
||||
}
|
||||
|
||||
void execute_single_cpu(const Interpolation &interpolation)
|
||||
void execute_single_cpu(const Interpolation &interpolation,
|
||||
const ExtensionMode &extension_mode_x,
|
||||
const ExtensionMode &extension_mode_y)
|
||||
{
|
||||
const Result &input_uv = get_input("UV");
|
||||
const Result &input_image = get_input("Image");
|
||||
|
||||
float2 uv_coordinates = input_uv.get_single_value<float3>().xy();
|
||||
float4 sampled_color{0.0f};
|
||||
switch (interpolation) {
|
||||
case Interpolation::Nearest:
|
||||
sampled_color = input_image.sample_nearest_zero(uv_coordinates);
|
||||
break;
|
||||
case Interpolation::Bilinear:
|
||||
sampled_color = input_image.sample_bilinear_zero(uv_coordinates);
|
||||
break;
|
||||
/* NOTE: The anisotropic case should be handled after reimplementation of EWA. */
|
||||
case Interpolation::Anisotropic:
|
||||
case Interpolation::Bicubic:
|
||||
sampled_color = input_image.sample_cubic_wrap(uv_coordinates, false, false);
|
||||
break;
|
||||
}
|
||||
float4 sampled_color = input_image.sample(
|
||||
uv_coordinates, interpolation, extension_mode_x, extension_mode_y);
|
||||
|
||||
/* The UV input is assumed to contain an alpha channel as its third channel, since the
|
||||
* UV coordinates might be defined in only a subset area of the UV texture as mentioned.
|
||||
@@ -183,7 +197,9 @@ class MapUVOperation : public NodeOperation {
|
||||
output.set_single_value(result);
|
||||
}
|
||||
|
||||
void execute_cpu_interpolation(const Interpolation &interpolation)
|
||||
void execute_cpu_interpolation(const Interpolation &interpolation,
|
||||
const ExtensionMode &extension_mode_x,
|
||||
const ExtensionMode &extension_mode_y)
|
||||
{
|
||||
const Result &input_image = get_input("Image");
|
||||
const Result &input_uv = get_input("UV");
|
||||
@@ -194,24 +210,8 @@ class MapUVOperation : public NodeOperation {
|
||||
|
||||
parallel_for(domain.size, [&](const int2 texel) {
|
||||
float2 uv_coordinates = input_uv.load_pixel<float3>(texel).xy();
|
||||
float4 sampled_color{0.0f};
|
||||
|
||||
switch (interpolation) {
|
||||
/* Anisotropic is handled separately. */
|
||||
case Interpolation::Anisotropic:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
case Interpolation::Nearest:
|
||||
sampled_color = input_image.sample_nearest_zero(uv_coordinates);
|
||||
break;
|
||||
case Interpolation::Bilinear:
|
||||
sampled_color = input_image.sample_bilinear_zero(uv_coordinates);
|
||||
break;
|
||||
case Interpolation::Bicubic:
|
||||
sampled_color = input_image.sample_cubic_wrap(uv_coordinates, false, false);
|
||||
break;
|
||||
}
|
||||
|
||||
float4 sampled_color = input_image.sample(
|
||||
uv_coordinates, interpolation, extension_mode_x, extension_mode_y);
|
||||
/* The UV input is assumed to contain an alpha channel as its third channel, since the
|
||||
* UV coordinates might be defined in only a subset area of the UV texture as mentioned.
|
||||
* In that case, the alpha is typically opaque at the subset area and transparent
|
||||
@@ -303,7 +303,7 @@ class MapUVOperation : public NodeOperation {
|
||||
|
||||
Interpolation get_interpolation() const
|
||||
{
|
||||
switch (static_cast<CMPNodeInterpolation>(bnode().custom2)) {
|
||||
switch (static_cast<CMPNodeInterpolation>(node_storage(bnode()).interpolation)) {
|
||||
case CMP_NODE_INTERPOLATION_ANISOTROPIC:
|
||||
return Interpolation::Anisotropic;
|
||||
case CMP_NODE_INTERPOLATION_NEAREST:
|
||||
@@ -317,6 +317,36 @@ class MapUVOperation : public NodeOperation {
|
||||
BLI_assert_unreachable();
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
static NodeOperation *get_compositor_operation(Context &context, DNode node)
|
||||
@@ -342,6 +372,8 @@ static void register_node_type_cmp_mapuv()
|
||||
ntype.draw_buttons = file_ns::node_composit_buts_map_uv;
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
ntype.initfunc = file_ns::node_composit_init_map_uv;
|
||||
blender::bke::node_type_storage(
|
||||
ntype, "NodeMapUVData", node_free_standard_storage, node_copy_standard_storage);
|
||||
|
||||
blender::bke::node_register_type(ntype);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user