29#define MINIMUM_DISTORTION -0.999f
31#define HORIZONTAL_DISPERSION_SCALE 5.0f
33#define RADIAL_DISPERSION_SCALE 4.0f
35#define DISTORTION_SCALE 4.0f
50 "The amount of distortion. 0 means no distortion, -1 means full Pincushion distortion, "
51 "and 1 means full Barrel distortion")
52 .compositor_expects_single_value();
58 .description(
"The amount of chromatic aberration to add to the distortion")
59 .compositor_expects_single_value();
63 "Introduces jitter while doing distortion, which can be faster but can produce grainy "
65 .compositor_expects_single_value();
69 "Scales the image such that it fits entirely in the frame, leaving no empty spaces at "
71 .compositor_expects_single_value();
90 node_storage(*node).distortion_type);
123 const float distance_squared)
126 1.0f - chromatic_distortion * distance_squared)));
143 const bool use_jitter)
146 return distortion < 4.0f ? 2 : int(
math::sqrt(distortion + 1.0f));
148 return int(distortion + 1.0f);
159 const float distance_squared,
160 const bool use_jitter)
171 float distortion_red =
math::distance(distorted_uv_red, distorted_uv_green);
176 float distortion_blue =
math::distance(distorted_uv_green, distorted_uv_blue);
181 return int3(steps_red, steps_red + steps_blue, steps_blue);
208 const float3 &chromatic_distortion,
211 const float distance_squared,
214 const bool use_jitter)
217 float distortion_amount = chromatic_distortion[end] - chromatic_distortion[start];
222 float distortion = chromatic_distortion[start] + increment * distortion_amount;
229 accumulated_color[start] += (1.0f - increment) *
color[start];
230 accumulated_color[end] += increment *
color[end];
232 return accumulated_color;
239 const float3 &chromatic_distortion,
241 const bool use_jitter)
247 float distance_squared =
math::dot(uv, uv);
251 float3 distortion_bounds = chromatic_distortion * distance_squared;
252 if (distortion_bounds.x > 1.0f || distortion_bounds.y > 1.0f || distortion_bounds.z > 1.0f) {
260 chromatic_distortion,
size, uv, distance_squared, use_jitter);
270 chromatic_distortion,
280 chromatic_distortion,
325 if (this->
context().use_gpu()) {
335 GPUShader *shader =
context().
get_shader(
"compositor_horizontal_lens_distortion");
367 output.allocate_texture(domain);
375 const float red =
input.sample_bilinear_zero(normalized_texel +
float2(dispersion, 0.0f)).x;
377 const float blue =
input.sample_bilinear_zero(normalized_texel -
float2(dispersion, 0.0f)).z;
379 output.store_pixel(texel,
float4(red, green, blue, 1.0f));
385 if (this->
context().use_gpu()) {
424 return "compositor_radial_lens_distortion_jitter";
426 return "compositor_radial_lens_distortion";
439 output.allocate_texture(domain);
456 return clamp_f(
input.get_single_value_default(0.0f), 0.0f, 1.0f);
479 const float maximum_distortion =
max_fff(distortion[0], distortion[1], distortion[2]);
481 if (
get_is_fit() && (maximum_distortion > 0.0f)) {
482 return 1.0f / (1.0f + 2.0f * maximum_distortion);
484 return 1.0f / (1.0f + maximum_distortion);
506 if (this->
get_input(
"Image").is_single_value()) {
541 ntype.
ui_name =
"Lens Distortion";
542 ntype.
ui_description =
"Simulate distortion and dispersion from camera lenses";
545 ntype.
declare = file_ns::cmp_node_lensdist_declare;
547 ntype.
draw_buttons = file_ns::node_composit_buts_lensdist;
548 ntype.
initfunc = file_ns::node_composit_init_lensdist;
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_DISTORT
#define CMP_NODE_LENSDIST
MINLINE float max_fff(float a, float b, float c)
MINLINE float clamp_f(float value, float min, float max)
CMPNodeLensDistortionType
@ CMP_NODE_LENS_DISTORTION_RADIAL
@ CMP_NODE_LENS_DISTORTION_HORIZONTAL
void GPU_shader_uniform_1f(GPUShader *sh, const char *name, float value)
void GPU_shader_bind(GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3])
void GPU_texture_extend_mode(GPUTexture *texture, GPUSamplerExtendMode extend_mode)
@ GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER
void GPU_texture_filter_mode(GPUTexture *texture, bool use_filter)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static unsigned long seed
GPUShader * get_shader(const char *info_name, ResultPrecision precision)
const bNode & bnode() const
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Context & context() const
Result & get_input(StringRef identifier) const
virtual Domain compute_domain()
void share_data(const Result &source)
T get_single_value_default(const T &default_value) const
void allocate_texture(Domain domain, bool from_pool=true)
void unbind_as_texture() const
void bind_as_texture(GPUShader *shader, const char *texture_name) const
void bind_as_image(GPUShader *shader, const char *image_name, bool read=false) const
void unbind_as_image() const
ColorGeometry4f default_value
void execute_horizontal_distortion()
CMPNodeLensDistortionType get_type()
float3 compute_chromatic_distortion()
void execute_horizontal_distortion_gpu()
void execute_radial_distortion_cpu()
void execute_radial_distortion_gpu()
NodeOperation(Context &context, DNode node)
void execute_horizontal_distortion_cpu()
const char * get_radial_distortion_shader()
void execute_radial_distortion()
void * MEM_callocN(size_t len, const char *str)
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
void node_register_type(bNodeType &ntype)
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
void parallel_for(const int2 range, const Function &function)
T distance(const T &a, const T &b)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T max(const T &a, const T &b)
static void node_composit_buts_lensdist(uiLayout *layout, bContext *, PointerRNA *ptr)
static void node_update(bNodeTree *ntree, bNode *node)
static int3 compute_number_of_integration_steps(const float3 &chromatic_distortion, const int2 &size, const float2 &uv, const float distance_squared, const bool use_jitter)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
static float2 compute_distorted_uv(const float2 &uv, const float uv_scale, const int2 &size)
static float3 integrate_distortion(const int2 &texel, const Result &input, const int2 &size, const float3 &chromatic_distortion, const int start, const int end, const float distance_squared, const float2 &uv, const int steps, const bool use_jitter)
static float get_jitter(const int2 &texel, const int seed, const bool use_jitter)
static int compute_number_of_integration_steps_heuristic(const float distortion, const bool use_jitter)
static void cmp_node_lensdist_declare(NodeDeclarationBuilder &b)
static float compute_distortion_scale(const float distortion, const float distance_squared)
static void node_composit_init_lensdist(bNodeTree *, bNode *node)
static float3 compute_chromatic_distortion_scale(const float3 &chromatic_distortion, const float distance_squared)
static void radial_lens_distortion(const int2 texel, const Result &input, Result &output, const int2 &size, const float3 &chromatic_distortion, const float scale, const bool use_jitter)
float hash_to_float(uint32_t kx)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
#define HORIZONTAL_DISPERSION_SCALE
#define MINIMUM_DISTORTION
#define RADIAL_DISPERSION_SCALE
static void register_node_type_cmp_lensdist()
void cmp_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
std::string ui_description
NodeGetCompositorOperationFunction get_compositor_operation
void(* initfunc)(bNodeTree *ntree, bNode *node)
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
void(* updatefunc)(bNodeTree *ntree, bNode *node)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)