Realtime Compositor: Implement Movie Distortion node #108230
|
@ -21,6 +21,7 @@ struct MovieClipUser;
|
|||
struct MovieDistortion;
|
||||
struct MovieReconstructContext;
|
||||
struct MovieTracking;
|
||||
struct MovieTrackingCamera;
|
||||
struct MovieTrackingMarker;
|
||||
struct MovieTrackingObject;
|
||||
struct MovieTrackingPlaneMarker;
|
||||
|
@ -464,6 +465,16 @@ void BKE_tracking_camera_principal_point_pixel_get(struct MovieClip *clip,
|
|||
void BKE_tracking_camera_principal_point_pixel_set(struct MovieClip *clip,
|
||||
const float principal_point_pixel[2]);
|
||||
|
||||
/* Compares distortion related parameters of camera. Ideally, this implementation will be
|
||||
* abstracted away in the future, but for now, one needs to be careful about it and handle any
|
||||
* extra parameters of distortions models. */
|
||||
bool BKE_tracking_camera_distortion_equal(const struct MovieTrackingCamera *a,
|
||||
const struct MovieTrackingCamera *b);
|
||||
/* Hashes distortion related paramaters of camera. Ideally, this implementation will be
|
||||
* abstracted away in the future, but for now, one needs to be careful about it and handle any
|
||||
* extra parameters of distortions models. */
|
||||
uint64_t BKE_tracking_camera_distortion_hash(const struct MovieTrackingCamera *camera);
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* (Un)distortion.
|
||||
*/
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
|
@ -23,9 +24,12 @@
|
|||
|
||||
#include "BLI_bitmap_draw_2d.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_hash.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_threads.h"
|
||||
|
@ -2197,6 +2201,66 @@ void BKE_tracking_camera_principal_point_pixel_set(MovieClip *clip,
|
|||
principal_point_pixel, frame_width, frame_height, camera->principal_point);
|
||||
}
|
||||
|
||||
bool BKE_tracking_camera_distortion_equal(const MovieTrackingCamera *a,
|
||||
const MovieTrackingCamera *b)
|
||||
OmarEmaraDev marked this conversation as resolved
Outdated
|
||||
{
|
||||
if (a->pixel_aspect != b->pixel_aspect || a->focal != b->focal ||
|
||||
!equals_v2v2(a->principal_point, b->principal_point))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a->distortion_model != b->distortion_model) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (a->distortion_model) {
|
||||
case TRACKING_DISTORTION_MODEL_POLYNOMIAL:
|
||||
return a->k1 == b->k1 && a->k2 == b->k2 && a->k3 == b->k3;
|
||||
case TRACKING_DISTORTION_MODEL_DIVISION:
|
||||
return a->division_k1 == b->division_k1 && a->division_k2 == b->division_k2;
|
||||
case TRACKING_DISTORTION_MODEL_NUKE:
|
||||
return a->nuke_k1 == b->nuke_k1 && a->nuke_k2 == b->nuke_k2;
|
||||
case TRACKING_DISTORTION_MODEL_BROWN:
|
||||
return a->brown_k1 == b->brown_k1 && a->brown_k2 == b->brown_k2 &&
|
||||
a->brown_k3 == b->brown_k3 && a->brown_k4 == b->brown_k4 &&
|
||||
a->brown_p1 == b->brown_p1 && a->brown_p2 == b->brown_p2;
|
||||
}
|
||||
OmarEmaraDev marked this conversation as resolved
Sergey Sharybin
commented
Please do not add In this example it is as easy as moving the Please do not add `default` unless absolutely needed, as it makes it very hard to see at compile time where enumerator value is forgotten to be checked when adding a new value.
In this example it is as easy as moving the `BLI_assert_unreachable` past the `switch` statement.
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t BKE_tracking_camera_distortion_hash(const MovieTrackingCamera *camera)
|
||||
{
|
||||
using namespace blender;
|
||||
switch (camera->distortion_model) {
|
||||
OmarEmaraDev marked this conversation as resolved
Sergey Sharybin
commented
Is it intended to skip Is it intended to skip `distortion_model`, `focal` and so on?
|
||||
case TRACKING_DISTORTION_MODEL_POLYNOMIAL:
|
||||
return get_default_hash_4(camera->distortion_model,
|
||||
float2(camera->pixel_aspect, camera->focal),
|
||||
float2(camera->principal_point),
|
||||
float3(camera->k1, camera->k2, camera->k3));
|
||||
case TRACKING_DISTORTION_MODEL_DIVISION:
|
||||
return get_default_hash_4(camera->distortion_model,
|
||||
float2(camera->pixel_aspect, camera->focal),
|
||||
float2(camera->principal_point),
|
||||
float2(camera->division_k1, camera->division_k2));
|
||||
case TRACKING_DISTORTION_MODEL_NUKE:
|
||||
return get_default_hash_4(camera->distortion_model,
|
||||
float2(camera->pixel_aspect, camera->focal),
|
||||
float2(camera->principal_point),
|
||||
float2(camera->nuke_k1, camera->nuke_k2));
|
||||
case TRACKING_DISTORTION_MODEL_BROWN:
|
||||
return get_default_hash_4(
|
||||
float2(camera->pixel_aspect, camera->focal),
|
||||
float2(camera->principal_point),
|
||||
OmarEmaraDev marked this conversation as resolved
Sergey Sharybin
commented
Same as above. Same as above.
|
||||
float4(camera->brown_k1, camera->brown_k2, camera->brown_k3, camera->brown_k4),
|
||||
float2(camera->brown_p1, camera->brown_p2));
|
||||
}
|
||||
|
||||
BLI_assert_unreachable();
|
||||
return 0;
|
||||
}
|
||||
/* --------------------------------------------------------------------
|
||||
* (Un)distortion.
|
||||
*/
|
||||
|
|
|
@ -17,6 +17,9 @@ set(INC
|
|||
../../render
|
||||
../../gpu/intern
|
||||
../../../../intern/guardedalloc
|
||||
|
||||
# dna_type_offsets.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../../makesdna/intern
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
@ -74,6 +77,7 @@ set(SRC
|
|||
|
||||
cached_resources/intern/cached_mask.cc
|
||||
cached_resources/intern/cached_texture.cc
|
||||
cached_resources/intern/distortion_grid.cc
|
||||
cached_resources/intern/morphological_distance_feather_weights.cc
|
||||
cached_resources/intern/ocio_color_space_conversion_shader.cc
|
||||
cached_resources/intern/smaa_precomputed_textures.cc
|
||||
|
@ -83,6 +87,7 @@ set(SRC
|
|||
cached_resources/COM_cached_mask.hh
|
||||
cached_resources/COM_cached_resource.hh
|
||||
cached_resources/COM_cached_texture.hh
|
||||
cached_resources/COM_distortion_grid.hh
|
||||
cached_resources/COM_morphological_distance_feather_weights.hh
|
||||
cached_resources/COM_ocio_color_space_conversion_shader.hh
|
||||
cached_resources/COM_smaa_precomputed_textures.hh
|
||||
|
@ -133,6 +138,7 @@ set(GLSL_SRC
|
|||
shaders/compositor_morphological_distance_feather.glsl
|
||||
shaders/compositor_morphological_distance_threshold.glsl
|
||||
shaders/compositor_morphological_step.glsl
|
||||
shaders/compositor_movie_distortion.glsl
|
||||
shaders/compositor_normalize.glsl
|
||||
shaders/compositor_parallel_reduction.glsl
|
||||
shaders/compositor_plane_deform.glsl
|
||||
|
@ -234,6 +240,7 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/compositor_morphological_distance_info.hh
|
||||
shaders/infos/compositor_morphological_distance_threshold_info.hh
|
||||
shaders/infos/compositor_morphological_step_info.hh
|
||||
shaders/infos/compositor_movie_distortion_info.hh
|
||||
shaders/infos/compositor_normalize_info.hh
|
||||
shaders/infos/compositor_parallel_reduction_info.hh
|
||||
shaders/infos/compositor_plane_deform_info.hh
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "COM_cached_mask.hh"
|
||||
#include "COM_cached_texture.hh"
|
||||
#include "COM_distortion_grid.hh"
|
||||
#include "COM_morphological_distance_feather_weights.hh"
|
||||
#include "COM_ocio_color_space_conversion_shader.hh"
|
||||
#include "COM_smaa_precomputed_textures.hh"
|
||||
|
@ -45,6 +46,7 @@ class StaticCacheManager {
|
|||
CachedMaskContainer cached_masks;
|
||||
SMAAPrecomputedTexturesContainer smaa_precomputed_textures;
|
||||
OCIOColorSpaceConversionShaderContainer ocio_color_space_conversion_shaders;
|
||||
DistortionGridContainer distortion_grids;
|
||||
|
||||
/* Reset the cache manager by deleting the cached resources that are no longer needed because
|
||||
* they weren't used in the last evaluation and prepare the remaining cached resources to track
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
OmarEmaraDev marked this conversation as resolved
Outdated
Sergey Sharybin
commented
Please add copyright to the new files. Please add copyright to the new files.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "DNA_movieclip_types.h"
|
||||
|
||||
#include "COM_cached_resource.hh"
|
||||
|
||||
namespace blender::realtime_compositor {
|
||||
|
||||
enum class DistortionType : uint8_t {
|
||||
Distort,
|
||||
Undistort,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Distortion Grid Key.
|
||||
*/
|
||||
class DistortionGridKey {
|
||||
public:
|
||||
MovieTrackingCamera camera;
|
||||
int2 size;
|
||||
DistortionType type;
|
||||
int2 calibration_size;
|
||||
|
||||
DistortionGridKey(MovieTrackingCamera camera,
|
||||
int2 size,
|
||||
DistortionType type,
|
||||
int2 calibration_size);
|
||||
|
||||
uint64_t hash() const;
|
||||
};
|
||||
|
||||
bool operator==(const DistortionGridKey &a, const DistortionGridKey &b);
|
||||
|
||||
/* -------------------------------------------------------------------------------------------------
|
||||
* Distortion Grid.
|
||||
*
|
||||
* A cached resource that computes and caches a GPU texture containing the normalized coordinates
|
||||
* after applying the camera distortion of a given movie clip tracking camera. See the constructor
|
||||
* for more information. */
|
||||
class DistortionGrid : public CachedResource {
|
||||
private:
|
||||
GPUTexture *texture_ = nullptr;
|
||||
|
||||
public:
|
||||
/* The calibration size is the size of the image where the tracking camera was calibrated, this
|
||||
* is the size of the movie clip in most cases. */
|
||||
DistortionGrid(MovieClip *movie_clip, int2 size, DistortionType type, int2 calibration_size);
|
||||
|
||||
~DistortionGrid();
|
||||
|
||||
void bind_as_texture(GPUShader *shader, const char *texture_name) const;
|
||||
|
||||
void unbind_as_texture() const;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Distortion Grid Container.
|
||||
*/
|
||||
class DistortionGridContainer : CachedResourceContainer {
|
||||
private:
|
||||
Map<DistortionGridKey, std::unique_ptr<DistortionGrid>> map_;
|
||||
|
||||
public:
|
||||
void reset() override;
|
||||
|
||||
/* Check if there is an available DistortionGrid 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. */
|
||||
DistortionGrid &get(MovieClip *movie_clip, int2 size, DistortionType type, int frame_number);
|
||||
};
|
||||
|
||||
} // namespace blender::realtime_compositor
|
|
@ -0,0 +1,160 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* 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_types.hh"
|
||||
#include "BLI_task.hh"
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_movieclip_types.h"
|
||||
#include "DNA_tracking_types.h"
|
||||
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "BKE_movieclip.h"
|
||||
#include "BKE_tracking.h"
|
||||
|
||||
#include "COM_distortion_grid.hh"
|
||||
|
||||
namespace blender::realtime_compositor {
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Distortion Grid Key.
|
||||
*/
|
||||
|
||||
DistortionGridKey::DistortionGridKey(MovieTrackingCamera camera,
|
||||
int2 size,
|
||||
DistortionType type,
|
||||
int2 calibration_size)
|
||||
: camera(camera), size(size), type(type), calibration_size(calibration_size)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t DistortionGridKey::hash() const
|
||||
{
|
||||
return get_default_hash_4(
|
||||
BKE_tracking_camera_distortion_hash(&camera), size, type, calibration_size);
|
||||
}
|
||||
|
||||
bool operator==(const DistortionGridKey &a, const DistortionGridKey &b)
|
||||
{
|
||||
return BKE_tracking_camera_distortion_equal(&a.camera, &b.camera) && a.size == b.size &&
|
||||
a.type == b.type && a.calibration_size == b.calibration_size;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Distortion Grid.
|
||||
*/
|
||||
|
||||
DistortionGrid::DistortionGrid(MovieClip *movie_clip,
|
||||
int2 size,
|
||||
DistortionType type,
|
||||
int2 calibration_size)
|
||||
{
|
||||
MovieDistortion *distortion = BKE_tracking_distortion_new(
|
||||
&movie_clip->tracking, calibration_size.x, calibration_size.y);
|
||||
|
||||
Array<float2> distortion_grid(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)) {
|
||||
/* The tracking distortion functions expect the coordinates to be in the space of the image
|
||||
* where the tracking camera was calibrated. So we first remap the coordinates into that
|
||||
* space, apply the distortion, then remap back to the original coordinates space. This is
|
||||
* done by dividing the by the size then multiplying by the calibration size, making sure
|
||||
* to add 0.5 to evaluate at the center of pixels. */
|
||||
float2 coordinates = ((float2(x, y) + 0.5f) / float2(size)) * float2(calibration_size);
|
||||
|
||||
if (type == DistortionType::Undistort) {
|
||||
BKE_tracking_distortion_undistort_v2(distortion, coordinates, coordinates);
|
||||
}
|
||||
else {
|
||||
BKE_tracking_distortion_distort_v2(distortion, coordinates, coordinates);
|
||||
}
|
||||
|
||||
/* Note that we should remap the coordinates back into the original size by dividing by the
|
||||
* calibration size and multiplying by the size, however, we skip the latter to store the
|
||||
* coordinates in normalized form, since this is what the shader expects. */
|
||||
distortion_grid[y * size.x + x] = coordinates / float2(calibration_size);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BKE_tracking_distortion_free(distortion);
|
||||
|
||||
texture_ = GPU_texture_create_2d("Distortion Grid",
|
||||
size.x,
|
||||
size.y,
|
||||
1,
|
||||
GPU_RG16F,
|
||||
GPU_TEXTURE_USAGE_SHADER_READ,
|
||||
*distortion_grid.data());
|
||||
}
|
||||
|
||||
DistortionGrid::~DistortionGrid()
|
||||
{
|
||||
GPU_texture_free(texture_);
|
||||
}
|
||||
|
||||
void DistortionGrid::bind_as_texture(GPUShader *shader, const char *texture_name) const
|
||||
{
|
||||
const int texture_image_unit = GPU_shader_get_sampler_binding(shader, texture_name);
|
||||
GPU_texture_bind(texture_, texture_image_unit);
|
||||
}
|
||||
|
||||
void DistortionGrid::unbind_as_texture() const
|
||||
{
|
||||
GPU_texture_unbind(texture_);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Distortion Grid Container.
|
||||
*/
|
||||
|
||||
void DistortionGridContainer::reset()
|
||||
{
|
||||
/* First, delete all resources that are no longer needed. */
|
||||
map_.remove_if([](auto item) { return !item.value->needed; });
|
||||
|
||||
/* Second, reset the needed status of the remaining resources to false to ready them to track
|
||||
* their needed status for the next evaluation. */
|
||||
for (auto &value : map_.values()) {
|
||||
value->needed = false;
|
||||
}
|
||||
}
|
||||
|
||||
static int2 get_movie_clip_size(MovieClip *movie_clip, int frame_number)
|
||||
{
|
||||
MovieClipUser user = *DNA_struct_default_get(MovieClipUser);
|
||||
BKE_movieclip_user_set_frame(&user, frame_number);
|
||||
|
||||
int2 size;
|
||||
BKE_movieclip_get_size(movie_clip, &user, &size.x, &size.y);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
DistortionGrid &DistortionGridContainer::get(MovieClip *movie_clip,
|
||||
int2 size,
|
||||
DistortionType type,
|
||||
int frame_number)
|
||||
{
|
||||
const int2 calibration_size = get_movie_clip_size(movie_clip, frame_number);
|
||||
|
||||
const DistortionGridKey key(movie_clip->tracking.camera, size, type, calibration_size);
|
||||
|
||||
auto &distortion_grid = *map_.lookup_or_add_cb(key, [&]() {
|
||||
return std::make_unique<DistortionGrid>(movie_clip, size, type, calibration_size);
|
||||
});
|
||||
|
||||
distortion_grid.needed = true;
|
||||
return distortion_grid;
|
||||
}
|
||||
|
||||
} // namespace blender::realtime_compositor
|
|
@ -0,0 +1,7 @@
|
|||
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
imageStore(output_img, texel, texture(input_tx, texture_load(distortion_grid_tx, texel).xy));
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(compositor_movie_distortion)
|
||||
.local_group_size(16, 16)
|
||||
.sampler(0, ImageType::FLOAT_2D, "input_tx")
|
||||
.sampler(1, ImageType::FLOAT_2D, "distortion_grid_tx")
|
||||
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
|
||||
.compute_source("compositor_movie_distortion.glsl")
|
||||
.do_static_compilation(true);
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "BLI_string_utf8.h"
|
||||
|
||||
#include "DNA_movieclip_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_tracking.h"
|
||||
|
@ -15,7 +17,12 @@
|
|||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
#include "COM_distortion_grid.hh"
|
||||
#include "COM_node_operation.hh"
|
||||
#include "COM_utilities.hh"
|
||||
|
||||
#include "node_composite_util.hh"
|
||||
|
||||
|
@ -25,7 +32,9 @@ namespace blender::nodes::node_composite_moviedistortion_cc {
|
|||
|
||||
static void cmp_node_moviedistortion_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Color>("Image").default_value({0.8f, 0.8f, 0.8f, 1.0f});
|
||||
b.add_input<decl::Color>("Image")
|
||||
.default_value({0.8f, 0.8f, 0.8f, 1.0f})
|
||||
.compositor_domain_priority(0);
|
||||
b.add_output<decl::Color>("Image");
|
||||
}
|
||||
|
||||
|
@ -94,8 +103,45 @@ class MovieDistortionOperation : public NodeOperation {
|
|||
|
||||
void execute() override
|
||||
{
|
||||
get_input("Image").pass_through(get_result("Image"));
|
||||
context().set_info_message("Viewport compositor setup not fully supported");
|
||||
Result &input_image = get_input("Image");
|
||||
Result &output_image = get_result("Image");
|
||||
if (input_image.is_single_value() || !get_movie_clip()) {
|
||||
input_image.pass_through(output_image);
|
||||
return;
|
||||
}
|
||||
|
||||
const Domain domain = compute_domain();
|
||||
const DistortionGrid &distortion_grid = context().cache_manager().distortion_grids.get(
|
||||
get_movie_clip(), domain.size, get_distortion_type(), context().get_frame_number());
|
||||
|
||||
GPUShader *shader = shader_manager().get("compositor_movie_distortion");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
GPU_texture_extend_mode(input_image.texture(), GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
|
||||
GPU_texture_filter_mode(input_image.texture(), true);
|
||||
input_image.bind_as_texture(shader, "input_tx");
|
||||
|
||||
distortion_grid.bind_as_texture(shader, "distortion_grid_tx");
|
||||
|
||||
output_image.allocate_texture(domain);
|
||||
output_image.bind_as_image(shader, "output_img");
|
||||
|
||||
compute_dispatch_threads_at_least(shader, domain.size);
|
||||
|
||||
input_image.unbind_as_texture();
|
||||
distortion_grid.unbind_as_texture();
|
||||
output_image.unbind_as_image();
|
||||
GPU_shader_unbind();
|
||||
}
|
||||
|
||||
DistortionType get_distortion_type()
|
||||
{
|
||||
return bnode().custom1 == 0 ? DistortionType::Distort : DistortionType::Undistort;
|
||||
}
|
||||
|
||||
MovieClip *get_movie_clip()
|
||||
{
|
||||
return reinterpret_cast<MovieClip *>(bnode().id);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -119,8 +165,6 @@ void register_node_type_cmp_moviedistortion()
|
|||
ntype.initfunc_api = file_ns::init;
|
||||
node_type_storage(&ntype, nullptr, file_ns::storage_free, file_ns::storage_copy);
|
||||
ntype.get_compositor_operation = file_ns::get_compositor_operation;
|
||||
ntype.realtime_compositor_unsupported_message = N_(
|
||||
"Node not supported in the Viewport compositor");
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
This is a bit confusing. Camera also defines sensor width, which is not compared here.