C++ Minimal implementation of motion blur?

I’ve tried to guess without luck about adding motion blur to my sample based on Cycles standalone.

Some params are easy to find like
scene->camera->shuttertime = 1.0f/speed;

But unfortunately I don’t know the full chain of functions I need to call to get proper motion blur in both modes (camera/mesh).

Any help on this is welcome!

I’ll try to summon two master @brecht @LazyDodo

For objects (Meshes and Curves):

  • transformation motion blur: set the various transformation matrices in object->motion, in chronological order from the previous frame to the next frame (including subframes/substeps, with a maximum of Object::MAX_MOTION_STEPS values).
  • set object->geometry->motion_steps to the number of steps/frames that you have
  • deformation motion blur:
    1. set object->geometry->use_motion_blur
    2. add vertex positions for the previous, and next frame as an attribute (i.e. mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION), and ATTR_STD_MOTION_VERTEX_NORMAL if you have data for it); the number of vertices have to match across all frames, if the vertex count changes (like for a liquid simulation), you will need to interpolate the vertex positions based on some velocity field

For camera:

  • transformation motion blur: set the various transformation matrices in camera->motion, similar to Object::motion
  • perspective motion blur: set camera->fov_pre (previous frame), camera->fov_post (next frame), and camera->use_perspective_motion
  • set shutter informations

To enable motion blur, set integrator->motion_blur = true.

Unless I forgot something, that should be it.

Thank you @KevinDietrich I managed to implement it but using ATTR_STD_MOTION_VERTEX_POSITION I got weird artifacts and also it becomes extremely slow (about 20 times slower than without mb).

If I disable object->geometry->use_motion_blur it comes back to a normal behaviour, also if I do not add ATTR_STD_MOTION_VERTEX_NORMAL it works ok too.

My rough aproximation was finding the attribute if it exists:

ccl::Attribute* attr_vert = cyclesMesh->attributes.find(attributeName);
if (attr_vert == nullptr)
{
	attr_vert = cyclesMesh->attributes.add(ccl::ATTR_STD_MOTION_VERTEX_POSITION, attributeName);
}
ccl::float3* attr_data_vert = attr_vert->data_float3();

And after that I fill the attr_data_vert.

Also I fill it twice one with an offset 0 and another time with offset NumVertex, my intention is that the first offset is the previous frame and the second pass is the next frame, notice that for testing I also tried by filling the vertex with the current position so it shouldn’t generate any motion blur.

And just for finish it:

cyclesMesh->tag_update(scene, true);
cyclesObject->tag_update(scene);

I’m driving nuts about that the implementation, in brief I have set the current vertex and I have the previous and next frame but I’m getting weird results everytime and probably I’ve missed a step.

Any tip is welcome!

Your code snippets seem fine to me. The artifacts could come from the way you fill in the attribute. In Cycles, float3 is 16 bytes wide (so 4 floats) due to alignement specification on certain hardware, so if you use memcpy from a source that is only using 3 floats to store vertices, this will pose a problem (I had such issues in the past).

The attribute is indeed supposed to be have the data for the previous frame at index 0 and then the next frame at offset NumVertex, so this is also fine.

Seeing the actual code could help (I am diekev on github, if you have the code there in private repository or so), or even a render result.