40 .compositor_domain_priority(0);
66 col->label(
IFACE_(
"Bokeh Type:"), ICON_NONE);
80 sub = &
col->column(
false);
106 const bool is_circle = node_storage(
bnode()).bktype == 0;
107 const int2 kernel_size =
int2(maximum_defocus_radius * 2 + 1);
108 const int sides = is_circle ? 3 : node_storage(
bnode()).bktype;
109 const float rotation = node_storage(
bnode()).rotation;
110 const float roundness = is_circle ? 1.0f : 0.0f;
112 context(), kernel_size, sides, rotation, roundness, 0.0f, 0.0f);
114 if (this->
context().use_gpu()) {
126 const Result &bokeh_kernel,
128 const int search_radius)
135 input.bind_as_texture(shader,
"input_tx");
143 output.allocate_texture(domain);
144 output.bind_as_image(shader,
"output_img");
149 input.unbind_as_texture();
157 const Result &bokeh_kernel,
159 const int search_radius)
162 output.allocate_texture(domain);
176 auto load_weight = [&](
const int2 texel,
const float radius) {
183 1.0f - ((
float2(texel) +
float2(radius + 0.5f)) / (radius * 2.0f + 1.0f)));
187 float center_radius = math::max(0.0f, radius.load_pixel<float, true>(texel));
193 float4 accumulated_color = float4(0.0);
194 float4 accumulated_weight = float4(0.0);
195 for (int y = -search_radius; y <= search_radius; y++) {
196 for (int x = -search_radius; x <= search_radius; x++) {
197 float candidate_radius = math::max(
198 0.0f, radius.load_pixel_extended<float, true>(texel + int2(x, y)));
203 float radius = math::min(center_radius, candidate_radius);
204 if (math::max(math::abs(x), math::abs(y)) > radius) {
208 float4 weight = load_weight(int2(x, y), radius);
209 float4 input_color = input.load_pixel_extended<float4>(texel + int2(x, y));
211 accumulated_color += input_color * weight;
212 accumulated_weight += weight;
218 output.store_pixel(texel, accumulated_color);
224 if (node_storage(
bnode()).no_zbuf) {
241 GPUShader *shader =
context().get_shader(
"compositor_defocus_radius_from_scale");
261 return output_radius;
266 const float scale = node_storage(
bnode()).scale;
267 const float max_radius = node_storage(
bnode()).maxblur;
273 auto compute_radius = [&](
const float depth) {
274 return math::clamp(depth * scale, 0.0f, max_radius);
280 return output_radius;
287 float depth = input_depth.load_pixel<float>(texel);
288 output_radius.store_pixel(texel, compute_radius(depth));
291 return output_radius;
306 return output_radius;
318 return eroded_radius;
323 GPUShader *shader =
context().get_shader(
"compositor_defocus_radius_from_depth");
351 const float max_radius = node_storage(this->
bnode()).maxblur;
362 auto compute_radius = [&](
const float depth) {
364 const float distance_to_image_of_object = (focal_length * depth) / (depth - focal_length);
369 float diameter =
math::abs((distance_to_image_of_object - distance_to_image_of_focus) *
370 (focal_length / (f_stop * distance_to_image_of_object)));
373 float radius = (diameter / 2.0f) * pixels_per_meter;
388 float depth = input_depth.load_pixel<float>(texel);
389 output_radius.store_pixel(texel, compute_radius(depth));
396 if (node_storage(
bnode()).no_zbuf) {
397 return node_storage(
bnode()).maxblur;
402 const float radius = (maximum_diameter / 2.0f) * pixels_per_meter;
420 return math::abs((distance_to_image_of_focus / (f_stop * focal_length)) -
421 (focal_length / f_stop));
433 return (focal_length * focus_distance) / (focus_distance - focal_length);
441 return camera ?
math::max(1e-6f, camera->
lens / 1000.0f) : 50.0f / 1000.0f;
449 if (!camera_object) {
464 return default_value;
480 return default_value;
496 return reinterpret_cast<Camera *
>(camera_object->
data);
525 ntype.
ui_description =
"Apply depth of field in 2D, using a Z depth map or mask";
528 ntype.
declare = file_ns::cmp_node_defocus_declare;
529 ntype.
draw_buttons = file_ns::node_composit_buts_defocus;
530 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_1i(GPUShader *sh, const char *name, int value)
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_texture_filter_mode(GPUTexture *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
void uiLayoutSetActive(uiLayout *layout, bool active)
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()
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 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 set_single_value(const T &value)
const Domain & domain() const
void bind_as_image(GPUShader *shader, const char *image_name, bool read=false) const
void unbind_as_image() const
void allocate_single_value()
float4 sample_bilinear_extended(const float2 &coordinates) const
bool is_single_value() const
const T & get_single_value() const
BokehKernelContainer bokeh_kernels
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 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 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 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 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)