Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add motion blur support #260

Merged
merged 5 commits into from
Mar 30, 2019
Merged

Add motion blur support #260

merged 5 commits into from
Mar 30, 2019

Conversation

usakhelo
Copy link
Contributor

Hello!

This is quick attempt to add motion blur support. Both object and camera motion blur are supported.

  • To enable object motion blur appleseed object properties modifier needs to be added and optimize instances should be turned on. Plus Object motion blur should be enabled in standard object properties.
  • Camera motion blur turned on by using Physical camera and by turning on Enable Motion Blur checkbox.
    In both cases physical camera's shutter speed is used to determine time offset.

@usakhelo
Copy link
Contributor Author

Hi @dictoon , I'm wondering if I understand correctly time offset for motion blur in appleseed: I used object's coordinate on the current frame for the frame 0 and coordinates with time offset for the frame 1 in appleseed file. Time offset equals to (shutter_duration * ticks_per_frame).

@Mango-3
Copy link
Member

Mango-3 commented Jan 12, 2019

Nice work Sergo!
I think (shutter_duration * ticks_per_frame) should work. In Max all time is in ticks, where 1 second = 4800 ticks. Depending on the frame rate (24, 25 or 30 per second) a frame lasts for
200, 192 or 160 ticks, respectively. You query the shutter duration in number of frames and then multiply with the ticks/frame to get the duration in total number of ticks.
https://help.autodesk.com/view/3DSMAX/2017/ENU/?guid=__files_GUID_5B1D652F_6BD8_4EAF_8380_4C489363A8C0_htm

@usakhelo
Copy link
Contributor Author

Thanks @Mango-3 ,
I think that's what I did, right? shutter_duration * GetTicksPerFrame()
I was so happy they have GetShutterDurationInFrames function. In UI max have so many options - frames, time, degrees. But that function just converts everything to frames.

@Mango-3
Copy link
Member

Mango-3 commented Jan 14, 2019

I think that's what I did, right? shutter_duration * GetTicksPerFrame()

Yes, that should work, independent of how the shutter time is set (frames, seconds, 1/seconds,..) in the UI, as you sad.

if (is_animated)
{
float shutter_duration = 0.5f;
if (view_node != nullptr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If view_node is nullptr, shutter_duration remains set to 0.5f and so we'll set a transform at time offset 0.5f * GetTicksPerFrame(). Is that what we want?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's we want, because only physical camera provides shutter duration parameter. If there's no physical camera then 0.5f is safe choice I guess. I honestly don't remember where 0.5 came from, maybe it's default for the physical camera

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's actually not quite right, even when there is a Physical Camera in the scene.

It seems to me that we should always set the camera's transforms at t=0 and t=1, and then we should set the camera's shutter times such that:

  • Opening times (begin and end) set to GetShutterOffsetInFrames() (or 0.0f when there is no Physical Camera)
  • Closing times (begin and end) set to GetShutterOffsetInFrames() + GetShutterDurationInFrames() (or 0.5f when there is no Physical Camera).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @dictoon ,
Are 0 and 1 frame numbers? Can I set transform for 1 to GetObjTMAfterWSM(time + GetTicksPerFrame())?
You mentioned camera transforms, but line 837 is about assembly transforms. What do we do here? Can I leave this place as is?
I added changes for camera transforms, only for physical camera case. I think only physical camera has Enable Motion Blur checkbox. Other cameras have it as a viewport multi-pass effect. I don't know if we should consider it or should not.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, they're arbitrary times. The idea is as follow: you set transforms (for transformation motion blur) or poses (for deformation motion blur) at arbitrary times, be it seconds, frames, etc. Then you tell the camera when to open the shutter, at what speed (and following what curve) and when to close it. The exact unit for the times is not specified by appleseed, it simply needs to be consistent.

@usakhelo
Copy link
Contributor Author

Fixed comments and rebased.
Thanks for review, @dictoon!

// Set motion blur parameters.
const float opening_time = phys_camera->GetShutterOffsetInFrames(time, FOREVER);
const float closing_time = opening_time + phys_camera->GetShutterDurationInFrames(time, FOREVER);
params.insert("shutter_open_begin_time", opening_time);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's recap:

  1. You're setting the first transform at time 0: since you adopted "frames" as the unit of time, that means you're setting the first transform at frame 0.

  2. You're setting the second transform at time 1, i.e. at frame 1.

  3. You're setting the shutter open and close times at (fractional) frame values, which I hope are between 0 and 1.

So it looks correct.

{
float shutter_duration = 0.5f;
if (view_node != nullptr)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct thing to do might be to remove everything related to the camera here, and simply set the object's transform at time = 0 (frame 0) and time = 1 (frame 1).

That means you would need to call GetObjTMAfterWSM() at time and time + GetTicksPerFrame().

@dictoon
Copy link
Member

dictoon commented Feb 1, 2019

This stuff is tricky...

I suggest to compare your results with V-Ray and/or Arnold to make sure we're handling transformation motion blur correctly in all cases.

@usakhelo
Copy link
Contributor Author

usakhelo commented Feb 5, 2019

Turned out I only have mental ray on my max 2016 and it looks little different than appleseed. I'll test on something more modern if I can get trial/demo access to it.

@Mango-3
Copy link
Member

Mango-3 commented Feb 6, 2019

You can download Corona for Max (2013-2019) and test it for 45 days free, even for commercial purposes in unlimited demo mode (no resolution limits or watermarks).
https://corona-renderer.com/download

@usakhelo
Copy link
Contributor Author

Hi @dictoon , I compared last version of object motion blur with Arnold and it looks fine except when open/close duration on the camera is longer than 1 frame.
Transforms on the object are for 0 and 1 frame, right? So if I set shutter duration more than 1 motion blur is broken.
My is guess we still need to check camera shutter duration when calculating transforms for the object and take max(1.0, shutter_duration) for the frame 1.

@dictoon
Copy link
Member

dictoon commented Feb 12, 2019

I'm not sure what Arnold does in this case: does it extrapolate the motion outside the [0, 1] range? In appleseed, we assume that the object stops moving before the first transform or after the last, i.e. we clamp motion.

Using max(1.0, shutter_duration) for frame 1 would push the time when the object reaches frame 1 in the future, i.e. it would make motion slower, that doesn't seem right (but maybe I'm wrong).

Can you show a comparison between Arnold and appleseed for, say, t=2, t=3 (and maybe t=-1, t=-2) when transforms have been set only at t=0 and t=1?

@usakhelo
Copy link
Contributor Author

Maybe we should just clamp duration to 1.0 then?

Below is the comparison. Lower sphere doesn't have mblur checked in the properties, but arnold ignores that checkbox as long as mblur is checked on camera:

Appleseed duration 2.0:
image

Arnold duration 2.0:
image

Appleseed and arnold duration 1.0:
image
image

@usakhelo
Copy link
Contributor Author

Oh, wait, I guess I misunderstood. Do you mean object have animation keys on frame 0 and 1 and I render on frame 2? There's no motion blur on that frame. I guess I misunderstood again:
Arnold, frame 2, animation of the upper sphere 0-1, duration on top image 1, on other one 2:
image
image

@usakhelo
Copy link
Contributor Author

Hi @dictoon ,
I rebased the branch and made small changes. Right now when shutter_duration parameter is 0-1 appleseed rendering looks the same as Arnold.
When the parameter is >1 Arnold moves the object further in the future, but only until animation keys are set. So if transforms are only set for 0 and 1 frame, and shutter_duration = 2, then the blur will be the same as if shutter_duration = 1.

@dictoon
Copy link
Member

dictoon commented Mar 30, 2019

I propose to merge this as it looks reasonable and actually matches Arnold for shutter durations in [0, 1].

Once merged we can continue testing and iterate.

Thanks for the quality work!

@dictoon dictoon merged commit 653595a into appleseedhq:master Mar 30, 2019
@usakhelo usakhelo deleted the motion_blur branch April 16, 2019 03:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants