41 .structure_type(StructureType::Dynamic);
43 StructureType::Dynamic);
65 col->label(
IFACE_(
"Bokeh Type:"), ICON_NONE);
79 sub = &
col->column(
false);
105 const bool is_circle = node_storage(
bnode()).bktype == 0;
106 const int2 kernel_size =
int2(maximum_defocus_radius * 2 + 1);
107 const int sides = is_circle ? 3 : node_storage(
bnode()).bktype;
108 const float rotation = node_storage(
bnode()).rotation;
109 const float roundness = is_circle ? 1.0f : 0.0f;
111 context(), kernel_size, sides, rotation, roundness, 0.0f, 0.0f);
113 if (this->
context().use_gpu()) {
125 const Result &bokeh_kernel,
127 const int search_radius)
134 input.bind_as_texture(shader,
"input_tx");
142 output.allocate_texture(domain);
143 output.bind_as_image(shader,
"output_img");
148 input.unbind_as_texture();
156 const Result &bokeh_kernel,
158 const int search_radius)
161 output.allocate_texture(domain);
175 auto load_weight = [&](
const int2 texel,
const float radius) {
182 1.0f - ((
float2(texel) +
float2(radius + 0.5f)) / (radius * 2.0f + 1.0f)));
186 float center_radius = math::max(0.0f, radius.load_pixel<float, true>(texel));
192 float4 accumulated_color = float4(0.0);
193 float4 accumulated_weight = float4(0.0);
194 for (int y = -search_radius; y <= search_radius; y++) {
195 for (int x = -search_radius; x <= search_radius; x++) {
196 float candidate_radius = math::max(
197 0.0f, radius.load_pixel_extended<float, true>(texel + int2(x, y)));
202 float radius = math::min(center_radius, candidate_radius);
203 if (math::max(math::abs(x), math::abs(y)) > radius) {
207 float4 weight = load_weight(int2(x, y), radius);
208 float4 input_color = input.load_pixel_extended<float4>(texel + int2(x, y));
210 accumulated_color += input_color * weight;
211 accumulated_weight += weight;
217 output.store_pixel(texel, accumulated_color);
223 if (node_storage(
bnode()).no_zbuf) {
260 return output_radius;
265 const float scale = node_storage(
bnode()).scale;
266 const float max_radius = node_storage(
bnode()).maxblur;
272 auto compute_radius = [&](
const float depth) {
273 return math::clamp(depth * scale, 0.0f, max_radius);
279 return output_radius;
286 float depth = input_depth.load_pixel<float>(texel);
287 output_radius.store_pixel(texel, compute_radius(depth));
290 return output_radius;
305 return output_radius;
317 return eroded_radius;
350 const float max_radius = node_storage(this->
bnode()).maxblur;
361 auto compute_radius = [&](
const float depth) {
363 const float distance_to_image_of_object = (focal_length * depth) / (depth - focal_length);
368 float diameter =
math::abs((distance_to_image_of_object - distance_to_image_of_focus) *
369 (focal_length / (f_stop * distance_to_image_of_object)));
372 float radius = (diameter / 2.0f) * pixels_per_meter;
387 float depth = input_depth.load_pixel<float>(texel);
388 output_radius.store_pixel(texel, compute_radius(depth));
395 if (node_storage(
bnode()).no_zbuf) {
396 return node_storage(
bnode()).maxblur;
401 const float radius = (maximum_diameter / 2.0f) * pixels_per_meter;
419 return math::abs((distance_to_image_of_focus / (f_stop * focal_length)) -
420 (focal_length / f_stop));
432 return (focal_length * focus_distance) / (focus_distance - focal_length);
440 return camera ?
math::max(1e-6f, camera->
lens / 1000.0f) : 50.0f / 1000.0f;
448 if (!camera_object) {
463 return default_value;
479 return default_value;
495 return reinterpret_cast<Camera *
>(camera_object->
data);
524 ntype.
ui_description =
"Apply depth of field in 2D, using a Z depth map or mask";
527 ntype.
declare = file_ns::cmp_node_defocus_declare;
528 ntype.
draw_buttons = file_ns::node_composit_buts_defocus;
529 ntype.
initfunc = file_ns::node_composit_init_defocus;
Camera data-block and utility functions.
float BKE_camera_object_dof_distance(const struct Object *ob)
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_OP_FILTER
#define DEFAULT_SENSOR_WIDTH
Object is a sort of wrapper for general info.
void GPU_shader_uniform_1f(blender::gpu::Shader *sh, const char *name, float value)
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_1i(blender::gpu::Shader *sh, const char *name, int value)
void GPU_texture_filter_mode(blender::gpu::Texture *texture, bool use_filter)
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, blender::StringRefNull propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, std::optional< blender::StringRef > text=std::nullopt)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Result & get(Context &context, int2 size, int sides, float rotation, float roundness, float catadioptric, float lens_shift)
StaticCacheManager & cache_manager()
gpu::Shader * 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 allocate_texture(const Domain domain, const bool from_pool=true, const std::optional< ResultStorageType > storage_type=std::nullopt)
void unbind_as_texture() const
void set_single_value(const T &value)
void bind_as_texture(gpu::Shader *shader, const char *texture_name) const
const Domain & domain() const
void unbind_as_image() const
void allocate_single_value()
float4 sample_bilinear_extended(const float2 &coordinates) const
void bind_as_image(gpu::Shader *shader, const char *image_name, bool read=false) const
bool is_single_value() const
const T & get_single_value() const
BokehKernelContainer bokeh_kernels
StructureType structure_type
ColorGeometry4f default_value
float compute_maximum_defocus_radius()
Result compute_defocus_radius_from_scale_cpu()
float compute_distance_to_image_of_focus()
void compute_defocus_radius_from_depth_cpu(Result &output_radius)
const Scene * get_scene()
float compute_focus_distance()
float compute_pixels_per_meter()
void execute_gpu(const Result &input, const Result &radius, const Result &bokeh_kernel, Result &output, const int search_radius)
float compute_maximum_diameter_of_circle_of_confusion()
void execute_cpu(const Result &input, const Result &radius, const Result &bokeh_kernel, Result &output, const int search_radius)
const Camera * get_camera()
const Object * get_camera_object()
Result compute_defocus_radius_from_scale_gpu()
Result compute_defocus_radius()
Result compute_defocus_radius_from_depth()
void compute_defocus_radius_from_depth_gpu(Result &output_radius)
Result compute_defocus_radius_from_scale()
NodeOperation(Context &context, DNode node)
void * MEM_callocN(size_t len, const char *str)
void node_register_type(bNodeType &ntype)
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(gpu::Shader *shader, int2 threads_range, int2 local_size=int2(16))
void morphological_blur(Context &context, const Result &input, Result &output, const float2 &radius, const MorphologicalBlurOperation operation=MorphologicalBlurOperation::Erode, const int filter_type=R_FILTER_GAUSS)
void parallel_for(const int2 range, const Function &function)
T clamp(const T &a, const T &min, const T &max)
T safe_divide(const T &a, const T &b)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA *ptr)
static void cmp_node_defocus_declare(NodeDeclarationBuilder &b)
static void node_composit_init_defocus(bNodeTree *, bNode *node)
static NodeOperation * get_compositor_operation(Context &context, DNode node)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
static void register_node_type_cmp_defocus()
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)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
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
uiLayout & column(bool align)
void active_set(bool active)
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)
static pxr::UsdShadeInput get_input(const pxr::UsdShadeShader &usd_shader, const pxr::TfToken &input_name)