Cycles: Implement preliminary test for volume stack update from SSS

This adds an AABB collision check for objects with volumes and if there's a
collision detected then the object will have SD_OBJECT_INTERSECTS_VOLUME flag.

This solves a speed regression introduced by the fix for T39823 by skipping
volume stack update in cases no volumes intersects the current SSS object.
This commit is contained in:
Sergey Sharybin
2014-10-03 10:52:04 +02:00
parent b86f199a98
commit a654512356
5 changed files with 52 additions and 9 deletions

View File

@@ -260,6 +260,11 @@ public:
return data.size();
}
T* get_data()
{
return &data[0];
}
private:
array<T> data;
};

View File

@@ -411,6 +411,8 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd
int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
#ifdef __VOLUME__
Ray volume_ray = *ray;
bool need_update_volume_stack = kernel_data.integrator.use_volumes &&
sd->flag & SD_OBJECT_INTERSECTS_VOLUME;
#endif
/* compute lighting with the BSDF closure */
@@ -430,7 +432,7 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd
#endif
#ifdef __VOLUME__
if(kernel_data.integrator.use_volumes) {
if(need_update_volume_stack) {
/* Setup ray from previous surface point to the new one. */
volume_ray.D = normalize_len(hit_ray.P - volume_ray.P,
&volume_ray.t);
@@ -802,6 +804,8 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true);
#ifdef __VOLUME__
Ray volume_ray = *ray;
bool need_update_volume_stack = kernel_data.integrator.use_volumes &&
sd->flag & SD_OBJECT_INTERSECTS_VOLUME;
#endif
/* compute lighting with the BSDF closure */
@@ -811,7 +815,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
path_state_branch(&hit_state, j, num_samples);
#ifdef __VOLUME__
if(kernel_data.integrator.use_volumes) {
if(need_update_volume_stack) {
/* Setup ray from previous surface point to the new one. */
float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng);
volume_ray.D = normalize_len(P - volume_ray.P,

View File

@@ -616,9 +616,11 @@ enum ShaderDataFlag {
SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */
SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */
SD_OBJECT_HAS_VOLUME = 8388608, /* object has a volume shader */
SD_OBJECT_INTERSECTS_VOLUME = 16777216, /* object intersects AABB of an object with volume shader */
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED|
SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME)
SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME|
SD_OBJECT_INTERSECTS_VOLUME)
};
struct KernelGlobals;

View File

@@ -1105,8 +1105,37 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
bool motion_blur = false;
#endif
foreach(Object *object, scene->objects)
/* TODO(sergey): There's an ongoing fake cyclic dependency between objects
* and meshes here -- needs to make update functions a bit more granular in
* order to keep all the updates in a logical way.
*/
/* update obejcts */
vector<Object *> volume_objects;
foreach(Object *object, scene->objects) {
object->compute_bounds(motion_blur);
if(object->mesh->has_volume) {
volume_objects.push_back(object);
}
}
int object_index = 0;
uint *object_flags = dscene->object_flag.get_data();
foreach(Object *object, scene->objects) {
foreach(Object *volume_object, volume_objects) {
if(object == volume_object) {
continue;
}
if(object->bounds.intersects(volume_object->bounds)) {
object_flags[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
break;
}
}
++object_index;
}
/* allocate object flag */
device->tex_alloc("__object_flag", dscene->object_flag);
if(progress.get_cancel()) return;

View File

@@ -75,8 +75,14 @@ void Object::compute_bounds(bool motion_blur)
bounds.grow(mbounds.transformed(&ttfm));
}
}
else
bounds = mbounds.transformed(&tfm);
else {
if(mesh->transform_applied) {
bounds = mbounds;
}
else {
bounds = mbounds.transformed(&tfm);
}
}
}
void Object::apply_transform(bool apply_to_motion)
@@ -410,9 +416,6 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
progress.set_status("Updating Objects", "Applying Static Transformations");
apply_static_transforms(dscene, scene, object_flag, progress);
}
/* allocate object flag */
device->tex_alloc("__object_flag", dscene->object_flag);
}
void ObjectManager::device_free(Device *device, DeviceScene *dscene)