diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-03-10 08:55:39 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-03-10 08:55:39 +0300 |
commit | d27158aae9bc48b2a07760a2dbe8e642fcecbe57 (patch) | |
tree | 7ecfe898e53f07e589ee4be0ea5b297153d7dfcf /intern/cycles/render | |
parent | f3161bd2abe4bcc41f0e9169275be315ecc6b054 (diff) | |
parent | 8a76f8dac3475b1d24956e0d384d65295f15c76a (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/camera.cpp | 154 | ||||
-rw-r--r-- | intern/cycles/render/camera.h | 28 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 141 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 161 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 8 | ||||
-rw-r--r-- | intern/cycles/render/mesh_volume.cpp | 46 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 17 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 284 | ||||
-rw-r--r-- | intern/cycles/render/object.h | 56 | ||||
-rw-r--r-- | intern/cycles/render/osl.cpp | 15 | ||||
-rw-r--r-- | intern/cycles/render/particles.cpp | 22 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 18 | ||||
-rw-r--r-- | intern/cycles/render/session.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 21 |
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) |