diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-01-04 03:58:34 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-01-05 16:17:57 +0300 |
commit | 4c3f52e7dc868471393cab76619b1187a654bc43 (patch) | |
tree | c387d9db194a4632f0c5b23b9029f27c749a9ab2 /intern | |
parent | b1bd0f8ffdaf5e5df3038ae688a7b4eb8d10ba6d (diff) |
Cycles: support rendering PointCloud motion blur from attribute
This adds support to render PointCloud motion blur from a standard
"velocity" attribute.
This implementation is similar to that of the Mesh geometry, and
perhaps some code could be deduplicated through a more generic API.
`mesh_need_motion_attribute` was renamed `object_need_motion_attribute`
as it does not really require a mesh and moved to `util.h` so that
it can be shared.
This fixes T94622.
Reviewed By: brecht
Maniphest Tasks: T94622
Differential Revision: https://developer.blender.org/D13719
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/mesh.cpp | 36 | ||||
-rw-r--r-- | intern/cycles/blender/pointcloud.cpp | 60 | ||||
-rw-r--r-- | intern/cycles/blender/util.h | 35 |
3 files changed, 91 insertions, 40 deletions
diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index bb17cfdcb45..5e2b700427a 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -1086,40 +1086,6 @@ static void create_subd_mesh(Scene *scene, /* Sync */ -/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes - * things like velocity from cache modifier, fluid simulation). - * - * NOTE: This code is run prior to object motion blur initialization. so can not access properties - * set by `sync_object_motion_init()`. */ -static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene) -{ - const Scene::MotionType need_motion = scene->need_motion(); - if (need_motion == Scene::MOTION_NONE) { - /* Simple case: neither motion pass nor motion blur is needed, no need in the motion related - * attributes. */ - return false; - } - - if (need_motion == Scene::MOTION_BLUR) { - /* A bit tricky and implicit case: - * - Motion blur is enabled in the scene, which implies specific number of time steps for - * objects. - * - If the object has motion blur disabled on it, it will have 0 time steps. - * - Motion attribute expects non-zero time steps. - * - * Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */ - PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles"); - const bool use_motion = get_boolean(cobject, "use_motion_blur"); - if (!use_motion) { - return false; - } - } - - /* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object - * level. */ - return true; -} - void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh) { /* make a copy of the shaders as the caller in the main thread still need them for syncing the @@ -1144,7 +1110,7 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M if (b_mesh) { /* Motion blur attribute is relative to seconds, we need it relative to frames. */ - const bool need_motion = mesh_need_motion_attribute(b_ob_info, scene); + const bool need_motion = object_need_motion_attribute(b_ob_info, scene); const float motion_scale = (need_motion) ? scene->motion_shutter_time() / (b_scene.render().fps() / b_scene.render().fps_base()) : diff --git a/intern/cycles/blender/pointcloud.cpp b/intern/cycles/blender/pointcloud.cpp index a9e616a468f..a69c4f6eca3 100644 --- a/intern/cycles/blender/pointcloud.cpp +++ b/intern/cycles/blender/pointcloud.cpp @@ -37,12 +37,52 @@ static void fill_generic_attribute(BL::PointCloud &b_pointcloud, } } -static void copy_attributes(PointCloud *pointcloud, BL::PointCloud b_pointcloud) +static void attr_create_motion(PointCloud *pointcloud, + BL::Attribute &b_attribute, + const float motion_scale) +{ + if (!(b_attribute.domain() == BL::Attribute::domain_POINT) && + (b_attribute.data_type() == BL::Attribute::data_type_FLOAT_VECTOR)) { + return; + } + + BL::FloatVectorAttribute b_vector_attribute(b_attribute); + const int num_points = pointcloud->get_points().size(); + + /* Find or add attribute */ + float3 *P = &pointcloud->get_points()[0]; + Attribute *attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + + if (!attr_mP) { + attr_mP = pointcloud->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); + } + + /* Only export previous and next frame, we don't have any in between data. */ + float motion_times[2] = {-1.0f, 1.0f}; + for (int step = 0; step < 2; step++) { + const float relative_time = motion_times[step] * 0.5f * motion_scale; + float3 *mP = attr_mP->data_float3() + step * num_points; + + for (int i = 0; i < num_points; i++) { + mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time; + } + } +} + +static void copy_attributes(PointCloud *pointcloud, + BL::PointCloud b_pointcloud, + const bool need_motion, + const float motion_scale) { AttributeSet &attributes = pointcloud->attributes; + static const ustring u_velocity("velocity"); for (BL::Attribute &b_attribute : b_pointcloud.attributes) { const ustring name{b_attribute.name().c_str()}; + if (need_motion && name == u_velocity) { + attr_create_motion(pointcloud, b_attribute, motion_scale); + } + if (attributes.find(name)) { continue; } @@ -111,7 +151,11 @@ static void copy_attributes(PointCloud *pointcloud, BL::PointCloud b_pointcloud) } } -static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointCloud b_pointcloud) +static void export_pointcloud(Scene *scene, + PointCloud *pointcloud, + BL::PointCloud b_pointcloud, + const bool need_motion, + const float motion_scale) { /* TODO: optimize so we can straight memcpy arrays from Blender? */ @@ -141,7 +185,7 @@ static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointClo } /* Export attributes */ - copy_attributes(pointcloud, b_pointcloud); + copy_attributes(pointcloud, b_pointcloud, need_motion, motion_scale); } static void export_pointcloud_motion(PointCloud *pointcloud, @@ -193,7 +237,7 @@ static void export_pointcloud_motion(PointCloud *pointcloud, } /* Export attributes */ - copy_attributes(pointcloud, b_pointcloud); + copy_attributes(pointcloud, b_pointcloud, false, 0.0f); } void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info) @@ -207,7 +251,13 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info /* TODO: add option to filter out points in the view layer. */ BL::PointCloud b_pointcloud(b_ob_info.object_data); - export_pointcloud(scene, &new_pointcloud, b_pointcloud); + /* Motion blur attribute is relative to seconds, we need it relative to frames. */ + const bool need_motion = object_need_motion_attribute(b_ob_info, scene); + const float motion_scale = (need_motion) ? + scene->motion_shutter_time() / + (b_scene.render().fps() / b_scene.render().fps_base()) : + 0.0f; + export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale); /* update original sockets */ for (const SocketType &socket : new_pointcloud.type->inputs) { diff --git a/intern/cycles/blender/util.h b/intern/cycles/blender/util.h index 6c396d39614..ae9cdfd4f58 100644 --- a/intern/cycles/blender/util.h +++ b/intern/cycles/blender/util.h @@ -18,6 +18,7 @@ #define __BLENDER_UTIL_H__ #include "scene/mesh.h" +#include "scene/scene.h" #include "util/algorithm.h" #include "util/array.h" @@ -670,6 +671,40 @@ static inline uint object_ray_visibility(BL::Object &b_ob) return flag; } +/* Check whether some of "built-in" motion-related attributes are needed to be exported (includes + * things like velocity from cache modifier, fluid simulation). + * + * NOTE: This code is run prior to object motion blur initialization. so can not access properties + * set by `sync_object_motion_init()`. */ +static bool object_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene) +{ + const Scene::MotionType need_motion = scene->need_motion(); + if (need_motion == Scene::MOTION_NONE) { + /* Simple case: neither motion pass nor motion blur is needed, no need in the motion related + * attributes. */ + return false; + } + + if (need_motion == Scene::MOTION_BLUR) { + /* A bit tricky and implicit case: + * - Motion blur is enabled in the scene, which implies specific number of time steps for + * objects. + * - If the object has motion blur disabled on it, it will have 0 time steps. + * - Motion attribute expects non-zero time steps. + * + * Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */ + PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles"); + const bool use_motion = get_boolean(cobject, "use_motion_blur"); + if (!use_motion) { + return false; + } + } + + /* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object + * level. */ + return true; +} + class EdgeMap { public: EdgeMap() |