Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-04-30 16:49:26 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-04-30 16:49:26 +0400
commit1d8c79818870b92df46c443d7778438aa67d019c (patch)
treeba3fc305671261e40851d8a230a33ebe19396e95 /intern/cycles/kernel
parent796dd8a321108df26757fb9df5c2aa6eb42c9633 (diff)
Cycles: support for motion vector and UV passes.
Most of the changes are related to adding support for motion data throughout the code. There's some code for actual camera/object motion blur raytracing but it's unfinished (it badly slows down the raytracing kernel even when the option is turned off), so that code it disabled still. Motion vector export from Blender tries to avoid computing derived meshes when the mesh does not have a deforming modifier, and it also won't store motion vectors for every vertex if only the object or camera is moving.
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r--intern/cycles/kernel/kernel_bvh.h19
-rw-r--r--intern/cycles/kernel/kernel_camera.h25
-rw-r--r--intern/cycles/kernel/kernel_emission.h8
-rw-r--r--intern/cycles/kernel/kernel_light.h13
-rw-r--r--intern/cycles/kernel/kernel_object.h70
-rw-r--r--intern/cycles/kernel/kernel_passes.h7
-rw-r--r--intern/cycles/kernel/kernel_path.h17
-rw-r--r--intern/cycles/kernel/kernel_shader.h58
-rw-r--r--intern/cycles/kernel/kernel_triangle.h63
-rw-r--r--intern/cycles/kernel/kernel_types.h65
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h24
11 files changed, 295 insertions, 74 deletions
diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h
index 523ae8ae926..5da4253bd86 100644
--- a/intern/cycles/kernel/kernel_bvh.h
+++ b/intern/cycles/kernel/kernel_bvh.h
@@ -57,7 +57,7 @@ __device_inline float3 bvh_inverse_direction(float3 dir)
__device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax)
{
- Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, object, ray->time, OBJECT_INVERSE_TRANSFORM);
*P = transform_point(&tfm, ray->P);
@@ -74,7 +74,7 @@ __device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray
__device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *idir, float *t, const float tmax)
{
- Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, object, ray->time, OBJECT_TRANSFORM);
if(*t != FLT_MAX)
*t *= len(transform_direction(&tfm, 1.0f/(*idir)));
@@ -341,7 +341,7 @@ __device_inline float3 ray_offset(float3 P, float3 Ng)
#endif
}
-__device_inline float3 bvh_triangle_refine(KernelGlobals *kg, const Intersection *isect, const Ray *ray)
+__device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
{
float3 P = ray->P;
float3 D = ray->D;
@@ -349,7 +349,11 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, const Intersection
#ifdef __INTERSECTION_REFINE__
if(isect->object != ~0) {
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+#ifdef __MOTION__
+ Transform tfm = sd->ob_itfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, ray->time, OBJECT_INVERSE_TRANSFORM);
+#endif
P = transform_point(&tfm, P);
D = transform_direction(&tfm, D*t);
@@ -366,7 +370,12 @@ __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, const Intersection
P = P + D*rt;
if(isect->object != ~0) {
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+#ifdef __MOTION__
+ Transform tfm = sd->ob_tfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, ray->time, OBJECT_TRANSFORM);
+#endif
+
P = transform_point(&tfm, P);
}
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 99dac18d545..7b93ed7c0e6 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -63,6 +63,11 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float
/* transform ray from camera to world */
Transform cameratoworld = kernel_data.cam.cameratoworld;
+#ifdef __MOTION__
+ if(ray->time != TIME_INVALID)
+ transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
+#endif
+
ray->P = transform_point(&cameratoworld, ray->P);
ray->D = transform_direction(&cameratoworld, ray->D);
ray->D = normalize(ray->D);
@@ -101,6 +106,11 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa
/* transform ray from camera to world */
Transform cameratoworld = kernel_data.cam.cameratoworld;
+#ifdef __MOTION__
+ if(ray->time != TIME_INVALID)
+ transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
+#endif
+
ray->P = transform_point(&cameratoworld, ray->P);
ray->D = transform_direction(&cameratoworld, ray->D);
ray->D = normalize(ray->D);
@@ -136,6 +146,11 @@ __device void camera_sample_environment(KernelGlobals *kg, float raster_x, float
/* transform ray from camera to world */
Transform cameratoworld = kernel_data.cam.cameratoworld;
+#ifdef __MOTION__
+ if(ray->time != TIME_INVALID)
+ transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
+#endif
+
ray->P = transform_point(&cameratoworld, ray->P);
ray->D = transform_direction(&cameratoworld, ray->D);
ray->D = normalize(ray->D);
@@ -162,14 +177,20 @@ __device void camera_sample_environment(KernelGlobals *kg, float raster_x, float
/* Common */
-__device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, float filter_v, float lens_u, float lens_v, Ray *ray)
+__device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, float filter_v,
+ float lens_u, float lens_v, float time, Ray *ray)
{
/* pixel filter */
float raster_x = x + kernel_tex_interp(__filter_table, filter_u, FILTER_TABLE_SIZE);
float raster_y = y + kernel_tex_interp(__filter_table, filter_v, FILTER_TABLE_SIZE);
+#ifdef __MOTION__
/* motion blur */
- //ray->time = lerp(time_t, kernel_data.cam.shutter_open, kernel_data.cam.shutter_close);
+ if(kernel_data.cam.shuttertime == 0.0f)
+ ray->time = TIME_INVALID;
+ else
+ ray->time = 0.5f + (time - 0.5f)*kernel_data.cam.shuttertime;
+#endif
/* sample */
if(kernel_data.cam.type == CAMERA_PERSPECTIVE)
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 764ac599991..cd7701a0c75 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN
/* Direction Emission */
__device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
- LightSample *ls, float u, float v, float3 I)
+ LightSample *ls, float u, float v, float3 I, float time)
{
/* setup shading at emitter */
ShaderData sd;
@@ -40,7 +40,7 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
else
#endif
{
- shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v);
+ shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v, time);
ls->Ng = sd.Ng;
/* no path flag, we're evaluating this for all closures. that's weak but
@@ -76,7 +76,7 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
#endif
{
/* sample a light and position on int */
- light_sample(kg, randt, randu, randv, sd->P, &ls, &pdf);
+ light_sample(kg, randt, randu, randv, sd->time, sd->P, &ls, &pdf);
}
/* compute pdf */
@@ -87,7 +87,7 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
return false;
/* evaluate closure */
- float3 light_eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D);
+ float3 light_eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D, sd->time);
if(is_zero(light_eval))
return false;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 42260577069..c2cf293cab3 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -251,7 +251,7 @@ __device float regular_light_pdf(KernelGlobals *kg,
/* Triangle Light */
__device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
- float randu, float randv, LightSample *ls)
+ float randu, float randv, float time, LightSample *ls)
{
/* triangle, so get position, normal, shader */
ls->P = triangle_sample_MT(kg, prim, randu, randv);
@@ -264,8 +264,11 @@ __device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
#ifdef __INSTANCING__
/* instance transform */
if(ls->object >= 0) {
- object_position_transform(kg, ls->object, &ls->P);
- object_normal_transform(kg, ls->object, &ls->Ng);
+ Transform tfm = object_fetch_transform(kg, ls->object, time, OBJECT_TRANSFORM);
+ Transform itfm = object_fetch_transform(kg, ls->object, time, OBJECT_INVERSE_TRANSFORM);
+
+ ls->P = transform_point(&tfm, ls->P);
+ ls->Ng = transform_direction_transposed(&itfm, ls->Ng);
}
#endif
}
@@ -313,7 +316,7 @@ __device int light_distribution_sample(KernelGlobals *kg, float randt)
/* Generic Light */
-__device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float3 P, LightSample *ls, float *pdf)
+__device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls, float *pdf)
{
/* sample index */
int index = light_distribution_sample(kg, randt);
@@ -324,7 +327,7 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
if(prim >= 0) {
int object = __float_as_int(l.w);
- triangle_light_sample(kg, prim, object, randu, randv, ls);
+ triangle_light_sample(kg, prim, object, randu, randv, time, ls);
}
else {
int point = -prim-1;
diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h
index b676f58e5d4..262ca848f28 100644
--- a/intern/cycles/kernel/kernel_object.h
+++ b/intern/cycles/kernel/kernel_object.h
@@ -20,41 +20,87 @@ CCL_NAMESPACE_BEGIN
enum ObjectTransform {
OBJECT_TRANSFORM = 0,
- OBJECT_INVERSE_TRANSFORM = 4,
- OBJECT_NORMAL_TRANSFORM = 8,
- OBJECT_PROPERTIES = 12
+ OBJECT_INVERSE_TRANSFORM = 3,
+ OBJECT_PROPERTIES = 6,
+ OBJECT_TRANSFORM_MOTION_PRE = 8,
+ OBJECT_TRANSFORM_MOTION_POST = 12
};
-__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
+__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, float time, enum ObjectTransform type)
{
Transform tfm;
+#ifdef __MOTION__
+ /* if we do motion blur */
+ if(time != TIME_INVALID) {
+ int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE;
+ float4 have_motion = kernel_tex_fetch(__objects, offset + 0);
+
+ /* if this object have motion */
+ if(have_motion.x != FLT_MAX) {
+ /* fetch motion transforms */
+ MotionTransform motion;
+
+ motion.pre.x = have_motion;
+ motion.pre.y = kernel_tex_fetch(__objects, offset + 1);
+ motion.pre.z = kernel_tex_fetch(__objects, offset + 2);
+ motion.pre.w = kernel_tex_fetch(__objects, offset + 3);
+
+ 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);
+
+ /* interpolate (todo: do only once per object) */
+ transform_motion_interpolate(&tfm, &motion, time);
+
+ /* invert */
+ if(type == OBJECT_INVERSE_TRANSFORM)
+ tfm = transform_quick_inverse(tfm);
+
+ return tfm;
+ }
+ }
+#endif
+
int offset = object*OBJECT_SIZE + (int)type;
tfm.x = kernel_tex_fetch(__objects, offset + 0);
tfm.y = kernel_tex_fetch(__objects, offset + 1);
tfm.z = kernel_tex_fetch(__objects, offset + 2);
- tfm.w = kernel_tex_fetch(__objects, offset + 3);
+ tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
return tfm;
}
-__device_inline void object_position_transform(KernelGlobals *kg, int object, float3 *P)
+__device_inline void object_position_transform(KernelGlobals *kg, ShaderData *sd, float3 *P)
{
- Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+#ifdef __MOTION__
+ *P = transform_point(&sd->ob_tfm, *P);
+#else
+ Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM);
*P = transform_point(&tfm, *P);
+#endif
}
-__device_inline void object_normal_transform(KernelGlobals *kg, int object, float3 *N)
+__device_inline void object_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N)
{
- Transform tfm = object_fetch_transform(kg, object, OBJECT_NORMAL_TRANSFORM);
- *N = normalize(transform_direction(&tfm, *N));
+#ifdef __MOTION__
+ *N = normalize(transform_direction_transposed(&sd->ob_itfm, *N));
+#else
+ Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_INVERSE_TRANSFORM);
+ *N = normalize(transform_direction_transposed(&tfm, *N));
+#endif
}
-__device_inline void object_dir_transform(KernelGlobals *kg, int object, float3 *D)
+__device_inline void object_dir_transform(KernelGlobals *kg, ShaderData *sd, float3 *D)
{
- Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+#ifdef __MOTION__
+ *D = transform_direction(&sd->ob_tfm, *D);
+#else
+ Transform tfm = object_fetch_transform(kg, sd->object, 0.0f, OBJECT_TRANSFORM);
*D = transform_direction(&tfm, *D);
+#endif
}
__device_inline float object_surface_area(KernelGlobals *kg, int object)
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index fd4ee17cdc1..f3ddda4a392 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -72,9 +72,14 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
- float3 uv = make_float3(0.0f, 0.0f, 0.0f); /* todo: request and lookup */
+ float3 uv = triangle_uv(kg, sd);
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
}
+ if(flag & PASS_MOTION) {
+ float4 speed = triangle_motion_vector(kg, sd);
+ kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, sample, speed);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, sample, 1.0f);
+ }
}
if(flag & (PASS_DIFFUSE_INDIRECT|PASS_DIFFUSE_COLOR|PASS_DIFFUSE_DIRECT))
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 8ebac177277..b7c22087e1f 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -18,8 +18,8 @@
#include "kernel_differential.h"
#include "kernel_montecarlo.h"
-#include "kernel_triangle.h"
#include "kernel_object.h"
+#include "kernel_triangle.h"
#ifdef __QBVH__
#include "kernel_qbvh.h"
#else
@@ -324,6 +324,9 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
light_ray.P = ray_offset(sd.P, sd.Ng);
light_ray.D = ao_D;
light_ray.t = kernel_data.background.ao_distance;
+#ifdef __MOTION__
+ light_ray.time = sd.time;
+#endif
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor;
@@ -346,6 +349,10 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
BsdfEval L_light;
bool is_lamp;
+#ifdef __MOTION__
+ light_ray.time = sd.time;
+#endif
+
#ifdef __MULTI_LIGHT__
/* index -1 means randomly sample from distribution */
int i = (kernel_data.integrator.num_distribution)? -1: 0;
@@ -449,7 +456,13 @@ __device void kernel_path_trace(KernelGlobals *kg,
float lens_u = path_rng(kg, &rng, sample, PRNG_LENS_U);
float lens_v = path_rng(kg, &rng, sample, PRNG_LENS_V);
- camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, &ray);
+#ifdef __MOTION__
+ float time = path_rng(kg, &rng, sample, PRNG_TIME);
+#else
+ float time = 0.0f;
+#endif
+
+ camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, &ray);
/* integrate */
float4 L = kernel_path_integrate(kg, &rng, sample, ray, buffer);
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 46ef5d2022a..b2f2a7577be 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -53,16 +53,9 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
int shader = __float_as_int(Ns.w);
- /* vectors */
- sd->P = bvh_triangle_refine(kg, isect, ray);
- sd->Ng = Ng;
- sd->N = Ng;
- sd->I = -ray->D;
- sd->shader = shader;
-
/* triangle */
#ifdef __INSTANCING__
- sd->object = isect->object;
+ sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
#endif
sd->prim = prim;
#ifdef __UV__
@@ -70,6 +63,21 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->v = isect->v;
#endif
+ /* matrices and time */
+#ifdef __MOTION__
+ sd->ob_tfm = object_fetch_transform(kg, sd->object, ray->time, OBJECT_TRANSFORM);
+ sd->ob_itfm = object_fetch_transform(kg, sd->object, ray->time, OBJECT_INVERSE_TRANSFORM);
+
+ sd->time = ray->time;
+#endif
+
+ /* vectors */
+ sd->P = bvh_triangle_refine(kg, sd, isect, ray);
+ sd->Ng = Ng;
+ sd->N = Ng;
+ sd->I = -ray->D;
+ sd->shader = shader;
+
/* smooth normal */
if(sd->shader & SHADER_SMOOTH_NORMAL)
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
@@ -82,19 +90,15 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#endif
#ifdef __INSTANCING__
- if(sd->object != ~0) {
+ if(isect->object != ~0) {
/* instance transform */
- object_normal_transform(kg, sd->object, &sd->N);
- object_normal_transform(kg, sd->object, &sd->Ng);
+ object_normal_transform(kg, sd, &sd->N);
+ object_normal_transform(kg, sd, &sd->Ng);
#ifdef __DPDU__
- object_dir_transform(kg, sd->object, &sd->dPdu);
- object_dir_transform(kg, sd->object, &sd->dPdv);
+ object_dir_transform(kg, sd, &sd->dPdu);
+ object_dir_transform(kg, sd, &sd->dPdv);
#endif
}
- else {
- /* non-instanced object index */
- sd->object = kernel_tex_fetch(__prim_object, isect->prim);
- }
#endif
/* backfacing test */
@@ -122,7 +126,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
__device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
const float3 P, const float3 Ng, const float3 I,
- int shader, int object, int prim, float u, float v)
+ int shader, int object, int prim, float u, float v, float time)
{
/* vectors */
sd->P = P;
@@ -155,13 +159,20 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
}
#endif
+#ifdef __MOTION__
+ sd->time = time;
+
+ sd->ob_tfm = object_fetch_transform(kg, sd->object, time, OBJECT_TRANSFORM);
+ sd->ob_itfm = object_fetch_transform(kg, sd->object, time, OBJECT_INVERSE_TRANSFORM);
+#endif
+
/* smooth normal */
if(sd->shader & SHADER_SMOOTH_NORMAL) {
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#ifdef __INSTANCING__
if(instanced)
- object_normal_transform(kg, sd->object, &sd->N);
+ object_normal_transform(kg, sd, &sd->N);
#endif
}
@@ -178,8 +189,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#ifdef __INSTANCING__
if(instanced) {
- object_dir_transform(kg, sd->object, &sd->dPdu);
- object_dir_transform(kg, sd->object, &sd->dPdv);
+ object_dir_transform(kg, sd, &sd->dPdu);
+ object_dir_transform(kg, sd, &sd->dPdv);
}
#endif
}
@@ -229,7 +240,7 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
/* watch out: no instance transform currently */
- shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v);
+ shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, TIME_INVALID);
}
/* ShaderData setup from ray into background */
@@ -243,6 +254,9 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
sd->I = -sd->P;
sd->shader = kernel_data.background.shader;
sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
+#ifdef __MOTION__
+ sd->time = ray->time;
+#endif
#ifdef __INSTANCING__
sd->object = ~0;
diff --git a/intern/cycles/kernel/kernel_triangle.h b/intern/cycles/kernel/kernel_triangle.h
index 7eaf54d14bf..1b3956c1dd4 100644
--- a/intern/cycles/kernel/kernel_triangle.h
+++ b/intern/cycles/kernel/kernel_triangle.h
@@ -179,5 +179,68 @@ __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *s
}
}
+/* motion */
+
+__device int triangle_find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
+{
+ /* find attribute by unique id */
+ uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
+ uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+
+ while(attr_map.x != id)
+ attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
+
+ /* return result */
+ return (attr_map.y == ATTR_ELEMENT_NONE)? ATTR_STD_NOT_FOUND: attr_map.z;
+}
+
+__device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
+{
+ float3 motion_pre = sd->P, motion_post = sd->P;
+
+ /* deformation motion */
+ int offset_pre = triangle_find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
+ int offset_post = triangle_find_attribute(kg, sd, ATTR_STD_MOTION_POST);
+
+ if(offset_pre != ATTR_STD_NOT_FOUND)
+ motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
+ if(offset_post != ATTR_STD_NOT_FOUND)
+ motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL);
+
+ /* object motion. note that depending on the mesh having motion vectors, this
+ transformation was set match the world/object space of motion_pre/post */
+ Transform tfm;
+
+ tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_PRE);
+ motion_pre = transform_point(&tfm, motion_pre);
+
+ tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_POST);
+ motion_post = transform_point(&tfm, motion_post);
+
+ /* camera motion */
+ tfm = kernel_data.cam.worldtoraster;
+ float3 P = transform_perspective(&tfm, sd->P);
+
+ tfm = kernel_data.cam.motion.pre;
+ motion_pre = transform_perspective(&tfm, motion_pre) - P;
+
+ tfm = kernel_data.cam.motion.post;
+ motion_post = P - transform_perspective(&tfm, motion_post);
+
+ return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
+}
+
+__device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
+{
+ int offset_uv = triangle_find_attribute(kg, sd, ATTR_STD_UV);
+
+ if(offset_uv == ATTR_STD_NOT_FOUND)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float3 uv = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, offset_uv, NULL, NULL);
+ uv.z = 1.0f;
+ return uv;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 102a2bb036d..e9103087025 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -20,9 +20,12 @@
#define __KERNEL_TYPES_H__
#include "kernel_math.h"
-
#include "svm/svm_types.h"
+#ifndef __KERNEL_GPU__
+#define __KERNEL_CPU__
+#endif
+
CCL_NAMESPACE_BEGIN
/* constants */
@@ -30,6 +33,7 @@ CCL_NAMESPACE_BEGIN
#define LIGHT_SIZE 4
#define FILTER_TABLE_SIZE 256
#define RAMP_TABLE_SIZE 256
+#define TIME_INVALID FLT_MAX
/* device capabilities */
#ifdef __KERNEL_CPU__
@@ -75,6 +79,7 @@ CCL_NAMESPACE_BEGIN
#define __PASSES__
#define __BACKGROUND_MIS__
#define __AO__
+//#define __MOTION__
#endif
//#define __MULTI_LIGHT__
@@ -90,14 +95,21 @@ enum ShaderEvalType {
SHADER_EVAL_BACKGROUND
};
-/* Path Tracing */
+/* Path Tracing
+ * note we need to keep the u/v pairs at even values */
enum PathTraceDimension {
PRNG_FILTER_U = 0,
PRNG_FILTER_V = 1,
PRNG_LENS_U = 2,
PRNG_LENS_V = 3,
+#ifdef __MOTION__
+ PRNG_TIME = 4,
+ PRNG_UNUSED = 5,
+ PRNG_BASE_NUM = 6,
+#else
PRNG_BASE_NUM = 4,
+#endif
PRNG_BSDF_U = 0,
PRNG_BSDF_V = 1,
@@ -177,7 +189,9 @@ typedef enum PassType {
PASS_EMISSION = 65536,
PASS_BACKGROUND = 131072,
PASS_AO = 262144,
- PASS_SHADOW = 524288
+ PASS_SHADOW = 524288,
+ PASS_MOTION = 1048576,
+ PASS_MOTION_WEIGHT = 2097152
} PassType;
#define PASS_ALL (~0)
@@ -275,6 +289,7 @@ typedef struct Ray {
float3 P;
float3 D;
float t;
+ float time;
#ifdef __RAY_DIFFERENTIALS__
differential3 dP;
@@ -300,6 +315,21 @@ typedef enum AttributeElement {
ATTR_ELEMENT_NONE
} AttributeElement;
+typedef enum AttributeStandard {
+ ATTR_STD_NONE = 0,
+ ATTR_STD_VERTEX_NORMAL,
+ ATTR_STD_FACE_NORMAL,
+ ATTR_STD_UV,
+ ATTR_STD_GENERATED,
+ ATTR_STD_POSITION_UNDEFORMED,
+ ATTR_STD_POSITION_UNDISPLACED,
+ ATTR_STD_MOTION_PRE,
+ ATTR_STD_MOTION_POST,
+ ATTR_STD_NUM,
+
+ ATTR_STD_NOT_FOUND = ~0
+} AttributeStandard;
+
/* Closure data */
#define MAX_CLOSURE 8
@@ -365,6 +395,16 @@ typedef struct ShaderData {
/* object id if there is one, ~0 otherwise */
int object;
+ /* motion blur sample time */
+ float time;
+
+#ifdef __MOTION__
+ /* object <-> world space transformations, cached to avoid
+ * re-interpolating them constantly for shading */
+ Transform ob_tfm;
+ Transform ob_itfm;
+#endif
+
#ifdef __RAY_DIFFERENTIALS__
/* differential of P. these are orthogonal to Ng, not N */
differential3 dP;
@@ -422,8 +462,8 @@ typedef struct KernelCamera {
float focaldistance;
/* motion blur */
- float shutteropen;
- float shutterclose;
+ float shuttertime;
+ float pad;
/* clipping */
float nearclip;
@@ -437,6 +477,8 @@ typedef struct KernelCamera {
Transform worldtoraster;
Transform worldtondc;
Transform worldtocamera;
+
+ MotionTransform motion;
} KernelCamera;
typedef struct KernelFilm {
@@ -448,27 +490,32 @@ typedef struct KernelFilm {
int pass_combined;
int pass_depth;
int pass_normal;
- int pass_pad;
+ int pass_motion;
+ int pass_motion_weight;
int pass_uv;
int pass_object_id;
int pass_material_id;
- int pass_diffuse_color;
+ int pass_diffuse_color;
int pass_glossy_color;
int pass_transmission_color;
int pass_diffuse_indirect;
- int pass_glossy_indirect;
+ int pass_glossy_indirect;
int pass_transmission_indirect;
int pass_diffuse_direct;
int pass_glossy_direct;
- int pass_transmission_direct;
+ int pass_transmission_direct;
int pass_emission;
int pass_background;
int pass_ao;
+
int pass_shadow;
+ int pass_pad1;
+ int pass_pad2;
+ int pass_pad3;
} KernelFilm;
typedef struct KernelBackground {
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index 98f8734aed2..5ecda795251 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -33,8 +33,8 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack
switch(type) {
case NODE_TEXCO_OBJECT: {
if(sd->object != ~0) {
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- data = transform_point(&tfm, sd->P);
+ data = sd->P;
+ object_position_transform(kg, sd, &data);
}
else
data = sd->P;
@@ -42,8 +42,8 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack
}
case NODE_TEXCO_NORMAL: {
if(sd->object != ~0) {
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- data = transform_direction(&tfm, sd->N);
+ data = sd->N;
+ object_normal_transform(kg, sd, &data);
}
else
data = sd->N;
@@ -87,8 +87,8 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa
switch(type) {
case NODE_TEXCO_OBJECT: {
if(sd->object != ~0) {
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- data = transform_point(&tfm, sd->P + sd->dP.dx);
+ data = sd->P + sd->dP.dx;
+ object_position_transform(kg, sd, &data);
}
else
data = sd->P + sd->dP.dx;
@@ -96,8 +96,8 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa
}
case NODE_TEXCO_NORMAL: {
if(sd->object != ~0) {
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- data = transform_direction(&tfm, sd->N);
+ data = sd->N;
+ object_normal_transform(kg, sd, &data);
}
else
data = sd->N;
@@ -144,8 +144,8 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
switch(type) {
case NODE_TEXCO_OBJECT: {
if(sd->object != ~0) {
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- data = transform_point(&tfm, sd->P + sd->dP.dy);
+ data = sd->P + sd->dP.dy;
+ object_position_transform(kg, sd, &data);
}
else
data = sd->P + sd->dP.dy;
@@ -153,8 +153,8 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
}
case NODE_TEXCO_NORMAL: {
if(sd->object != ~0) {
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- data = normalize(transform_direction(&tfm, sd->N));
+ data = sd->N;
+ object_normal_transform(kg, sd, &data);
}
else
data = sd->N;