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:
@@ -260,6 +260,11 @@ public:
|
|||||||
return data.size();
|
return data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T* get_data()
|
||||||
|
{
|
||||||
|
return &data[0];
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
array<T> data;
|
array<T> data;
|
||||||
};
|
};
|
||||||
|
@@ -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);
|
int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
|
||||||
#ifdef __VOLUME__
|
#ifdef __VOLUME__
|
||||||
Ray volume_ray = *ray;
|
Ray volume_ray = *ray;
|
||||||
|
bool need_update_volume_stack = kernel_data.integrator.use_volumes &&
|
||||||
|
sd->flag & SD_OBJECT_INTERSECTS_VOLUME;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* compute lighting with the BSDF closure */
|
/* compute lighting with the BSDF closure */
|
||||||
@@ -430,7 +432,7 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __VOLUME__
|
#ifdef __VOLUME__
|
||||||
if(kernel_data.integrator.use_volumes) {
|
if(need_update_volume_stack) {
|
||||||
/* Setup ray from previous surface point to the new one. */
|
/* Setup ray from previous surface point to the new one. */
|
||||||
volume_ray.D = normalize_len(hit_ray.P - volume_ray.P,
|
volume_ray.D = normalize_len(hit_ray.P - volume_ray.P,
|
||||||
&volume_ray.t);
|
&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);
|
int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true);
|
||||||
#ifdef __VOLUME__
|
#ifdef __VOLUME__
|
||||||
Ray volume_ray = *ray;
|
Ray volume_ray = *ray;
|
||||||
|
bool need_update_volume_stack = kernel_data.integrator.use_volumes &&
|
||||||
|
sd->flag & SD_OBJECT_INTERSECTS_VOLUME;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* compute lighting with the BSDF closure */
|
/* 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);
|
path_state_branch(&hit_state, j, num_samples);
|
||||||
|
|
||||||
#ifdef __VOLUME__
|
#ifdef __VOLUME__
|
||||||
if(kernel_data.integrator.use_volumes) {
|
if(need_update_volume_stack) {
|
||||||
/* Setup ray from previous surface point to the new one. */
|
/* Setup ray from previous surface point to the new one. */
|
||||||
float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng);
|
float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng);
|
||||||
volume_ray.D = normalize_len(P - volume_ray.P,
|
volume_ray.D = normalize_len(P - volume_ray.P,
|
||||||
|
@@ -616,9 +616,11 @@ enum ShaderDataFlag {
|
|||||||
SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */
|
SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */
|
||||||
SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */
|
SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */
|
||||||
SD_OBJECT_HAS_VOLUME = 8388608, /* object has a volume shader */
|
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_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;
|
struct KernelGlobals;
|
||||||
|
@@ -1105,8 +1105,37 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
|
|||||||
bool motion_blur = false;
|
bool motion_blur = false;
|
||||||
#endif
|
#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);
|
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;
|
if(progress.get_cancel()) return;
|
||||||
|
|
||||||
|
@@ -75,9 +75,15 @@ void Object::compute_bounds(bool motion_blur)
|
|||||||
bounds.grow(mbounds.transformed(&ttfm));
|
bounds.grow(mbounds.transformed(&ttfm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
if(mesh->transform_applied) {
|
||||||
|
bounds = mbounds;
|
||||||
|
}
|
||||||
|
else {
|
||||||
bounds = mbounds.transformed(&tfm);
|
bounds = mbounds.transformed(&tfm);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Object::apply_transform(bool apply_to_motion)
|
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");
|
progress.set_status("Updating Objects", "Applying Static Transformations");
|
||||||
apply_static_transforms(dscene, scene, object_flag, progress);
|
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)
|
void ObjectManager::device_free(Device *device, DeviceScene *dscene)
|
||||||
|
Reference in New Issue
Block a user