diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-04-19 17:28:14 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-04-19 18:07:53 +0300 |
commit | 2890c11cd7b008c3c261b6aa833c826c85cac504 (patch) | |
tree | 5bc3432767fc6dd260e6fec18bd1817766572abd /intern/cycles/blender | |
parent | 56cfd60d432bf387c21bf5bde08fece044fac99c (diff) |
Cycles: add support for volume motion blur
This adds support for rendering motion blur for volumes, using their
velocity field. This works for fluid simulations and imported VDB
volumes. For the latter, the name of the velocity field can be set per
volume object, with automatic detection of velocity fields that are
split into 3 scalar grids.
A new parameter is also added to scale velocity for more artistic control.
Like for Alembic and USD caches, a parameter to set the unit of time in
which the velocity vectors are expressed is also added. For Blender gas
simulations, the velocity unit should always be in seconds, so this is
only exposed for volume objects which may come from external OpenVDB
files.
These parameters are available under the `Render` panels for the fluid
domain and the volume object data properties respectively.
Credits: kernel advection code from Tangent Animation's Blackbird based
on earlier work by Geraldine Chua
Differential Revision: https://developer.blender.org/D14629
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 2 | ||||
-rw-r--r-- | intern/cycles/blender/camera.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/blender/object.cpp | 7 | ||||
-rw-r--r-- | intern/cycles/blender/sync.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/blender/volume.cpp | 49 |
5 files changed, 55 insertions, 15 deletions
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 739a555f037..8a7b0635ed7 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1034,7 +1034,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel): def poll(cls, context): ob = context.object if CyclesButtonsPanel.poll(context) and ob: - if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'CURVES', 'POINTCLOUD'}: + if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'CURVES', 'POINTCLOUD', 'VOLUME'}: return True if ob.instance_type == 'COLLECTION' and ob.instance_collection: return True diff --git a/intern/cycles/blender/camera.cpp b/intern/cycles/blender/camera.cpp index cdd19341534..402fd7c4ec6 100644 --- a/intern/cycles/blender/camera.cpp +++ b/intern/cycles/blender/camera.cpp @@ -23,7 +23,7 @@ struct BlenderCamera { float lens; float shuttertime; - Camera::MotionPosition motion_position; + MotionPosition motion_position; array<float> shutter_curve; Camera::RollingShutterType rolling_shutter_type; @@ -114,7 +114,7 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings &b_rende bcam->sensor_width = 36.0f; bcam->sensor_height = 24.0f; bcam->sensor_fit = BlenderCamera::AUTO; - bcam->motion_position = Camera::MOTION_POSITION_CENTER; + bcam->motion_position = MOTION_POSITION_CENTER; bcam->border.right = 1.0f; bcam->border.top = 1.0f; bcam->viewport_camera_border.right = 1.0f; @@ -555,10 +555,8 @@ void BlenderSync::sync_camera(BL::RenderSettings &b_render, curvemapping_to_array(b_shutter_curve, bcam.shutter_curve, RAMP_TABLE_SIZE); PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - bcam.motion_position = (Camera::MotionPosition)get_enum(cscene, - "motion_blur_position", - Camera::MOTION_NUM_POSITIONS, - Camera::MOTION_POSITION_CENTER); + bcam.motion_position = (MotionPosition)get_enum( + cscene, "motion_blur_position", MOTION_NUM_POSITIONS, MOTION_POSITION_CENTER); bcam.rolling_shutter_type = (Camera::RollingShutterType)get_enum( cscene, "rolling_shutter_type", diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp index f77cbdf847d..9b08b564b25 100644 --- a/intern/cycles/blender/object.cpp +++ b/intern/cycles/blender/object.cpp @@ -16,6 +16,7 @@ #include "scene/shader.h" #include "scene/shader_graph.h" #include "scene/shader_nodes.h" +#include "scene/volume.h" #include "util/foreach.h" #include "util/hash.h" @@ -715,13 +716,13 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render, float frame_center_delta = 0.0f; if (scene->need_motion() != Scene::MOTION_PASS && - scene->camera->get_motion_position() != Camera::MOTION_POSITION_CENTER) { + scene->camera->get_motion_position() != MOTION_POSITION_CENTER) { float shuttertime = scene->camera->get_shuttertime(); - if (scene->camera->get_motion_position() == Camera::MOTION_POSITION_END) { + if (scene->camera->get_motion_position() == MOTION_POSITION_END) { frame_center_delta = -shuttertime * 0.5f; } else { - assert(scene->camera->get_motion_position() == Camera::MOTION_POSITION_START); + assert(scene->camera->get_motion_position() == MOTION_POSITION_START); frame_center_delta = shuttertime * 0.5f; } diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index bd6bfafedeb..1028c940772 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -272,7 +272,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render, geometry_synced.clear(); /* use for objects and motion sync */ if (scene->need_motion() == Scene::MOTION_PASS || scene->need_motion() == Scene::MOTION_NONE || - scene->camera->get_motion_position() == Camera::MOTION_POSITION_CENTER) { + scene->camera->get_motion_position() == MOTION_POSITION_CENTER) { sync_objects(b_depsgraph, b_v3d); } sync_motion(b_render, b_depsgraph, b_v3d, b_override, width, height, python_thread_state); diff --git a/intern/cycles/blender/volume.cpp b/intern/cycles/blender/volume.cpp index 381b3385a5a..8dd2d45c0b6 100644 --- a/intern/cycles/blender/volume.cpp +++ b/intern/cycles/blender/volume.cpp @@ -168,7 +168,8 @@ class BlenderSmokeLoader : public ImageLoader { AttributeStandard attribute; }; -static void sync_smoke_volume(Scene *scene, BObjectInfo &b_ob_info, Volume *volume, float frame) +static void sync_smoke_volume( + BL::Scene &b_scene, Scene *scene, BObjectInfo &b_ob_info, Volume *volume, float frame) { if (!b_ob_info.is_real_object_data()) { return; @@ -178,6 +179,18 @@ static void sync_smoke_volume(Scene *scene, BObjectInfo &b_ob_info, Volume *volu return; } + float velocity_scale = b_domain.velocity_scale(); + /* 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; + + velocity_scale *= motion_scale; + + volume->set_velocity_scale(velocity_scale); + AttributeStandard attributes[] = {ATTR_STD_VOLUME_DENSITY, ATTR_STD_VOLUME_COLOR, ATTR_STD_VOLUME_FLAME, @@ -234,6 +247,7 @@ class BlenderVolumeLoader : public VDBImageLoader { }; static void sync_volume_object(BL::BlendData &b_data, + BL::Scene &b_scene, BObjectInfo &b_ob_info, Scene *scene, Volume *volume) @@ -247,6 +261,20 @@ static void sync_volume_object(BL::BlendData &b_data, volume->set_step_size(b_render.step_size()); volume->set_object_space((b_render.space() == BL::VolumeRender::space_OBJECT)); + float velocity_scale = b_volume.velocity_scale(); + if (b_volume.velocity_unit() == BL::Volume::velocity_unit_SECOND) { + /* 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; + + velocity_scale *= motion_scale; + } + + volume->set_velocity_scale(velocity_scale); + /* Find grid with matching name. */ for (BL::VolumeGrid &b_grid : b_volume.grids) { ustring name = ustring(b_grid.name()); @@ -267,9 +295,22 @@ static void sync_volume_object(BL::BlendData &b_data, else if (name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) { std = ATTR_STD_VOLUME_TEMPERATURE; } - else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) { + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) || + name == b_volume.velocity_grid()) { std = ATTR_STD_VOLUME_VELOCITY; } + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY_X) || + name == b_volume.velocity_x_grid()) { + std = ATTR_STD_VOLUME_VELOCITY_X; + } + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY_Y) || + name == b_volume.velocity_y_grid()) { + std = ATTR_STD_VOLUME_VELOCITY_Y; + } + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY_Z) || + name == b_volume.velocity_z_grid()) { + std = ATTR_STD_VOLUME_VELOCITY_Z; + } if ((std != ATTR_STD_NONE && volume->need_attribute(scene, std)) || volume->need_attribute(scene, name)) { @@ -294,11 +335,11 @@ void BlenderSync::sync_volume(BObjectInfo &b_ob_info, Volume *volume) if (b_ob_info.object_data.is_a(&RNA_Volume)) { /* Volume object. Create only attributes, bounding mesh will then * be automatically generated later. */ - sync_volume_object(b_data, b_ob_info, scene, volume); + sync_volume_object(b_data, b_scene, b_ob_info, scene, volume); } else { /* Smoke domain. */ - sync_smoke_volume(scene, b_ob_info, volume, b_scene.frame_current()); + sync_smoke_volume(b_scene, scene, b_ob_info, volume, b_scene.frame_current()); } } |