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@gmail.com>2018-03-10 08:55:39 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-03-10 08:55:39 +0300
commitd27158aae9bc48b2a07760a2dbe8e642fcecbe57 (patch)
tree7ecfe898e53f07e589ee4be0ea5b297153d7dfcf /intern/cycles/render
parentf3161bd2abe4bcc41f0e9169275be315ecc6b054 (diff)
parent8a76f8dac3475b1d24956e0d384d65295f15c76a (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/camera.cpp154
-rw-r--r--intern/cycles/render/camera.h28
-rw-r--r--intern/cycles/render/light.cpp141
-rw-r--r--intern/cycles/render/mesh.cpp161
-rw-r--r--intern/cycles/render/mesh.h8
-rw-r--r--intern/cycles/render/mesh_volume.cpp46
-rw-r--r--intern/cycles/render/nodes.cpp17
-rw-r--r--intern/cycles/render/object.cpp284
-rw-r--r--intern/cycles/render/object.h56
-rw-r--r--intern/cycles/render/osl.cpp15
-rw-r--r--intern/cycles/render/particles.cpp22
-rw-r--r--intern/cycles/render/scene.cpp10
-rw-r--r--intern/cycles/render/scene.h18
-rw-r--r--intern/cycles/render/session.cpp4
-rw-r--r--intern/cycles/render/shader.cpp21
15 files changed, 569 insertions, 416 deletions
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index a2fda12ec85..38936ffc094 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -82,6 +82,7 @@ NODE_DEFINE(Camera)
SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f);
SOCKET_TRANSFORM(matrix, "Matrix", transform_identity());
+ SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f);
@@ -151,9 +152,6 @@ Camera::Camera()
height = 512;
resolution = 1;
- motion.pre = transform_identity();
- motion.post = transform_identity();
- use_motion = false;
use_perspective_motion = false;
shutter_curve.resize(RAMP_TABLE_SIZE);
@@ -163,12 +161,12 @@ Camera::Camera()
compute_auto_viewplane();
- screentoworld = transform_identity();
- rastertoworld = transform_identity();
- ndctoworld = transform_identity();
- rastertocamera = transform_identity();
+ screentoworld = projection_identity();
+ rastertoworld = projection_identity();
+ ndctoworld = projection_identity();
+ rastertocamera = projection_identity();
cameratoworld = transform_identity();
- worldtoraster = transform_identity();
+ worldtoraster = projection_identity();
dx = make_float3(0.0f, 0.0f, 0.0f);
dy = make_float3(0.0f, 0.0f, 0.0f);
@@ -241,18 +239,18 @@ void Camera::update(Scene *scene)
Transform full_rastertoscreen = transform_inverse(full_screentoraster);
/* screen to camera */
- Transform cameratoscreen;
+ ProjectionTransform cameratoscreen;
if(type == CAMERA_PERSPECTIVE)
- cameratoscreen = transform_perspective(fov, nearclip, farclip);
+ cameratoscreen = projection_perspective(fov, nearclip, farclip);
else if(type == CAMERA_ORTHOGRAPHIC)
- cameratoscreen = transform_orthographic(nearclip, farclip);
+ cameratoscreen = projection_orthographic(nearclip, farclip);
else
- cameratoscreen = transform_identity();
+ cameratoscreen = projection_identity();
- Transform screentocamera = transform_inverse(cameratoscreen);
+ ProjectionTransform screentocamera = projection_inverse(cameratoscreen);
rastertocamera = screentocamera * rastertoscreen;
- Transform full_rastertocamera = screentocamera * full_rastertoscreen;
+ ProjectionTransform full_rastertocamera = screentocamera * full_rastertoscreen;
cameratoraster = screentoraster * cameratoscreen;
cameratoworld = matrix;
@@ -270,10 +268,10 @@ void Camera::update(Scene *scene)
/* differentials */
if(type == CAMERA_ORTHOGRAPHIC) {
- dx = transform_direction(&rastertocamera, make_float3(1, 0, 0));
- dy = transform_direction(&rastertocamera, make_float3(0, 1, 0));
- full_dx = transform_direction(&full_rastertocamera, make_float3(1, 0, 0));
- full_dy = transform_direction(&full_rastertocamera, make_float3(0, 1, 0));
+ dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0));
+ dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0));
+ full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0));
+ full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0));
}
else if(type == CAMERA_PERSPECTIVE) {
dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
@@ -302,23 +300,6 @@ void Camera::update(Scene *scene)
frustum_top_normal = normalize(make_float3(0.0f, v.z, -v.y));
}
- /* TODO(sergey): Support other types of camera. */
- if(type == CAMERA_PERSPECTIVE) {
- /* TODO(sergey): Move to an utility function and de-duplicate with
- * calculation above.
- */
- Transform screentocamera_pre =
- transform_inverse(transform_perspective(fov_pre,
- nearclip,
- farclip));
- Transform screentocamera_post =
- transform_inverse(transform_perspective(fov_post,
- nearclip,
- farclip));
- perspective_motion.pre = screentocamera_pre * rastertoscreen;
- perspective_motion.post = screentocamera_post * rastertoscreen;
- }
-
/* Compute kernel camera data. */
KernelCamera *kcam = &kernel_camera;
@@ -331,41 +312,65 @@ void Camera::update(Scene *scene)
kcam->worldtoscreen = worldtoscreen;
kcam->worldtoraster = worldtoraster;
kcam->worldtondc = worldtondc;
+ kcam->ndctoworld = ndctoworld;
/* camera motion */
- kcam->have_motion = 0;
+ kcam->num_motion_steps = 0;
kcam->have_perspective_motion = 0;
+ kernel_camera_motion.clear();
+
+ /* Test if any of the transforms are actually different. */
+ bool have_motion = false;
+ for(size_t i = 0; i < motion.size(); i++) {
+ have_motion = have_motion || motion[i] != matrix;
+ }
if(need_motion == Scene::MOTION_PASS) {
/* TODO(sergey): Support perspective (zoom, fov) motion. */
if(type == CAMERA_PANORAMA) {
- if(use_motion) {
- kcam->motion.pre = transform_inverse(motion.pre);
- kcam->motion.post = transform_inverse(motion.post);
+ if(have_motion) {
+ kcam->motion_pass_pre = transform_inverse(motion[0]);
+ kcam->motion_pass_post = transform_inverse(motion[motion.size()-1]);
}
else {
- kcam->motion.pre = kcam->worldtocamera;
- kcam->motion.post = kcam->worldtocamera;
+ kcam->motion_pass_pre = kcam->worldtocamera;
+ kcam->motion_pass_post = kcam->worldtocamera;
}
}
else {
- if(use_motion) {
- kcam->motion.pre = cameratoraster * transform_inverse(motion.pre);
- kcam->motion.post = cameratoraster * transform_inverse(motion.post);
+ if(have_motion) {
+ kcam->perspective_pre = cameratoraster * transform_inverse(motion[0]);
+ kcam->perspective_post = cameratoraster * transform_inverse(motion[motion.size()-1]);
}
else {
- kcam->motion.pre = worldtoraster;
- kcam->motion.post = worldtoraster;
+ kcam->perspective_pre = worldtoraster;
+ kcam->perspective_post = worldtoraster;
}
}
}
else if(need_motion == Scene::MOTION_BLUR) {
- if(use_motion) {
- transform_motion_decompose(&kcam->motion, &motion, &matrix);
- kcam->have_motion = 1;
+ if(have_motion) {
+ kernel_camera_motion.resize(motion.size());
+ transform_motion_decompose(kernel_camera_motion.data(), motion.data(), motion.size());
+ kcam->num_motion_steps = motion.size();
}
- if(use_perspective_motion) {
- kcam->perspective_motion = perspective_motion;
+
+ /* TODO(sergey): Support other types of camera. */
+ if(use_perspective_motion && type == CAMERA_PERSPECTIVE) {
+ /* TODO(sergey): Move to an utility function and de-duplicate with
+ * calculation above.
+ */
+ ProjectionTransform screentocamera_pre =
+ projection_inverse(projection_perspective(fov_pre,
+ nearclip,
+ farclip));
+ ProjectionTransform screentocamera_post =
+ projection_inverse(projection_perspective(fov_post,
+ nearclip,
+ farclip));
+
+ kcam->perspective_pre = screentocamera_pre * rastertoscreen;
+ kcam->perspective_post = screentocamera_post * rastertoscreen;
kcam->have_perspective_motion = 1;
}
}
@@ -470,6 +475,16 @@ void Camera::device_update(Device * /* device */,
}
dscene->data.cam = kernel_camera;
+
+ size_t num_motion_steps = kernel_camera_motion.size();
+ if(num_motion_steps) {
+ DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps);
+ memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps);
+ dscene->camera_motion.copy_to_device();
+ }
+ else {
+ dscene->camera_motion.free();
+ }
}
void Camera::device_update_volume(Device * /*device*/,
@@ -496,10 +511,11 @@ void Camera::device_update_volume(Device * /*device*/,
}
void Camera::device_free(Device * /*device*/,
- DeviceScene * /*dscene*/,
+ DeviceScene *dscene,
Scene *scene)
{
scene->lookup_tables->remove_table(&shutter_table_offset);
+ dscene->camera_motion.free();
}
bool Camera::modified(const Camera& cam)
@@ -510,7 +526,6 @@ bool Camera::modified(const Camera& cam)
bool Camera::motion_modified(const Camera& cam)
{
return !((motion == cam.motion) &&
- (use_motion == cam.use_motion) &&
(use_perspective_motion == cam.use_perspective_motion));
}
@@ -606,7 +621,7 @@ float Camera::world_to_raster_size(float3 P)
res = min(len(full_dx), len(full_dy));
if(offscreen_dicing_scale > 1.0f) {
- float3 p = transform_perspective(&worldtocamera, P);
+ float3 p = transform_point(&worldtocamera, P);
float3 v = transform_perspective(&rastertocamera, make_float3(width, height, 0.0f));
/* Create point clamped to frustum */
@@ -707,17 +722,17 @@ float Camera::world_to_raster_size(float3 P)
* may be a better way to do this, but calculating differentials from the
* point directly ahead seems to produce good enough results. */
#if 0
- float2 dir = direction_to_panorama(&kernel_camera, normalize(D));
+ float2 dir = direction_to_panorama(&kernel_camera, kernel_camera_motion.data(), normalize(D));
float3 raster = transform_perspective(&cameratoraster, make_float3(dir.x, dir.y, 0.0f));
ray.t = 1.0f;
- camera_sample_panorama(&kernel_camera, raster.x, raster.y, 0.0f, 0.0f, &ray);
+ camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), raster.x, raster.y, 0.0f, 0.0f, &ray);
if(ray.t == 0.0f) {
/* No differentials, just use from directly ahead. */
- camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray);
+ camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray);
}
#else
- camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray);
+ camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray);
#endif
differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist);
@@ -729,4 +744,27 @@ float Camera::world_to_raster_size(float3 P)
return res;
}
+bool Camera::use_motion() const
+{
+ return motion.size() > 1;
+}
+
+float Camera::motion_time(int step) const
+{
+ return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
+}
+
+int Camera::motion_step(float time) const
+{
+ if(use_motion()) {
+ for(int step = 0; step < motion.size(); step++) {
+ if(time == motion_time(step)) {
+ return step;
+ }
+ }
+ }
+
+ return -1;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 4ec0fe3bc6e..37d05c01bd9 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -22,6 +22,7 @@
#include "graph/node.h"
#include "util/util_boundbox.h"
+#include "util/util_projection.h"
#include "util/util_transform.h"
#include "util/util_types.h"
@@ -140,24 +141,23 @@ public:
Transform matrix;
/* motion */
- MotionTransform motion;
- bool use_motion, use_perspective_motion;
+ array<Transform> motion;
+ bool use_perspective_motion;
float fov_pre, fov_post;
- PerspectiveMotionTransform perspective_motion;
/* computed camera parameters */
- Transform screentoworld;
- Transform rastertoworld;
- Transform ndctoworld;
+ ProjectionTransform screentoworld;
+ ProjectionTransform rastertoworld;
+ ProjectionTransform ndctoworld;
Transform cameratoworld;
- Transform worldtoraster;
- Transform worldtoscreen;
- Transform worldtondc;
+ ProjectionTransform worldtoraster;
+ ProjectionTransform worldtoscreen;
+ ProjectionTransform worldtondc;
Transform worldtocamera;
- Transform rastertocamera;
- Transform cameratoraster;
+ ProjectionTransform rastertocamera;
+ ProjectionTransform cameratoraster;
float3 dx;
float3 dy;
@@ -176,6 +176,7 @@ public:
/* Kernel camera data, copied here for dicing. */
KernelCamera kernel_camera;
+ array<DecomposedTransform> kernel_camera_motion;
/* functions */
Camera();
@@ -199,6 +200,11 @@ public:
/* Calculates the width of a pixel at point in world space. */
float world_to_raster_size(float3 P);
+ /* Motion blur. */
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+ bool use_motion() const;
+
private:
/* Private utility functions. */
float3 transform_raster_to_world(float raster_x, float raster_y);
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index b62453cf5fc..8dec7e4ea64 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -288,7 +288,7 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce
VLOG(1) << "Total " << num_distribution << " of light distribution primitives.";
/* emission area */
- float4 *distribution = dscene->light_distribution.alloc(num_distribution + 1);
+ KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
float totarea = 0.0f;
/* triangles */
@@ -334,10 +334,10 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce
: scene->default_surface;
if(shader->use_mis && shader->has_surface_emission) {
- distribution[offset].x = totarea;
- distribution[offset].y = __int_as_float(i + mesh->tri_offset);
- distribution[offset].z = __int_as_float(shader_flag);
- distribution[offset].w = __int_as_float(object_id);
+ distribution[offset].totarea = totarea;
+ distribution[offset].prim = i + mesh->tri_offset;
+ distribution[offset].mesh_light.shader_flag = shader_flag;
+ distribution[offset].mesh_light.object_id = object_id;
offset++;
Mesh::Triangle t = mesh->get_triangle(i);
@@ -372,10 +372,10 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce
if(!light->is_enabled)
continue;
- distribution[offset].x = totarea;
- distribution[offset].y = __int_as_float(~light_index);
- distribution[offset].z = 1.0f;
- distribution[offset].w = light->size;
+ distribution[offset].totarea = totarea;
+ distribution[offset].prim = ~light_index;
+ distribution[offset].lamp.pad = 1.0f;
+ distribution[offset].lamp.size = light->size;
totarea += lightarea;
if(light->size > 0.0f && light->use_mis)
@@ -390,15 +390,15 @@ void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Sce
}
/* normalize cumulative distribution functions */
- distribution[num_distribution].x = totarea;
- distribution[num_distribution].y = 0.0f;
- distribution[num_distribution].z = 0.0f;
- distribution[num_distribution].w = 0.0f;
+ distribution[num_distribution].totarea = totarea;
+ distribution[num_distribution].prim = 0.0f;
+ distribution[num_distribution].lamp.pad = 0.0f;
+ distribution[num_distribution].lamp.size = 0.0f;
if(totarea > 0.0f) {
for(size_t i = 0; i < num_distribution; i++)
- distribution[i].x /= totarea;
- distribution[num_distribution].x = 1.0f;
+ distribution[i].totarea /= totarea;
+ distribution[num_distribution].totarea = 1.0f;
}
if(progress.get_cancel()) return;
@@ -620,7 +620,7 @@ void LightManager::device_update_points(Device *,
}
}
- float4 *light_data = dscene->light_data.alloc(num_lights*LIGHT_SIZE);
+ KernelLight *klights = dscene->lights.alloc(num_lights);
if(num_lights == 0) {
VLOG(1) << "No effective light, ignoring points update.";
@@ -637,8 +637,8 @@ void LightManager::device_update_points(Device *,
float3 co = light->co;
Shader *shader = (light->shader) ? light->shader : scene->default_light;
int shader_id = scene->shader_manager->get_shader_id(shader);
- float samples = __int_as_float(light->samples);
- float max_bounces = __int_as_float(light->max_bounces);
+ int samples = light->samples;
+ int max_bounces = light->max_bounces;
float random = (float)light->random_id * (1.0f/(float)0xFFFFFFFF);
if(!light->cast_shadow)
@@ -661,6 +661,9 @@ void LightManager::device_update_points(Device *,
use_light_visibility = true;
}
+ klights[light_index].type = light->type;
+ klights[light_index].samples = samples;
+
if(light->type == LIGHT_POINT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -670,10 +673,12 @@ void LightManager::device_update_points(Device *,
if(light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
- light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].spot.radius = radius;
+ klights[light_index].spot.invarea = invarea;
}
else if(light->type == LIGHT_DISTANT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -690,10 +695,13 @@ void LightManager::device_update_points(Device *,
if(light->use_mis && area > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
- light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
- light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ klights[light_index].co[0] = dir.x;
+ klights[light_index].co[1] = dir.y;
+ klights[light_index].co[2] = dir.z;
+
+ klights[light_index].distant.invarea = invarea;
+ klights[light_index].distant.radius = radius;
+ klights[light_index].distant.cosangle = cosangle;
}
else if(light->type == LIGHT_BACKGROUND) {
uint visibility = scene->background->visibility;
@@ -717,11 +725,6 @@ void LightManager::device_update_points(Device *,
shader_id |= SHADER_EXCLUDE_SCATTER;
use_light_visibility = true;
}
-
- light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
- light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
- light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_AREA) {
float3 axisu = light->axisu*(light->sizeu*light->size);
@@ -735,10 +738,20 @@ void LightManager::device_update_points(Device *,
if(light->use_mis && area > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
- light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
- light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].area.axisu[0] = axisu.x;
+ klights[light_index].area.axisu[1] = axisu.y;
+ klights[light_index].area.axisu[2] = axisu.z;
+ klights[light_index].area.axisv[0] = axisv.x;
+ klights[light_index].area.axisv[1] = axisv.y;
+ klights[light_index].area.axisv[2] = axisv.z;
+ klights[light_index].area.invarea = invarea;
+ klights[light_index].area.dir[0] = dir.x;
+ klights[light_index].area.dir[1] = dir.y;
+ klights[light_index].area.dir[2] = dir.z;
}
else if(light->type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -754,18 +767,26 @@ void LightManager::device_update_points(Device *,
if(light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
- light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
- light_data[light_index*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
- light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].spot.radius = radius;
+ klights[light_index].spot.invarea = invarea;
+ klights[light_index].spot.spot_angle = spot_angle;
+ klights[light_index].spot.spot_smooth = spot_smooth;
+ klights[light_index].spot.dir[0] = dir.x;
+ klights[light_index].spot.dir[1] = dir.y;
+ klights[light_index].spot.dir[2] = dir.z;
}
- light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, random, 0.0f, 0.0f);
+ klights[light_index].shader_id = shader_id;
+
+ klights[light_index].max_bounces = max_bounces;
+ klights[light_index].random = random;
- Transform tfm = light->tfm;
- Transform itfm = transform_inverse(tfm);
- memcpy(&light_data[light_index*LIGHT_SIZE + 5], &tfm, sizeof(float4)*3);
- memcpy(&light_data[light_index*LIGHT_SIZE + 8], &itfm, sizeof(float4)*3);
+ klights[light_index].tfm = light->tfm;
+ klights[light_index].itfm = transform_inverse(light->tfm);
light_index++;
}
@@ -782,21 +803,27 @@ void LightManager::device_update_points(Device *,
float3 axisu = light->axisu*(light->sizeu*light->size);
float3 axisv = light->axisv*(light->sizev*light->size);
float area = len(axisu)*len(axisv);
- float invarea = (area > 0.0f) ? 1.0f / area : 1.0f;
+ float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
float3 dir = light->dir;
dir = safe_normalize(dir);
- light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
- light_data[light_index*LIGHT_SIZE + 1] = make_float4(area, axisu.x, axisu.y, axisu.z);
- light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
- light_data[light_index*LIGHT_SIZE + 3] = make_float4(-1, dir.x, dir.y, dir.z);
- light_data[light_index*LIGHT_SIZE + 4] = make_float4(-1, 0.0f, 0.0f, 0.0f);
-
- Transform tfm = light->tfm;
- Transform itfm = transform_inverse(tfm);
- memcpy(&light_data[light_index*LIGHT_SIZE + 5], &tfm, sizeof(float4)*3);
- memcpy(&light_data[light_index*LIGHT_SIZE + 8], &itfm, sizeof(float4)*3);
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].area.axisu[0] = axisu.x;
+ klights[light_index].area.axisu[1] = axisu.y;
+ klights[light_index].area.axisu[2] = axisu.z;
+ klights[light_index].area.axisv[0] = axisv.x;
+ klights[light_index].area.axisv[1] = axisv.y;
+ klights[light_index].area.axisv[2] = axisv.z;
+ klights[light_index].area.invarea = invarea;
+ klights[light_index].area.dir[0] = dir.x;
+ klights[light_index].area.dir[1] = dir.y;
+ klights[light_index].area.dir[2] = dir.z;
+ klights[light_index].tfm = light->tfm;
+ klights[light_index].itfm = transform_inverse(light->tfm);
light_index++;
}
@@ -806,7 +833,7 @@ void LightManager::device_update_points(Device *,
VLOG(1) << "Number of lights without contribution: "
<< num_scene_lights - light_index;
- dscene->light_data.copy_to_device();
+ dscene->lights.copy_to_device();
}
void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@@ -842,7 +869,7 @@ void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *sce
void LightManager::device_free(Device *, DeviceScene *dscene)
{
dscene->light_distribution.free();
- dscene->light_data.free();
+ dscene->lights.free();
dscene->light_background_marginal_cdf.free();
dscene->light_background_conditional_cdf.free();
}
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 47d24970949..7cfbb7b7c7d 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -877,15 +877,8 @@ void Mesh::add_undisplaced()
}
}
-void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal)
+void Mesh::pack_shaders(Scene *scene, uint *tri_shader)
{
- Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
- if(attr_vN == NULL) {
- /* Happens on objects with just hair. */
- return;
- }
-
- float3 *vN = attr_vN->data_float3();
uint shader_id = 0;
uint last_shader = -1;
bool last_smooth = false;
@@ -893,10 +886,6 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal)
size_t triangles_size = num_triangles();
int *shader_ptr = shader.data();
- bool do_transform = transform_applied;
- Transform ntfm = transform_normal;
-
- /* save shader */
for(size_t i = 0; i < triangles_size; i++) {
if(shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
last_shader = shader_ptr[i];
@@ -908,7 +897,20 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal)
tri_shader[i] = shader_id;
}
+}
+
+void Mesh::pack_normals(float4 *vnormal)
+{
+ Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
+ if(attr_vN == NULL) {
+ /* Happens on objects with just hair. */
+ return;
+ }
+ bool do_transform = transform_applied;
+ Transform ntfm = transform_normal;
+
+ float3 *vN = attr_vN->data_float3();
size_t verts_size = verts.size();
for(size_t i = 0; i < verts_size; i++) {
@@ -1117,6 +1119,32 @@ bool Mesh::has_true_displacement() const
return false;
}
+float Mesh::motion_time(int step) const
+{
+ return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
+}
+
+int Mesh::motion_step(float time) const
+{
+ if(motion_steps > 1) {
+ int attr_step = 0;
+
+ for(int step = 0; step < motion_steps; step++) {
+ float step_time = motion_time(step);
+ if(step_time == time) {
+ return attr_step;
+ }
+
+ /* Center step is stored in a separate attribute. */
+ if(step != motion_steps / 2) {
+ attr_step++;
+ }
+ }
+ }
+
+ return -1;
+}
+
bool Mesh::need_build_bvh() const
{
return !transform_applied || has_surface_bssrdf;
@@ -1445,11 +1473,11 @@ static void update_attribute_element_offset(Mesh *mesh,
Transform *tfm = mattr->data_transform();
offset = attr_float3_offset;
- assert(attr_float3.size() >= offset + size * 4);
- for(size_t k = 0; k < size*4; k++) {
+ assert(attr_float3.size() >= offset + size * 3);
+ for(size_t k = 0; k < size*3; k++) {
attr_float3[offset+k] = (&tfm->x)[k];
}
- attr_float3_offset += size * 4;
+ attr_float3_offset += size * 3;
}
else {
float4 *data = mattr->data_float4();
@@ -1747,9 +1775,9 @@ void MeshManager::device_update_mesh(Device *,
float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_normals(scene,
- &tri_shader[mesh->tri_offset],
- &vnormal[mesh->vert_offset]);
+ mesh->pack_shaders(scene,
+ &tri_shader[mesh->tri_offset]);
+ mesh->pack_normals(&vnormal[mesh->vert_offset]);
mesh->pack_verts(tri_prim_index,
&tri_vindex[mesh->tri_offset],
&tri_patch[mesh->tri_offset],
@@ -2031,7 +2059,9 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
- /* Update normals. */
+ bool true_displacement_used = false;
+ size_t total_tess_needed = 0;
+
foreach(Mesh *mesh, scene->meshes) {
foreach(Shader *shader, mesh->used_shaders) {
if(shader->need_update_mesh)
@@ -2039,6 +2069,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
}
if(mesh->need_update) {
+ /* Update normals. */
mesh->add_face_normals();
mesh->add_vertex_normals();
@@ -2046,57 +2077,53 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
mesh->add_undisplaced();
}
+ /* Test if we need tesselation. */
+ if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
+ mesh->num_subd_verts == 0 &&
+ mesh->subd_params)
+ {
+ total_tess_needed++;
+ }
+
+ /* Test if we need displacement. */
+ if(mesh->has_true_displacement()) {
+ true_displacement_used = true;
+ }
+
if(progress.get_cancel()) return;
}
}
/* Tessellate meshes that are using subdivision */
- size_t total_tess_needed = 0;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update &&
- mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
- mesh->num_subd_verts == 0 &&
- mesh->subd_params)
- {
- total_tess_needed++;
- }
- }
+ if(total_tess_needed) {
+ size_t i = 0;
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update &&
+ mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
+ mesh->num_subd_verts == 0 &&
+ mesh->subd_params)
+ {
+ string msg = "Tessellating ";
+ if(mesh->name == "")
+ msg += string_printf("%u/%u", (uint)(i+1), (uint)total_tess_needed);
+ else
+ msg += string_printf("%s %u/%u", mesh->name.c_str(), (uint)(i+1), (uint)total_tess_needed);
- size_t i = 0;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update &&
- mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
- mesh->num_subd_verts == 0 &&
- mesh->subd_params)
- {
- string msg = "Tessellating ";
- if(mesh->name == "")
- msg += string_printf("%u/%u", (uint)(i+1), (uint)total_tess_needed);
- else
- msg += string_printf("%s %u/%u", mesh->name.c_str(), (uint)(i+1), (uint)total_tess_needed);
+ progress.set_status("Updating Mesh", msg);
- progress.set_status("Updating Mesh", msg);
+ DiagSplit dsplit(*mesh->subd_params);
+ mesh->tessellate(&dsplit);
- DiagSplit dsplit(*mesh->subd_params);
- mesh->tessellate(&dsplit);
+ i++;
- i++;
+ if(progress.get_cancel()) return;
+ }
- if(progress.get_cancel()) return;
}
}
/* Update images needed for true displacement. */
- bool true_displacement_used = false;
bool old_need_object_flags_update = false;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update &&
- mesh->has_true_displacement())
- {
- true_displacement_used = true;
- break;
- }
- }
if(true_displacement_used) {
VLOG(1) << "Updating images used for true displacement.";
device_update_displacement_images(device, scene, progress);
@@ -2122,11 +2149,17 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
/* Update displacement. */
bool displacement_done = false;
+ size_t num_bvh = 0;
+
foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update &&
- displace(device, dscene, scene, mesh, progress))
- {
- displacement_done = true;
+ if(mesh->need_update) {
+ if(displace(device, dscene, scene, mesh, progress)) {
+ displacement_done = true;
+ }
+
+ if(mesh->need_build_bvh()) {
+ num_bvh++;
+ }
}
}
@@ -2141,17 +2174,9 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
if(progress.get_cancel()) return;
}
- /* Update bvh. */
- size_t num_bvh = 0;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update && mesh->need_build_bvh()) {
- num_bvh++;
- }
- }
-
TaskPool pool;
- i = 0;
+ size_t i = 0;
foreach(Mesh *mesh, scene->meshes) {
if(mesh->need_update) {
pool.push(function_bind(&Mesh::compute_bvh,
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index c0d1513bee0..e370f8a2021 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -279,7 +279,8 @@ public:
void add_vertex_normals();
void add_undisplaced();
- void pack_normals(Scene *scene, uint *shader, float4 *vnormal);
+ void pack_shaders(Scene *scene, uint *shader);
+ void pack_normals(float4 *vnormal);
void pack_verts(const vector<uint>& tri_prim_index,
uint4 *tri_vindex,
uint *tri_patch,
@@ -304,6 +305,11 @@ public:
bool has_motion_blur() const;
bool has_true_displacement() const;
+ /* Convert between normalized -1..1 motion time and index
+ * in the VERTEX_MOTION attribute. */
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+
/* Check whether the mesh should have own BVH built separately. Briefly,
* own BVH is needed for mesh, if:
*
diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp
index f2347c79610..3571beb40d6 100644
--- a/intern/cycles/render/mesh_volume.cpp
+++ b/intern/cycles/render/mesh_volume.cpp
@@ -152,22 +152,22 @@ public:
void add_node_with_padding(int x, int y, int z);
void create_mesh(vector<float3> &vertices,
- vector<int> &indices,
- vector<float3> &face_normals);
+ vector<int> &indices,
+ vector<float3> &face_normals);
private:
void generate_vertices_and_quads(vector<int3> &vertices_is,
- vector<QuadData> &quads);
+ vector<QuadData> &quads);
void deduplicate_vertices(vector<int3> &vertices,
- vector<QuadData> &quads);
+ vector<QuadData> &quads);
void convert_object_space(const vector<int3> &vertices,
- vector<float3> &out_vertices);
+ vector<float3> &out_vertices);
void convert_quads_to_tris(const vector<QuadData> &quads,
- vector<int> &tris,
- vector<float3> &face_normals);
+ vector<int> &tris,
+ vector<float3> &face_normals);
};
VolumeMeshBuilder::VolumeMeshBuilder(VolumeParams *volume_params)
@@ -224,8 +224,8 @@ void VolumeMeshBuilder::add_node_with_padding(int x, int y, int z)
}
void VolumeMeshBuilder::create_mesh(vector<float3> &vertices,
- vector<int> &indices,
- vector<float3> &face_normals)
+ vector<int> &indices,
+ vector<float3> &face_normals)
{
/* We create vertices in index space (is), and only convert them to object
* space when done. */
@@ -260,8 +260,8 @@ void VolumeMeshBuilder::generate_vertices_and_quads(
/* Compute min and max coords of the node in index space. */
int3 min = make_int3((x - pad_offset.x)*CUBE_SIZE,
- (y - pad_offset.y)*CUBE_SIZE,
- (z - pad_offset.z)*CUBE_SIZE);
+ (y - pad_offset.y)*CUBE_SIZE,
+ (z - pad_offset.z)*CUBE_SIZE);
/* Maximum is just CUBE_SIZE voxels away from minimum on each axis. */
int3 max = make_int3(min.x + CUBE_SIZE, min.y + CUBE_SIZE, min.z + CUBE_SIZE);
@@ -316,7 +316,7 @@ void VolumeMeshBuilder::generate_vertices_and_quads(
}
void VolumeMeshBuilder::deduplicate_vertices(vector<int3> &vertices,
- vector<QuadData> &quads)
+ vector<QuadData> &quads)
{
vector<int3> sorted_vertices = vertices;
std::sort(sorted_vertices.begin(), sorted_vertices.end());
@@ -355,7 +355,7 @@ void VolumeMeshBuilder::deduplicate_vertices(vector<int3> &vertices,
}
void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices,
- vector<float3> &out_vertices)
+ vector<float3> &out_vertices)
{
out_vertices.reserve(vertices.size());
@@ -369,8 +369,8 @@ void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices,
}
void VolumeMeshBuilder::convert_quads_to_tris(const vector<QuadData> &quads,
- vector<int> &tris,
- vector<float3> &face_normals)
+ vector<int> &tris,
+ vector<float3> &face_normals)
{
int index_offset = 0;
tris.resize(quads.size()*6);
@@ -399,8 +399,8 @@ struct VoxelAttributeGrid {
};
void MeshManager::create_volume_mesh(Scene *scene,
- Mesh *mesh,
- Progress& progress)
+ Mesh *mesh,
+ Progress& progress)
{
string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str());
progress.set_status("Updating Mesh", msg);
@@ -470,8 +470,8 @@ void MeshManager::create_volume_mesh(Scene *scene,
const int3 resolution = volume_params.resolution;
float3 start_point = make_float3(0.0f, 0.0f, 0.0f);
float3 cell_size = make_float3(1.0f/resolution.x,
- 1.0f/resolution.y,
- 1.0f/resolution.z);
+ 1.0f/resolution.y,
+ 1.0f/resolution.z);
if(attr) {
const Transform *tfm = attr->data_transform();
@@ -575,12 +575,12 @@ void MeshManager::create_volume_mesh(Scene *scene,
/* Print stats. */
VLOG(1) << "Memory usage volume mesh: "
- << ((vertices.size() + face_normals.size())*sizeof(float3) + indices.size()*sizeof(int))/(1024.0*1024.0)
- << "Mb.";
+ << ((vertices.size() + face_normals.size())*sizeof(float3) + indices.size()*sizeof(int))/(1024.0*1024.0)
+ << "Mb.";
VLOG(1) << "Memory usage volume grid: "
- << (resolution.x*resolution.y*resolution.z*sizeof(float))/(1024.0*1024.0)
- << "Mb.";
+ << (resolution.x*resolution.y*resolution.z*sizeof(float))/(1024.0*1024.0)
+ << "Mb.";
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 41c9730e6fb..f117962a2ea 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -117,8 +117,7 @@ Transform TextureMapping::compute_transform()
case NORMAL:
/* no translation for normals, and inverse transpose */
mat = rmat*smat;
- mat = transform_inverse(mat);
- mat = transform_transpose(mat);
+ mat = transform_transposed_inverse(mat);
break;
}
@@ -153,7 +152,6 @@ void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_ou
compiler.add_node(tfm.x);
compiler.add_node(tfm.y);
compiler.add_node(tfm.z);
- compiler.add_node(tfm.w);
if(use_minmax) {
compiler.add_node(NODE_MIN_MAX, offset_out, offset_out);
@@ -193,9 +191,7 @@ void TextureMapping::compile_end(SVMCompiler& compiler, ShaderInput *vector_in,
void TextureMapping::compile(OSLCompiler &compiler)
{
if(!skip()) {
- Transform tfm = transform_transpose(compute_transform());
-
- compiler.parameter("mapping", tfm);
+ compiler.parameter("mapping", compute_transform());
compiler.parameter("use_mapping", 1);
}
}
@@ -1434,7 +1430,6 @@ void PointDensityTextureNode::compile(SVMCompiler& compiler)
compiler.add_node(tfm.x);
compiler.add_node(tfm.y);
compiler.add_node(tfm.z);
- compiler.add_node(tfm.w);
}
}
else {
@@ -1478,7 +1473,7 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler)
compiler.parameter("filename", string_printf("@%d", slot).c_str());
}
if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
- compiler.parameter("mapping", transform_transpose(tfm));
+ compiler.parameter("mapping", tfm);
compiler.parameter("use_mapping", 1);
}
compiler.parameter(this, "interpolation");
@@ -1558,8 +1553,7 @@ void MappingNode::compile(SVMCompiler& compiler)
void MappingNode::compile(OSLCompiler& compiler)
{
- Transform tfm = transform_transpose(tex_mapping.compute_transform());
- compiler.parameter("Matrix", tfm);
+ compiler.parameter("Matrix", tex_mapping.compute_transform());
compiler.parameter_point("mapping_min", tex_mapping.min);
compiler.parameter_point("mapping_max", tex_mapping.max);
compiler.parameter("use_minmax", tex_mapping.use_minmax);
@@ -3220,7 +3214,6 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler)
compiler.add_node(ob_itfm.x);
compiler.add_node(ob_itfm.y);
compiler.add_node(ob_itfm.z);
- compiler.add_node(ob_itfm.w);
}
}
@@ -3259,7 +3252,7 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler)
if(compiler.output_type() == SHADER_TYPE_VOLUME)
compiler.parameter("is_volume", true);
compiler.parameter(this, "use_transform");
- Transform ob_itfm = transform_transpose(transform_inverse(ob_tfm));
+ Transform ob_itfm = transform_transposed_inverse(ob_tfm);
compiler.parameter("object_itfm", ob_itfm);
compiler.parameter(this, "from_dupli");
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index b981d2b8849..138de250c5f 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -33,6 +33,52 @@
CCL_NAMESPACE_BEGIN
+/* Global state of object transform update. */
+
+struct UpdateObjectTransformState {
+ /* Global state used by device_update_object_transform().
+ * Common for both threaded and non-threaded update.
+ */
+
+ /* Type of the motion required by the scene settings. */
+ Scene::MotionType need_motion;
+
+ /* Mapping from particle system to a index in packed particle array.
+ * Only used for read.
+ */
+ map<ParticleSystem*, int> particle_offset;
+
+ /* Mesh area.
+ * Used to avoid calculation of mesh area multiple times. Used for both
+ * read and write. Acquire surface_area_lock to keep it all thread safe.
+ */
+ map<Mesh*, float> surface_area_map;
+
+ /* Motion offsets for each object. */
+ array<uint> motion_offset;
+
+ /* Packed object arrays. Those will be filled in. */
+ uint *object_flag;
+ KernelObject *objects;
+ Transform *object_motion_pass;
+ DecomposedTransform *object_motion;
+
+ /* Flags which will be synchronized to Integrator. */
+ bool have_motion;
+ bool have_curves;
+
+ /* ** Scheduling queue. ** */
+
+ Scene *scene;
+
+ /* Some locks to keep everything thread-safe. */
+ thread_spin_lock queue_lock;
+ thread_spin_lock surface_area_lock;
+
+ /* First unused object index in the queue. */
+ int queue_start_object;
+};
+
/* Object */
NODE_DEFINE(Object)
@@ -48,6 +94,7 @@ NODE_DEFINE(Object)
SOCKET_BOOLEAN(hide_on_missing_motion, "Hide on Missing Motion", false);
SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
+ SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
@@ -60,45 +107,54 @@ Object::Object()
particle_system = NULL;
particle_index = 0;
bounds = BoundBox::empty;
- motion.pre = transform_empty();
- motion.mid = transform_empty();
- motion.post = transform_empty();
- use_motion = false;
}
Object::~Object()
{
}
-void Object::compute_bounds(bool motion_blur)
+void Object::update_motion()
{
- BoundBox mbounds = mesh->bounds;
+ if(!use_motion()) {
+ return;
+ }
- if(motion_blur && use_motion) {
- MotionTransform mtfm = motion;
+ bool have_motion = false;
- if(hide_on_missing_motion) {
- /* Hide objects that have no valid previous or next transform, for
- * example particle that stop existing. TODO: add support for this
- * case in the kernel so we don't get render artifacts. */
- if(mtfm.pre == transform_empty() ||
- mtfm.post == transform_empty()) {
- bounds = BoundBox::empty;
+ for(size_t i = 0; i < motion.size(); i++) {
+ if(motion[i] == transform_empty()) {
+ if(hide_on_missing_motion) {
+ /* Hide objects that have no valid previous or next
+ * transform, for example particle that stop existing. It
+ * would be better to handle this in the kernel and make
+ * objects invisible outside certain motion steps. */
+ tfm = transform_empty();
+ motion.clear();
return;
}
+ else {
+ /* Otherwise just copy center motion. */
+ motion[i] = tfm;
+ }
}
- /* In case of missing motion information for previous/next frame,
- * assume there is no motion. */
- if(mtfm.pre == transform_empty()) {
- mtfm.pre = tfm;
- }
- if(mtfm.post == transform_empty()) {
- mtfm.post = tfm;
- }
+ /* Test if any of the transforms are actually different. */
+ have_motion = have_motion || motion[i] != tfm;
+ }
- MotionTransform decomp;
- transform_motion_decompose(&decomp, &mtfm, &tfm);
+ /* Clear motion array if there is no actual motion. */
+ if(!have_motion) {
+ motion.clear();
+ }
+}
+
+void Object::compute_bounds(bool motion_blur)
+{
+ BoundBox mbounds = mesh->bounds;
+
+ if(motion_blur && use_motion()) {
+ array<DecomposedTransform> decomp(motion.size());
+ transform_motion_decompose(decomp.data(), motion.data(), motion.size());
bounds = BoundBox::empty;
@@ -108,11 +164,12 @@ void Object::compute_bounds(bool motion_blur)
for(float t = 0.0f; t < 1.0f; t += (1.0f/128.0f)) {
Transform ttfm;
- transform_motion_interpolate(&ttfm, &decomp, t);
+ transform_motion_array_interpolate(&ttfm, decomp.data(), motion.size(), t);
bounds.grow(mbounds.transformed(&ttfm));
}
}
else {
+ /* No motion blur case. */
if(mesh->transform_applied) {
bounds = mbounds;
}
@@ -132,7 +189,7 @@ void Object::apply_transform(bool apply_to_motion)
/* store matrix to transform later. when accessing these as attributes we
* do not want the transform to be applied for consistency between static
* and dynamic BVH, so we do it on packing. */
- mesh->transform_normal = transform_transpose(transform_inverse(tfm));
+ mesh->transform_normal = transform_transposed_inverse(tfm);
/* apply to mesh vertices */
for(size_t i = 0; i < mesh->verts.size(); i++)
@@ -232,27 +289,30 @@ void Object::tag_update(Scene *scene)
scene->object_manager->need_update = true;
}
-vector<float> Object::motion_times()
+bool Object::use_motion() const
{
- /* compute times at which we sample motion for this object */
- vector<float> times;
-
- if(!mesh || mesh->motion_steps == 1)
- return times;
+ return (motion.size() > 1);
+}
- int motion_steps = mesh->motion_steps;
+float Object::motion_time(int step) const
+{
+ return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
+}
- for(int step = 0; step < motion_steps; step++) {
- if(step != motion_steps / 2) {
- float time = 2.0f * step / (motion_steps - 1) - 1.0f;
- times.push_back(time);
+int Object::motion_step(float time) const
+{
+ if(use_motion()) {
+ for(size_t step = 0; step < motion.size(); step++) {
+ if(time == motion_time(step)) {
+ return step;
+ }
}
}
- return times;
+ return -1;
}
-bool Object::is_traceable()
+bool Object::is_traceable() const
{
/* Mesh itself can be empty,can skip all such objects. */
if(!bounds.valid() || bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) {
@@ -289,8 +349,8 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
Object *ob,
int object_index)
{
- float4 *objects = state->objects;
- float4 *objects_vector = state->objects_vector;
+ KernelObject& kobject = state->objects[object_index];
+ Transform *object_motion_pass = state->object_motion_pass;
Mesh *mesh = ob->mesh;
uint flag = 0;
@@ -357,15 +417,13 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
}
}
- /* Pack in texture. */
- int offset = object_index*OBJECT_SIZE;
-
- /* OBJECT_TRANSFORM */
- memcpy(&objects[offset], &tfm, sizeof(float4)*3);
- /* OBJECT_INVERSE_TRANSFORM */
- memcpy(&objects[offset+4], &itfm, sizeof(float4)*3);
- /* OBJECT_PROPERTIES */
- objects[offset+12] = make_float4(surface_area, pass_id, random_number, __int_as_float(particle_index));
+ kobject.tfm = tfm;
+ kobject.itfm = itfm;
+ kobject.surface_area = surface_area;
+ kobject.pass_id = pass_id;
+ kobject.random_number = random_number;
+ kobject.particle_index = particle_index;
+ kobject.motion_offset = 0;
if(mesh->use_motion_blur) {
state->have_motion = true;
@@ -375,50 +433,56 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
}
if(state->need_motion == Scene::MOTION_PASS) {
- /* Motion transformations, is world/object space depending if mesh
- * comes with deformed position in object space, or if we transform
- * the shading point in world space.
- */
- MotionTransform mtfm = ob->motion;
+ /* Clear motion array if there is no actual motion. */
+ ob->update_motion();
- /* In case of missing motion information for previous/next frame,
- * assume there is no motion. */
- if(!ob->use_motion || mtfm.pre == transform_empty()) {
- mtfm.pre = ob->tfm;
+ /* Compute motion transforms. */
+ Transform tfm_pre, tfm_post;
+ if(ob->use_motion()) {
+ tfm_pre = ob->motion[0];
+ tfm_post = ob->motion[ob->motion.size() - 1];
}
- if(!ob->use_motion || mtfm.post == transform_empty()) {
- mtfm.post = ob->tfm;
+ else {
+ tfm_pre = tfm;
+ tfm_post = tfm;
}
+ /* Motion transformations, is world/object space depending if mesh
+ * comes with deformed position in object space, or if we transform
+ * the shading point in world space. */
if(!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
- mtfm.pre = mtfm.pre * itfm;
- mtfm.post = mtfm.post * itfm;
+ tfm_pre = tfm_pre * itfm;
+ tfm_post = tfm_post * itfm;
}
- memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+0], &mtfm.pre, sizeof(float4)*3);
- memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+3], &mtfm.post, sizeof(float4)*3);
+ int motion_pass_offset = object_index*OBJECT_MOTION_PASS_SIZE;
+ object_motion_pass[motion_pass_offset + 0] = tfm_pre;
+ object_motion_pass[motion_pass_offset + 1] = tfm_post;
}
else if(state->need_motion == Scene::MOTION_BLUR) {
- if(ob->use_motion) {
- /* decompose transformations for interpolation. */
- MotionTransform decomp;
+ if(ob->use_motion()) {
+ kobject.motion_offset = state->motion_offset[object_index];
- transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
- memcpy(&objects[offset], &decomp, sizeof(float4)*12);
+ /* Decompose transforms for interpolation. */
+ DecomposedTransform *decomp = state->object_motion + kobject.motion_offset;
+ transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size());
flag |= SD_OBJECT_MOTION;
state->have_motion = true;
}
}
/* Dupli object coords and motion info. */
+ kobject.dupli_generated[0] = ob->dupli_generated[0];
+ kobject.dupli_generated[1] = ob->dupli_generated[1];
+ kobject.dupli_generated[2] = ob->dupli_generated[2];
+ kobject.numkeys = mesh->curve_keys.size();
+ kobject.dupli_uv[0] = ob->dupli_uv[0];
+ kobject.dupli_uv[1] = ob->dupli_uv[1];
int totalsteps = mesh->motion_steps;
- int numsteps = (totalsteps - 1)/2;
- int numverts = mesh->verts.size();
- int numkeys = mesh->curve_keys.size();
-
- objects[offset+13] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], __int_as_float(numkeys));
- objects[offset+14] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], __int_as_float(numsteps), __int_as_float(numverts));
- objects[offset+15] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ kobject.numsteps = (totalsteps - 1)/2;
+ kobject.numverts = mesh->verts.size();;
+ kobject.patch_map_offset = 0;
+ kobject.attribute_map_offset = 0;
/* Object flag. */
if(ob->use_holdout) {
@@ -475,7 +539,6 @@ void ObjectManager::device_update_object_transform_task(
void ObjectManager::device_update_transforms(DeviceScene *dscene,
Scene *scene,
- uint *object_flag,
Progress& progress)
{
UpdateObjectTransformState state;
@@ -485,13 +548,29 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene,
state.scene = scene;
state.queue_start_object = 0;
- state.object_flag = object_flag;
- state.objects = dscene->objects.alloc(OBJECT_SIZE*scene->objects.size());
+ state.objects = dscene->objects.alloc(scene->objects.size());
+ state.object_flag = dscene->object_flag.alloc(scene->objects.size());
+ state.object_motion = NULL;
+ state.object_motion_pass = NULL;
+
if(state.need_motion == Scene::MOTION_PASS) {
- state.objects_vector = dscene->objects_vector.alloc(OBJECT_VECTOR_SIZE*scene->objects.size());
+ state.object_motion_pass = dscene->object_motion_pass.alloc(OBJECT_MOTION_PASS_SIZE*scene->objects.size());
}
- else {
- state.objects_vector = NULL;
+ else if(state.need_motion == Scene::MOTION_BLUR) {
+ /* Set object offsets into global object motion array. */
+ uint *motion_offsets = state.motion_offset.resize(scene->objects.size());
+ uint motion_offset = 0;
+
+ foreach(Object *ob, scene->objects) {
+ *motion_offsets = motion_offset;
+ motion_offsets++;
+
+ /* Clear motion array if there is no actual motion. */
+ ob->update_motion();
+ motion_offset += ob->motion.size();
+ }
+
+ state.object_motion = dscene->object_motion.alloc(motion_offset);
}
/* Particle system device offsets
@@ -534,7 +613,10 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene,
dscene->objects.copy_to_device();
if(state.need_motion == Scene::MOTION_PASS) {
- dscene->objects_vector.copy_to_device();
+ dscene->object_motion_pass.copy_to_device();
+ }
+ else if(state.need_motion == Scene::MOTION_BLUR) {
+ dscene->object_motion.copy_to_device();
}
dscene->data.bvh.have_motion = state.have_motion;
@@ -554,12 +636,9 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
if(scene->objects.size() == 0)
return;
- /* object info flag */
- uint *object_flag = dscene->object_flag.alloc(scene->objects.size());
-
/* set object transform matrices, before applying static transforms */
progress.set_status("Updating Objects", "Copying Transformations to device");
- device_update_transforms(dscene, scene, object_flag, progress);
+ device_update_transforms(dscene, scene, progress);
if(progress.get_cancel()) return;
@@ -567,7 +646,7 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
/* todo: do before to support getting object level coords? */
if(scene->params.bvh_type == SceneParams::BVH_STATIC) {
progress.set_status("Updating Objects", "Applying Static Transformations");
- apply_static_transforms(dscene, scene, object_flag, progress);
+ apply_static_transforms(dscene, scene, progress);
}
}
@@ -586,9 +665,10 @@ void ObjectManager::device_update_flags(Device *,
if(scene->objects.size() == 0)
return;
- /* object info flag */
+ /* Object info flag. */
uint *object_flag = dscene->object_flag.data();
+ /* Object volume intersection. */
vector<Object *> volume_objects;
bool has_volume_objects = false;
foreach(Object *object, scene->objects) {
@@ -642,7 +722,7 @@ void ObjectManager::device_update_flags(Device *,
++object_index;
}
- /* allocate object flag */
+ /* Copy object flag. */
dscene->object_flag.copy_to_device();
}
@@ -652,27 +732,26 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc
return;
}
- uint4* objects = (uint4*)dscene->objects.data();
+ KernelObject *kobjects = dscene->objects.data();
bool update = false;
int object_index = 0;
foreach(Object *object, scene->objects) {
Mesh* mesh = object->mesh;
- int offset = object_index*OBJECT_SIZE + 15;
if(mesh->patch_table) {
uint patch_map_offset = 2*(mesh->patch_table_offset + mesh->patch_table->total_size() -
mesh->patch_table->num_nodes * PATCH_NODE_SIZE) - mesh->patch_offset;
- if(objects[offset].x != patch_map_offset) {
- objects[offset].x = patch_map_offset;
+ if(kobjects[object_index].patch_map_offset != patch_map_offset) {
+ kobjects[object_index].patch_map_offset = patch_map_offset;
update = true;
}
}
- if(objects[offset].y != mesh->attr_map_offset) {
- objects[offset].y = mesh->attr_map_offset;
+ if(kobjects[object_index].attribute_map_offset != mesh->attr_map_offset) {
+ kobjects[object_index].attribute_map_offset = mesh->attr_map_offset;
update = true;
}
@@ -687,11 +766,12 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc
void ObjectManager::device_free(Device *, DeviceScene *dscene)
{
dscene->objects.free();
- dscene->objects_vector.free();
+ dscene->object_motion_pass.free();
+ dscene->object_motion.free();
dscene->object_flag.free();
}
-void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress)
+void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress)
{
/* todo: normals and displacement should be done before applying transform! */
/* todo: create objects/meshes in right order! */
@@ -715,6 +795,8 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u
if(progress.get_cancel()) return;
+ uint *object_flag = dscene->object_flag.data();
+
/* apply transforms for objects with single user meshes */
foreach(Object *object, scene->objects) {
/* Annoying feedback loop here: we can't use is_instanced() because
@@ -725,7 +807,7 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, u
if((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) &&
!object->mesh->has_true_displacement() && object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE)
{
- if(!(motion_blur && object->use_motion)) {
+ if(!(motion_blur && object->use_motion())) {
if(!object->mesh->transform_applied) {
object->apply_transform(apply_to_motion);
object->mesh->transform_applied = true;
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index acdb1b64123..c7212ae25f9 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -35,6 +35,7 @@ class ParticleSystem;
class Progress;
class Scene;
struct Transform;
+struct UpdateObjectTransformState;
/* Object */
@@ -49,8 +50,7 @@ public:
int pass_id;
vector<ParamValue> attributes;
uint visibility;
- MotionTransform motion;
- bool use_motion;
+ array<Transform> motion;
bool hide_on_missing_motion;
bool use_holdout;
bool is_shadow_catcher;
@@ -69,12 +69,17 @@ public:
void compute_bounds(bool motion_blur);
void apply_transform(bool apply_to_motion);
- vector<float> motion_times();
+ /* Convert between normalized -1..1 motion time and index
+ * in the motion array. */
+ bool use_motion() const;
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+ void update_motion();
/* Check whether object is traceable and it worth adding it to
* kernel scene.
*/
- bool is_traceable();
+ bool is_traceable() const;
/* Combine object's visibility with all possible internal run-time
* determined flags which denotes trace-time visibility.
@@ -95,7 +100,6 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_transforms(DeviceScene *dscene,
Scene *scene,
- uint *object_flag,
Progress& progress);
void device_update_flags(Device *device,
@@ -109,49 +113,9 @@ public:
void tag_update(Scene *scene);
- void apply_static_transforms(DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress);
+ void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress);
protected:
- /* Global state of object transform update. */
- struct UpdateObjectTransformState {
- /* Global state used by device_update_object_transform().
- * Common for both threaded and non-threaded update.
- */
-
- /* Type of the motion required by the scene settings. */
- Scene::MotionType need_motion;
-
- /* Mapping from particle system to a index in packed particle array.
- * Only used for read.
- */
- map<ParticleSystem*, int> particle_offset;
-
- /* Mesh area.
- * Used to avoid calculation of mesh area multiple times. Used for both
- * read and write. Acquire surface_area_lock to keep it all thread safe.
- */
- map<Mesh*, float> surface_area_map;
-
- /* Packed object arrays. Those will be filled in. */
- uint *object_flag;
- float4 *objects;
- float4 *objects_vector;
-
- /* Flags which will be synchronized to Integrator. */
- bool have_motion;
- bool have_curves;
-
- /* ** Scheduling queue. ** */
-
- Scene *scene;
-
- /* Some locks to keep everything thread-safe. */
- thread_spin_lock queue_lock;
- thread_spin_lock surface_area_lock;
-
- /* First unused object index in the queue. */
- int queue_start_object;
- };
void device_update_object_transform(UpdateObjectTransformState *state,
Object *ob,
const int object_index);
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 9e931280691..f1a22350060 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -34,6 +34,7 @@
#include "util/util_md5.h"
#include "util/util_path.h"
#include "util/util_progress.h"
+#include "util/util_projection.h"
#endif
@@ -832,7 +833,9 @@ void OSLCompiler::parameter(ShaderNode* node, const char *name)
case SocketType::TRANSFORM:
{
Transform value = node->get_transform(socket);
- ss->Parameter(uname, TypeDesc::TypeMatrix, &value);
+ ProjectionTransform projection(value);
+ projection = projection_transpose(projection);
+ ss->Parameter(uname, TypeDesc::TypeMatrix, &projection);
break;
}
case SocketType::BOOLEAN_ARRAY:
@@ -900,7 +903,11 @@ void OSLCompiler::parameter(ShaderNode* node, const char *name)
case SocketType::TRANSFORM_ARRAY:
{
const array<Transform>& value = node->get_transform_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, value.size()), value.data());
+ array<ProjectionTransform> fvalue(value.size());
+ for(size_t i = 0; i < value.size(); i++) {
+ fvalue[i] = projection_transpose(ProjectionTransform(value[i]));
+ }
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, fvalue.size()), fvalue.data());
break;
}
case SocketType::CLOSURE:
@@ -967,7 +974,9 @@ void OSLCompiler::parameter(const char *name, ustring s)
void OSLCompiler::parameter(const char *name, const Transform& tfm)
{
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&tfm);
+ ProjectionTransform projection(tfm);
+ projection = projection_transpose(projection);
+ ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&projection);
}
void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 3ee620c9d01..e4be3306d7e 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -62,14 +62,10 @@ void ParticleSystemManager::device_update_particles(Device *, DeviceScene *dscen
for(size_t j = 0; j < scene->particle_systems.size(); j++)
num_particles += scene->particle_systems[j]->particles.size();
- float4 *particles = dscene->particles.alloc(PARTICLE_SIZE*num_particles);
+ KernelParticle *kparticles = dscene->particles.alloc(num_particles);
/* dummy particle */
- particles[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- particles[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- particles[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- particles[3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- particles[4] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ memset(kparticles, 0, sizeof(KernelParticle));
int i = 1;
for(size_t j = 0; j < scene->particle_systems.size(); j++) {
@@ -78,13 +74,15 @@ void ParticleSystemManager::device_update_particles(Device *, DeviceScene *dscen
for(size_t k = 0; k < psys->particles.size(); k++) {
/* pack in texture */
Particle& pa = psys->particles[k];
- int offset = i*PARTICLE_SIZE;
- particles[offset] = make_float4(__uint_as_float(pa.index), pa.age, pa.lifetime, pa.size);
- particles[offset+1] = pa.rotation;
- particles[offset+2] = make_float4(pa.location.x, pa.location.y, pa.location.z, pa.velocity.x);
- particles[offset+3] = make_float4(pa.velocity.y, pa.velocity.z, pa.angular_velocity.x, pa.angular_velocity.y);
- particles[offset+4] = make_float4(pa.angular_velocity.z, 0.0f, 0.0f, 0.0f);
+ kparticles[i].index = pa.index;
+ kparticles[i].age = pa.age;
+ kparticles[i].lifetime = pa.lifetime;
+ kparticles[i].size = pa.size;
+ kparticles[i].rotation = pa.rotation;
+ kparticles[i].location = float3_to_float4(pa.location);
+ kparticles[i].velocity = float3_to_float4(pa.velocity);
+ kparticles[i].angular_velocity = float3_to_float4(pa.angular_velocity);
i++;
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 24923b650e3..ba47e3ab6f8 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -60,19 +60,21 @@ DeviceScene::DeviceScene(Device *device)
curve_keys(device, "__curve_keys", MEM_TEXTURE),
patches(device, "__patches", MEM_TEXTURE),
objects(device, "__objects", MEM_TEXTURE),
- objects_vector(device, "__objects_vector", MEM_TEXTURE),
+ object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE),
+ object_motion(device, "__object_motion", MEM_TEXTURE),
+ object_flag(device, "__object_flag", MEM_TEXTURE),
+ camera_motion(device, "__camera_motion", MEM_TEXTURE),
attributes_map(device, "__attributes_map", MEM_TEXTURE),
attributes_float(device, "__attributes_float", MEM_TEXTURE),
attributes_float3(device, "__attributes_float3", MEM_TEXTURE),
attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE),
light_distribution(device, "__light_distribution", MEM_TEXTURE),
- light_data(device, "__light_data", MEM_TEXTURE),
+ lights(device, "__lights", MEM_TEXTURE),
light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_TEXTURE),
light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_TEXTURE),
particles(device, "__particles", MEM_TEXTURE),
svm_nodes(device, "__svm_nodes", MEM_TEXTURE),
- shader_flag(device, "__shader_flag", MEM_TEXTURE),
- object_flag(device, "__object_flag", MEM_TEXTURE),
+ shaders(device, "__shaders", MEM_TEXTURE),
lookup_table(device, "__lookup_table", MEM_TEXTURE),
sobol_directions(device, "__sobol_directions", MEM_TEXTURE)
{
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index ea9485ff230..04bd4735a86 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -86,8 +86,13 @@ public:
device_vector<uint> patches;
/* objects */
- device_vector<float4> objects;
- device_vector<float4> objects_vector;
+ device_vector<KernelObject> objects;
+ device_vector<Transform> object_motion_pass;
+ device_vector<DecomposedTransform> object_motion;
+ device_vector<uint> object_flag;
+
+ /* cameras */
+ device_vector<DecomposedTransform> camera_motion;
/* attributes */
device_vector<uint4> attributes_map;
@@ -96,18 +101,17 @@ public:
device_vector<uchar4> attributes_uchar4;
/* lights */
- device_vector<float4> light_distribution;
- device_vector<float4> light_data;
+ device_vector<KernelLightDistribution> light_distribution;
+ device_vector<KernelLight> lights;
device_vector<float2> light_background_marginal_cdf;
device_vector<float2> light_background_conditional_cdf;
/* particles */
- device_vector<float4> particles;
+ device_vector<KernelParticle> particles;
/* shaders */
device_vector<int4> svm_nodes;
- device_vector<uint> shader_flag;
- device_vector<uint> object_flag;
+ device_vector<KernelShader> shaders;
/* lookup tables */
device_vector<float> lookup_table;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index e8d9558c38d..41156038558 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -656,13 +656,13 @@ DeviceRequestedFeatures Session::get_requested_device_features()
*/
requested_features.use_hair = false;
requested_features.use_object_motion = false;
- requested_features.use_camera_motion = scene->camera->use_motion;
+ requested_features.use_camera_motion = scene->camera->use_motion();
foreach(Object *object, scene->objects) {
Mesh *mesh = object->mesh;
if(mesh->num_curves()) {
requested_features.use_hair = true;
}
- requested_features.use_object_motion |= object->use_motion | mesh->use_motion_blur;
+ requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur;
requested_features.use_camera_motion |= mesh->use_motion_blur;
#ifdef WITH_OPENSUBDIV
if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 578c61a3e79..ec52c51e337 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -432,14 +432,12 @@ void ShaderManager::device_update_common(Device *device,
Scene *scene,
Progress& /*progress*/)
{
- dscene->shader_flag.free();
+ dscene->shaders.free();
if(scene->shaders.size() == 0)
return;
- uint shader_flag_size = scene->shaders.size()*SHADER_SIZE;
- uint *shader_flag = dscene->shader_flag.alloc(shader_flag_size);
- uint i = 0;
+ KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
bool has_volumes = false;
bool has_transparent_shadow = false;
@@ -487,16 +485,17 @@ void ShaderManager::device_update_common(Device *device,
flag |= SD_HAS_CONSTANT_EMISSION;
/* regular shader */
- shader_flag[i++] = flag;
- shader_flag[i++] = shader->pass_id;
- shader_flag[i++] = __float_as_int(constant_emission.x);
- shader_flag[i++] = __float_as_int(constant_emission.y);
- shader_flag[i++] = __float_as_int(constant_emission.z);
+ kshader->flags = flag;
+ kshader->pass_id = shader->pass_id;
+ kshader->constant_emission[0] = constant_emission.x;
+ kshader->constant_emission[1] = constant_emission.y;
+ kshader->constant_emission[2] = constant_emission.z;
+ kshader++;
has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
}
- dscene->shader_flag.copy_to_device();
+ dscene->shaders.copy_to_device();
/* lookup tables */
KernelTables *ktables = &dscene->data.tables;
@@ -525,7 +524,7 @@ void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *sce
{
scene->lookup_tables->remove_table(&beckmann_table_offset);
- dscene->shader_flag.free();
+ dscene->shaders.free();
}
void ShaderManager::add_default(Scene *scene)