Cycles: motion blur is now curved and passes exactly through the midpoint.

Previously it would only interpolate between the previous and next frame,
which meant it might not hit the current frame position.
This commit is contained in:
Brecht Van Lommel 2012-10-17 12:55:23 +00:00
parent afb75ad2af
commit d08b06f773
7 changed files with 54 additions and 24 deletions

@ -23,8 +23,9 @@ enum ObjectTransform {
OBJECT_INVERSE_TRANSFORM = 3,
OBJECT_PROPERTIES = 6,
OBJECT_TRANSFORM_MOTION_PRE = 8,
OBJECT_TRANSFORM_MOTION_POST = 12,
OBJECT_DUPLI = 16
OBJECT_TRANSFORM_MOTION_MID = 12,
OBJECT_TRANSFORM_MOTION_POST = 16,
OBJECT_DUPLI = 18
};
__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
@ -59,11 +60,15 @@ __device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int o
motion.pre.z = kernel_tex_fetch(__objects, offset + 2);
motion.pre.w = kernel_tex_fetch(__objects, offset + 3);
motion.mid.x = kernel_tex_fetch(__objects, offset + 4);
motion.mid.y = kernel_tex_fetch(__objects, offset + 5);
motion.mid.z = kernel_tex_fetch(__objects, offset + 6);
motion.mid.w = kernel_tex_fetch(__objects, offset + 7);
motion.post.x = kernel_tex_fetch(__objects, offset + 4);
motion.post.y = kernel_tex_fetch(__objects, offset + 5);
motion.post.z = kernel_tex_fetch(__objects, offset + 6);
motion.post.w = kernel_tex_fetch(__objects, offset + 7);
motion.post.x = kernel_tex_fetch(__objects, offset + 8);
motion.post.y = kernel_tex_fetch(__objects, offset + 9);
motion.post.z = kernel_tex_fetch(__objects, offset + 10);
motion.post.w = kernel_tex_fetch(__objects, offset + 11);
transform_motion_interpolate(&tfm, &motion, time);

@ -29,7 +29,7 @@
CCL_NAMESPACE_BEGIN
/* constants */
#define OBJECT_SIZE 18
#define OBJECT_SIZE 22
#define LIGHT_SIZE 4
#define FILTER_TABLE_SIZE 256
#define RAMP_TABLE_SIZE 256

@ -197,9 +197,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
}
#ifdef __CAMERA_MOTION__
else if(need_motion == Scene::MOTION_BLUR) {
/* todo: exact camera position will not be hit this way */
if(use_motion) {
transform_motion_decompose(&kcam->motion, &motion);
transform_motion_decompose(&kcam->motion, &motion, &matrix);
kcam->have_motion = 1;
}
}

@ -1254,8 +1254,6 @@ void WardBsdfNode::attributes(AttributeRequestSet *attributes)
void WardBsdfNode::compile(SVMCompiler& compiler)
{
ShaderInput *tangent_in = input("Tangent");
BsdfNode::compile(compiler, input("Roughness U"), input("Roughness V"));
}

@ -57,7 +57,7 @@ void Object::compute_bounds(bool motion_blur)
if(motion_blur && use_motion) {
MotionTransform decomp;
transform_motion_decompose(&decomp, &motion);
transform_motion_decompose(&decomp, &motion, &tfm);
bounds = BoundBox::empty;
@ -219,7 +219,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
mtfm_post = mtfm_post * itfm;
memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4);
memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4);
memcpy(&objects[offset+16], &mtfm_post, sizeof(float4)*4);
}
#ifdef __OBJECT_MOTION__
else if(need_motion == Scene::MOTION_BLUR) {
@ -227,21 +227,21 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
/* decompose transformations for interpolation */
MotionTransform decomp;
transform_motion_decompose(&decomp, &ob->motion);
memcpy(&objects[offset+8], &decomp, sizeof(float4)*8);
transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
memcpy(&objects[offset+8], &decomp, sizeof(float4)*12);
flag |= SD_OBJECT_MOTION;
have_motion = true;
}
else {
float4 no_motion = make_float4(FLT_MAX);
memcpy(&objects[offset+8], &no_motion, sizeof(float4));
memcpy(&objects[offset+8], &no_motion, sizeof(float4)*12);
}
}
#endif
/* dupli object coords */
objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
objects[offset+20] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
objects[offset+21] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
/* object flag */
if(ob->use_holdout)

@ -246,9 +246,10 @@ static void transform_decompose(Transform *decomp, const Transform *tfm)
decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
}
void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion)
void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid)
{
transform_decompose(&decomp->pre, &motion->pre);
transform_decompose(&decomp->mid, mid);
transform_decompose(&decomp->post, &motion->post);
}

@ -41,6 +41,7 @@ typedef struct Transform {
typedef struct MotionTransform {
Transform pre;
Transform mid;
Transform post;
} MotionTransform;
@ -383,11 +384,37 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform
{
Transform decomp;
decomp.x = quat_interpolate(motion->pre.x, motion->post.x, t);
decomp.y = (1.0f - t)*motion->pre.y + t*motion->post.y;
decomp.z = (1.0f - t)*motion->pre.z + t*motion->post.z;
decomp.w = (1.0f - t)*motion->pre.w + t*motion->post.w;
/* 3 point bezier curve interpolation for position */
float3 Ppre = float4_to_float3(motion->pre.y);
float3 Pmid = float4_to_float3(motion->mid.y);
float3 Ppost = float4_to_float3(motion->post.y);
float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost);
float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t);
decomp.y.x = P.x;
decomp.y.y = P.y;
decomp.y.z = P.z;
/* linear interpolation for rotation and scale */
if(t < 0.5f) {
t *= 2.0f;
decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t);
decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w;
decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z;
decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w;
}
else {
t = (t - 0.5f)*2.0f;
decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t);
decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w;
decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z;
decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w;
}
/* compose rotation, translation, scale into matrix */
transform_compose(tfm, &decomp);
}
@ -398,7 +425,7 @@ __device_inline bool operator==(const MotionTransform& A, const MotionTransform&
return (A.pre == B.pre && A.post == B.post);
}
void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion);
void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
#endif