diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-10-03 12:52:04 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2014-10-03 12:52:04 +0400 |
commit | a65451235637514abaaf2b04c5a89f14a6edd96f (patch) | |
tree | 434aa96d50837b2a08992230ddb46f9ab1995be4 | |
parent | b86f199a98fe77b634ea7f686d3d664d9791562b (diff) |
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.
-rw-r--r-- | intern/cycles/device/device_memory.h | 5 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 4 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 31 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 13 |
5 files changed, 52 insertions, 9 deletions
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h index 8eee6a2c79e..07a6eb36a3c 100644 --- a/intern/cycles/device/device_memory.h +++ b/intern/cycles/device/device_memory.h @@ -260,6 +260,11 @@ public: return data.size(); } + T* get_data() + { + return &data[0]; + } + private: array<T> data; }; diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 29077a8886c..e68a8370012 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -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, diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 34585ad8de6..2fe1cd87072 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -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; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index cc141b771d1..db6311c3d97 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -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; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 634d0401aa9..986a36ba120 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -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) |