Compositor: Remove Texture node
This patch removes the Texture node from the compositor, which was based on the legacy Internal Textures system in Blender. The main motivation for removing this node is as follows: - Procedural texturing nodes that previously existed in shading and geometry nodes are now supported in the compositor, which cover 95% of what is previously possible using and even adds new possibilities like Gabor, Bricks, and various improvements to existing texture types. - The old texture system did not support GPU evaluation, so it was always computed and cached on the CPU, which causes bad performance especially for interactive use in the viewport compositor. While the new nodes are fully GPU accelerated and do not require any caching. - The Texture node didn't support Texture nodes, so it was not fully supported and we so far had a warning about that. - The general direction in Blender is to remove the old texture system, and the compositor was one of the last main users of it. 5.0 is thus the ideal time to remove such use. - The Texture node was always and still is a source of bugs, since it relies on proper tagging for cache invalidation and updates, which is so far not perfect. It also suffers from UI/UX issues, since it needs to be adjusted from the properties panel, which can break if there are other texture nodes in the context. This is a breaking change and no versioning was attempted since: 1. It is impossible to get the same results as before due to the use of different random number generators, so any versioning would just give us the general look. 2. The Texture node supports a lot of possible configurations. For instance, each general texture can have many options for the basis type, and each basis type might have multiple options. So versioning all of that will take a lot of time, code, and effort. Pull Request: https://projects.blender.org/blender/blender/pulls/140545
This commit is contained in:
@@ -27,7 +27,6 @@ class NODE_MT_category_compositor_input(Menu):
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeImageCoordinates")
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeMask")
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeMovieClip")
|
||||
node_add_menu.add_node_type(layout, "CompositorNodeTexture")
|
||||
|
||||
if is_group:
|
||||
layout.separator()
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
#define CMP_NODE_R_LAYERS 221
|
||||
#define CMP_NODE_COMPOSITE 222
|
||||
#define CMP_NODE_OUTPUT_FILE 223
|
||||
#define CMP_NODE_TEXTURE 224
|
||||
#define CMP_NODE_TEXTURE_DEPRECATED 224
|
||||
#define CMP_NODE_TRANSLATE 225
|
||||
#define CMP_NODE_ZCOMBINE 226
|
||||
#define CMP_NODE_COMBRGBA_LEGACY 227
|
||||
|
||||
@@ -673,7 +673,7 @@ static const char *node_get_static_idname(int type, int treetype)
|
||||
return "CompositorNodeComposite";
|
||||
case CMP_NODE_OUTPUT_FILE:
|
||||
return "CompositorNodeOutputFile";
|
||||
case CMP_NODE_TEXTURE:
|
||||
case CMP_NODE_TEXTURE_DEPRECATED:
|
||||
return "CompositorNodeTexture";
|
||||
case CMP_NODE_TRANSLATE:
|
||||
return "CompositorNodeTranslate";
|
||||
|
||||
@@ -104,7 +104,6 @@ set(SRC
|
||||
cached_resources/intern/cached_image.cc
|
||||
cached_resources/intern/cached_mask.cc
|
||||
cached_resources/intern/cached_shader.cc
|
||||
cached_resources/intern/cached_texture.cc
|
||||
cached_resources/intern/deriche_gaussian_coefficients.cc
|
||||
cached_resources/intern/distortion_grid.cc
|
||||
cached_resources/intern/fog_glow_kernel.cc
|
||||
@@ -122,7 +121,6 @@ set(SRC
|
||||
cached_resources/COM_cached_mask.hh
|
||||
cached_resources/COM_cached_resource.hh
|
||||
cached_resources/COM_cached_shader.hh
|
||||
cached_resources/COM_cached_texture.hh
|
||||
cached_resources/COM_deriche_gaussian_coefficients.hh
|
||||
cached_resources/COM_distortion_grid.hh
|
||||
cached_resources/COM_fog_glow_kernel.hh
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "COM_cached_image.hh"
|
||||
#include "COM_cached_mask.hh"
|
||||
#include "COM_cached_shader.hh"
|
||||
#include "COM_cached_texture.hh"
|
||||
#include "COM_deriche_gaussian_coefficients.hh"
|
||||
#include "COM_distortion_grid.hh"
|
||||
#include "COM_fog_glow_kernel.hh"
|
||||
@@ -52,7 +51,6 @@ class StaticCacheManager {
|
||||
SymmetricBlurWeightsContainer symmetric_blur_weights;
|
||||
SymmetricSeparableBlurWeightsContainer symmetric_separable_blur_weights;
|
||||
MorphologicalDistanceFeatherWeightsContainer morphological_distance_feather_weights;
|
||||
CachedTextureContainer cached_textures;
|
||||
CachedMaskContainer cached_masks;
|
||||
SMAAPrecomputedTexturesContainer smaa_precomputed_textures;
|
||||
OCIOColorSpaceConversionShaderContainer ocio_color_space_conversion_shaders;
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "DNA_texture_types.h"
|
||||
|
||||
#include "COM_cached_resource.hh"
|
||||
#include "COM_result.hh"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
class Context;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Cached Texture Key.
|
||||
*/
|
||||
class CachedTextureKey {
|
||||
public:
|
||||
int2 size;
|
||||
float3 offset;
|
||||
float3 scale;
|
||||
|
||||
CachedTextureKey(int2 size, float3 offset, float3 scale);
|
||||
|
||||
uint64_t hash() const;
|
||||
};
|
||||
|
||||
bool operator==(const CachedTextureKey &a, const CachedTextureKey &b);
|
||||
|
||||
/* -------------------------------------------------------------------------------------------------
|
||||
* Cached Texture.
|
||||
*
|
||||
* A cached resource that computes and caches a GPU texture containing the result of evaluating the
|
||||
* given texture ID on a space that spans the given size, parameterized by the given parameters. */
|
||||
class CachedTexture : public CachedResource {
|
||||
private:
|
||||
Array<float4> color_pixels_;
|
||||
Array<float> value_pixels_;
|
||||
|
||||
public:
|
||||
Result color_result;
|
||||
Result value_result;
|
||||
|
||||
CachedTexture(Context &context,
|
||||
Tex *texture,
|
||||
bool use_color_management,
|
||||
int2 size,
|
||||
float3 offset,
|
||||
float3 scale);
|
||||
|
||||
~CachedTexture();
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Cached Texture Container.
|
||||
*/
|
||||
class CachedTextureContainer : CachedResourceContainer {
|
||||
private:
|
||||
Map<std::string, Map<CachedTextureKey, std::unique_ptr<CachedTexture>>> map_;
|
||||
|
||||
/* A map that stores the update counts of the textures at the moment they were cached. */
|
||||
Map<std::string, uint64_t> update_counts_;
|
||||
|
||||
public:
|
||||
void reset() override;
|
||||
|
||||
/* Check if the given texture ID has changed since the last time it was retrieved through its
|
||||
* recalculate flag, and if so, invalidate its corresponding cached textures and reset the
|
||||
* recalculate flag to ready it to track the next change. Then, check if there is an available
|
||||
* CachedTexture cached resource with the given parameters in the container, if one exists,
|
||||
* return it, otherwise, return a newly created one and add it to the container. In both cases,
|
||||
* tag the cached resource as needed to keep it cached for the next evaluation. */
|
||||
CachedTexture &get(Context &context,
|
||||
Tex *texture,
|
||||
bool use_color_management,
|
||||
int2 size,
|
||||
float3 offset,
|
||||
float3 scale);
|
||||
};
|
||||
|
||||
} // namespace blender::compositor
|
||||
@@ -1,171 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_hash.hh"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_task.hh"
|
||||
|
||||
#include "GPU_texture.hh"
|
||||
|
||||
#include "BKE_image.hh"
|
||||
#include "BKE_texture.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_texture_types.h"
|
||||
|
||||
#include "RE_texture.h"
|
||||
|
||||
#include "COM_cached_texture.hh"
|
||||
#include "COM_context.hh"
|
||||
#include "COM_result.hh"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Cached Texture Key.
|
||||
*/
|
||||
|
||||
CachedTextureKey::CachedTextureKey(int2 size, float3 offset, float3 scale)
|
||||
: size(size), offset(offset), scale(scale)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t CachedTextureKey::hash() const
|
||||
{
|
||||
return get_default_hash(size, offset, scale);
|
||||
}
|
||||
|
||||
bool operator==(const CachedTextureKey &a, const CachedTextureKey &b)
|
||||
{
|
||||
return a.size == b.size && a.offset == b.offset && a.scale == b.scale;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Cached Texture.
|
||||
*/
|
||||
|
||||
CachedTexture::CachedTexture(Context &context,
|
||||
Tex *texture,
|
||||
bool use_color_management,
|
||||
int2 size,
|
||||
float3 offset,
|
||||
float3 scale)
|
||||
: color_result(context.create_result(ResultType::Color)),
|
||||
value_result(context.create_result(ResultType::Float))
|
||||
{
|
||||
ImagePool *image_pool = BKE_image_pool_new();
|
||||
BKE_texture_fetch_images_for_pool(texture, image_pool);
|
||||
|
||||
color_pixels_ = Array<float4>(size.x * size.y);
|
||||
value_pixels_ = Array<float>(size.x * size.y);
|
||||
threading::parallel_for(IndexRange(size.y), 1, [&](const IndexRange sub_y_range) {
|
||||
for (const int64_t y : sub_y_range) {
|
||||
for (const int64_t x : IndexRange(size.x)) {
|
||||
/* Compute the coordinates in the [-1, 1] range and add 0.5 to evaluate the texture at the
|
||||
* center of pixels in case it was interpolated. */
|
||||
const float2 pixel_coordinates = ((float2(x, y) + 0.5f) / float2(size)) * 2.0f - 1.0f;
|
||||
/* Note that it is expected that the offset is scaled by the scale. */
|
||||
const float3 coordinates = (float3(pixel_coordinates, 0.0f) + offset) * scale;
|
||||
|
||||
TexResult texture_result;
|
||||
const int result_type = multitex_ext_safe(
|
||||
texture, coordinates, &texture_result, image_pool, use_color_management, false);
|
||||
|
||||
float4 color = float4(texture_result.trgba);
|
||||
color.w = texture_result.talpha ? color.w : texture_result.tin;
|
||||
if (!(result_type & TEX_RGB)) {
|
||||
copy_v3_fl(color, color.w);
|
||||
}
|
||||
|
||||
color_pixels_[y * size.x + x] = color;
|
||||
value_pixels_[y * size.x + x] = color.w;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BKE_image_pool_free(image_pool);
|
||||
|
||||
if (context.use_gpu()) {
|
||||
this->color_result.allocate_texture(Domain(size), false);
|
||||
this->value_result.allocate_texture(Domain(size), false);
|
||||
GPU_texture_update(this->color_result, GPU_DATA_FLOAT, color_pixels_.data());
|
||||
GPU_texture_update(this->value_result, GPU_DATA_FLOAT, value_pixels_.data());
|
||||
|
||||
/* CPU-side data no longer needed, so free it. */
|
||||
color_pixels_ = Array<float4>();
|
||||
value_pixels_ = Array<float>();
|
||||
}
|
||||
else {
|
||||
this->color_result.wrap_external(&color_pixels_.data()[0].x, size);
|
||||
this->value_result.wrap_external(value_pixels_.data(), size);
|
||||
}
|
||||
}
|
||||
|
||||
CachedTexture::~CachedTexture()
|
||||
{
|
||||
this->color_result.release();
|
||||
this->value_result.release();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Cached Texture Container.
|
||||
*/
|
||||
|
||||
void CachedTextureContainer::reset()
|
||||
{
|
||||
/* First, delete all cached textures that are no longer needed. */
|
||||
for (auto &cached_textures_for_id : map_.values()) {
|
||||
cached_textures_for_id.remove_if([](auto item) { return !item.value->needed; });
|
||||
}
|
||||
map_.remove_if([](auto item) { return item.value.is_empty(); });
|
||||
update_counts_.remove_if([&](auto item) { return !map_.contains(item.key); });
|
||||
|
||||
/* Second, reset the needed status of the remaining cached textures to false to ready them to
|
||||
* track their needed status for the next evaluation. */
|
||||
for (auto &cached_textures_for_id : map_.values()) {
|
||||
for (auto &value : cached_textures_for_id.values()) {
|
||||
value->needed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CachedTexture &CachedTextureContainer::get(Context &context,
|
||||
Tex *texture,
|
||||
bool use_color_management,
|
||||
int2 size,
|
||||
float3 offset,
|
||||
float3 scale)
|
||||
{
|
||||
const CachedTextureKey key(size, offset, scale);
|
||||
|
||||
const std::string library_key = texture->id.lib ? texture->id.lib->id.name : "";
|
||||
const std::string id_key = std::string(texture->id.name) + library_key;
|
||||
auto &cached_textures_for_id = map_.lookup_or_add_default(id_key);
|
||||
|
||||
/* Invalidate the cache for that texture if it was changed since it was cached. */
|
||||
if (!cached_textures_for_id.is_empty() &&
|
||||
texture->runtime.last_update != update_counts_.lookup(id_key))
|
||||
{
|
||||
cached_textures_for_id.clear();
|
||||
}
|
||||
|
||||
auto &cached_texture = *cached_textures_for_id.lookup_or_add_cb(key, [&]() {
|
||||
return std::make_unique<CachedTexture>(
|
||||
context, texture, use_color_management, size, offset, scale);
|
||||
});
|
||||
|
||||
/* Store the current update count to later compare to and check if the texture changed. */
|
||||
update_counts_.add_overwrite(id_key, texture->runtime.last_update);
|
||||
|
||||
cached_texture.needed = true;
|
||||
return cached_texture;
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
||||
@@ -16,7 +16,6 @@ void StaticCacheManager::reset()
|
||||
symmetric_blur_weights.reset();
|
||||
symmetric_separable_blur_weights.reset();
|
||||
morphological_distance_feather_weights.reset();
|
||||
cached_textures.reset();
|
||||
cached_masks.reset();
|
||||
smaa_precomputed_textures.reset();
|
||||
ocio_color_space_conversion_shaders.reset();
|
||||
|
||||
@@ -153,13 +153,7 @@ static void buttons_texture_users_find_nodetree(ListBase *users,
|
||||
{
|
||||
if (ntree) {
|
||||
for (bNode *node : ntree->all_nodes()) {
|
||||
if (node->type_legacy == CMP_NODE_TEXTURE) {
|
||||
PointerRNA ptr = RNA_pointer_create_discrete(&ntree->id, &RNA_Node, node);
|
||||
PropertyRNA *prop = RNA_struct_find_property(&ptr, "texture");
|
||||
buttons_texture_user_node_add(
|
||||
users, id, ntree, node, ptr, prop, category, RNA_struct_ui_icon(ptr.type), node->name);
|
||||
}
|
||||
else if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
|
||||
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
|
||||
PointerRNA ptr = RNA_pointer_create_discrete(&ntree->id, &RNA_Node, node);
|
||||
buttons_texture_user_node_add(users,
|
||||
id,
|
||||
|
||||
@@ -175,7 +175,6 @@ static void node_buts_texture(uiLayout *layout, bContext *C, PointerRNA *ptr)
|
||||
bNode *node = (bNode *)ptr->data;
|
||||
|
||||
short multi = (node->id && ((Tex *)node->id)->use_nodes &&
|
||||
(node->type_legacy != CMP_NODE_TEXTURE) &&
|
||||
(node->type_legacy != TEX_NODE_TEXTURE));
|
||||
|
||||
uiTemplateID(layout, C, ptr, "texture", "texture.new", nullptr, nullptr);
|
||||
@@ -632,9 +631,6 @@ static void node_composit_set_butfunc(blender::bke::bNodeType *ntype)
|
||||
case CMP_NODE_TIME:
|
||||
ntype->draw_buttons = node_buts_time;
|
||||
break;
|
||||
case CMP_NODE_TEXTURE:
|
||||
ntype->draw_buttons = node_buts_texture;
|
||||
break;
|
||||
case CMP_NODE_HUECORRECT:
|
||||
ntype->draw_buttons = node_composit_buts_huecorrect;
|
||||
break;
|
||||
|
||||
@@ -10643,7 +10643,6 @@ static void rna_def_nodes(BlenderRNA *brna)
|
||||
define("CompositorNode", "CompositorNodeSunBeams");
|
||||
define("CompositorNode", "CompositorNodeSwitch");
|
||||
define("CompositorNode", "CompositorNodeSwitchView");
|
||||
define("CompositorNode", "CompositorNodeTexture", def_texture);
|
||||
define("CompositorNode", "CompositorNodeTime", def_time);
|
||||
define("CompositorNode", "CompositorNodeTonemap", def_cmp_tonemap);
|
||||
define("CompositorNode", "CompositorNodeTrackPos", def_cmp_trackpos);
|
||||
|
||||
@@ -96,7 +96,6 @@ set(SRC
|
||||
nodes/node_composite_sunbeams.cc
|
||||
nodes/node_composite_switch.cc
|
||||
nodes/node_composite_switchview.cc
|
||||
nodes/node_composite_texture.cc
|
||||
nodes/node_composite_tonemap.cc
|
||||
nodes/node_composite_trackpos.cc
|
||||
nodes/node_composite_transform.cc
|
||||
|
||||
@@ -210,9 +210,6 @@ void ntreeCompositTagRender(Scene *scene)
|
||||
if (node->id == (ID *)scene || node->type_legacy == CMP_NODE_COMPOSITE) {
|
||||
BKE_ntree_update_tag_node_property(sce_iter->compositing_node_group, node);
|
||||
}
|
||||
else if (node->type_legacy == CMP_NODE_TEXTURE) /* uses scene size_x/size_y */ {
|
||||
BKE_ntree_update_tag_node_property(sce_iter->compositing_node_group, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2006 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup cmpnodes
|
||||
*/
|
||||
|
||||
#include "COM_cached_texture.hh"
|
||||
#include "COM_node_operation.hh"
|
||||
|
||||
#include "node_composite_util.hh"
|
||||
|
||||
/* **************** TEXTURE ******************** */
|
||||
|
||||
namespace blender::nodes::node_composite_texture_cc {
|
||||
|
||||
static void cmp_node_texture_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Vector>("Offset")
|
||||
.min(-2.0f)
|
||||
.max(2.0f)
|
||||
.subtype(PROP_TRANSLATION)
|
||||
.compositor_expects_single_value();
|
||||
b.add_input<decl::Vector>("Scale")
|
||||
.default_value({1.0f, 1.0f, 1.0f})
|
||||
.min(-10.0f)
|
||||
.max(10.0f)
|
||||
.subtype(PROP_XYZ)
|
||||
.compositor_expects_single_value();
|
||||
b.add_output<decl::Float>("Value");
|
||||
b.add_output<decl::Color>("Color");
|
||||
}
|
||||
|
||||
using namespace blender::compositor;
|
||||
|
||||
class TextureOperation : public NodeOperation {
|
||||
public:
|
||||
using NodeOperation::NodeOperation;
|
||||
|
||||
void execute() override
|
||||
{
|
||||
Tex *texture = get_texture();
|
||||
if (!texture || !context().is_valid_compositing_region()) {
|
||||
execute_invalid();
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture->use_nodes) {
|
||||
execute_invalid();
|
||||
context().set_info_message("Viewport compositor setup not fully supported");
|
||||
return;
|
||||
}
|
||||
|
||||
const Domain domain = compute_domain();
|
||||
CachedTexture &cached_texture = context().cache_manager().cached_textures.get(
|
||||
context(),
|
||||
texture,
|
||||
true,
|
||||
domain.size,
|
||||
get_input("Offset").get_single_value_default(float3(0.0f)),
|
||||
get_input("Scale").get_single_value_default(float3(1.0f)));
|
||||
|
||||
Result &color_result = get_result("Color");
|
||||
if (color_result.should_compute()) {
|
||||
color_result.wrap_external(cached_texture.color_result);
|
||||
}
|
||||
|
||||
Result &value_result = get_result("Value");
|
||||
if (value_result.should_compute()) {
|
||||
value_result.wrap_external(cached_texture.value_result);
|
||||
}
|
||||
}
|
||||
|
||||
void execute_invalid()
|
||||
{
|
||||
Result &color_result = get_result("Color");
|
||||
if (color_result.should_compute()) {
|
||||
color_result.allocate_invalid();
|
||||
}
|
||||
|
||||
Result &value_result = get_result("Value");
|
||||
if (value_result.should_compute()) {
|
||||
value_result.allocate_invalid();
|
||||
}
|
||||
}
|
||||
|
||||
Domain compute_domain() override
|
||||
{
|
||||
return Domain(context().get_compositing_region_size());
|
||||
}
|
||||
|
||||
Tex *get_texture()
|
||||
{
|
||||
return reinterpret_cast<Tex *>(bnode().id);
|
||||
}
|
||||
};
|
||||
|
||||
static NodeOperation *get_compositor_operation(Context &context, DNode node)
|
||||
{
|
||||
return new TextureOperation(context, node);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_composite_texture_cc
|
||||
|
||||
static void register_node_type_cmp_texture()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_composite_texture_cc;
|
||||
|
||||
static blender::bke::bNodeType ntype;
|
||||
|
||||
cmp_node_type_base(&ntype, "CompositorNodeTexture", CMP_NODE_TEXTURE);
|
||||
ntype.ui_name = "Texture";
|
||||
ntype.ui_description = "Generate texture pattern from texture datablock";
|
||||
ntype.enum_name_legacy = "TEXTURE";
|
||||
ntype.nclass = NODE_CLASS_INPUT;
|
||||
ntype.declare = file_ns::cmp_node_texture_declare;
|
||||
ntype.compositor_unsupported_message = N_(
|
||||
"Texture nodes not supported in the Viewport compositor");
|
||||
ntype.flag |= NODE_PREVIEW;
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
|
||||
blender::bke::node_register_type(ntype);
|
||||
}
|
||||
NOD_REGISTER_NODE(register_node_type_cmp_texture)
|
||||
BIN
tests/files/compositor/anisotropic_filtering/compositor-nodes-desintegrate-wipe-01.blend
(Stored with Git LFS)
BIN
tests/files/compositor/anisotropic_filtering/compositor-nodes-desintegrate-wipe-01.blend
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/compositor/input/compositor_renders/node_texture_color.png
(Stored with Git LFS)
BIN
tests/files/compositor/input/compositor_renders/node_texture_color.png
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/compositor/input/compositor_renders/node_texture_value.png
(Stored with Git LFS)
BIN
tests/files/compositor/input/compositor_renders/node_texture_value.png
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/compositor/input/node_texture_color.blend
(Stored with Git LFS)
BIN
tests/files/compositor/input/node_texture_color.blend
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/compositor/input/node_texture_value.blend
(Stored with Git LFS)
BIN
tests/files/compositor/input/node_texture_value.blend
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/compositor/multiple_node_setups/Fire2.blend
(Stored with Git LFS)
BIN
tests/files/compositor/multiple_node_setups/Fire2.blend
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/compositor/multiple_node_setups/compositor_renders/Fire2.png
(Stored with Git LFS)
BIN
tests/files/compositor/multiple_node_setups/compositor_renders/Fire2.png
(Stored with Git LFS)
Binary file not shown.
Reference in New Issue
Block a user