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

View File

@@ -23,8 +23,9 @@ enum ObjectTransform {
OBJECT_INVERSE_TRANSFORM = 3, OBJECT_INVERSE_TRANSFORM = 3,
OBJECT_PROPERTIES = 6, OBJECT_PROPERTIES = 6,
OBJECT_TRANSFORM_MOTION_PRE = 8, OBJECT_TRANSFORM_MOTION_PRE = 8,
OBJECT_TRANSFORM_MOTION_POST = 12, OBJECT_TRANSFORM_MOTION_MID = 12,
OBJECT_DUPLI = 16 OBJECT_TRANSFORM_MOTION_POST = 16,
OBJECT_DUPLI = 18
}; };
__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type) __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.z = kernel_tex_fetch(__objects, offset + 2);
motion.pre.w = kernel_tex_fetch(__objects, offset + 3); 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.x = kernel_tex_fetch(__objects, offset + 8);
motion.post.y = kernel_tex_fetch(__objects, offset + 5); motion.post.y = kernel_tex_fetch(__objects, offset + 9);
motion.post.z = kernel_tex_fetch(__objects, offset + 6); motion.post.z = kernel_tex_fetch(__objects, offset + 10);
motion.post.w = kernel_tex_fetch(__objects, offset + 7); motion.post.w = kernel_tex_fetch(__objects, offset + 11);
transform_motion_interpolate(&tfm, &motion, time); transform_motion_interpolate(&tfm, &motion, time);

View File

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

View File

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

View File

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

View File

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

View File

@@ -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); 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->pre, &motion->pre);
transform_decompose(&decomp->mid, mid);
transform_decompose(&decomp->post, &motion->post); transform_decompose(&decomp->post, &motion->post);
} }

View File

@@ -41,6 +41,7 @@ typedef struct Transform {
typedef struct MotionTransform { typedef struct MotionTransform {
Transform pre; Transform pre;
Transform mid;
Transform post; Transform post;
} MotionTransform; } MotionTransform;
@@ -383,11 +384,37 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform
{ {
Transform decomp; Transform decomp;
decomp.x = quat_interpolate(motion->pre.x, motion->post.x, t); /* 3 point bezier curve interpolation for position */
decomp.y = (1.0f - t)*motion->pre.y + t*motion->post.y; float3 Ppre = float4_to_float3(motion->pre.y);
decomp.z = (1.0f - t)*motion->pre.z + t*motion->post.z; float3 Pmid = float4_to_float3(motion->mid.y);
decomp.w = (1.0f - t)*motion->pre.w + t*motion->post.w; 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); 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); 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 #endif