Fix T86601: Cycles accumulates displacement when transforming an Object

In order to update the BVH when only the transformations are changing,
we would tag the Object's Geometry as modified. However, when
displacement is used, and the vertices were not themselves modified,
this would cause us to redo the displacement on already displaced
vertices.

To fix this, use a specific update flag for detecting and notifying that
transformations were modified.

Regression caused by rBbbe6d44928235cd4a5cfbeaf1a1de78ed861bb92.
This commit is contained in:
Kévin Dietrich 2021-03-24 10:36:31 +01:00
parent 6b18678e34
commit 42198e9eb0
Notes: blender-bot 2023-02-14 08:45:09 +01:00
Referenced by issue #86939, Cycles rendered view refresh on GPU
Referenced by issue #86601, Cycles: Each time you move an object with displacement shader, it's move up and up again
4 changed files with 14 additions and 13 deletions

View File

@ -1917,9 +1917,12 @@ void GeometryManager::device_update(Device *device,
}
}
/* update the bvh even when there is no geometry so the kernel bvh data is still valid,
* especially when removing all of the objects during interactive renders */
bool need_update_scene_bvh = (scene->bvh == nullptr);
/* Update the BVH even when there is no geometry so the kernel's BVH data is still valid,
* especially when removing all of the objects during interactive renders.
* Also update the BVH if the transformations change, we cannot rely on tagging the Geometry
* as modified in this case, as we may accumulate displacement if the vertices do not also
* change. */
bool need_update_scene_bvh = (scene->bvh == nullptr || (update_flags & TRANSFORM_MODIFIED) != 0);
{
scoped_callback_timer timer([scene](double time) {
if (scene->update_stats) {

View File

@ -189,6 +189,8 @@ class GeometryManager {
GEOMETRY_ADDED = MESH_ADDED | HAIR_ADDED,
GEOMETRY_REMOVED = MESH_REMOVED | HAIR_REMOVED,
TRANSFORM_MODIFIED = (1 << 10),
/* tag everything in the manager for an update */
UPDATE_ALL = ~0u,

View File

@ -221,16 +221,7 @@ void Object::tag_update(Scene *scene)
if (geometry) {
if (tfm_is_modified()) {
/* tag the geometry as modified so the BVH is updated, but do not tag everything as modified
*/
if (geometry->is_mesh() || geometry->is_volume()) {
Mesh *mesh = static_cast<Mesh *>(geometry);
mesh->tag_verts_modified();
}
else if (geometry->is_hair()) {
Hair *hair = static_cast<Hair *>(geometry);
hair->tag_curve_keys_modified();
}
flag |= ObjectManager::TRANSFORM_MODIFIED;
}
foreach (Node *node, geometry->get_used_shaders()) {
@ -923,6 +914,10 @@ void ObjectManager::tag_update(Scene *scene, uint32_t flag)
geometry_flag |= (GeometryManager::GEOMETRY_ADDED | GeometryManager::GEOMETRY_REMOVED);
}
if ((flag & TRANSFORM_MODIFIED) != 0) {
geometry_flag |= GeometryManager::TRANSFORM_MODIFIED;
}
scene->geometry_manager->tag_update(scene, geometry_flag);
}

View File

@ -133,6 +133,7 @@ class ObjectManager {
OBJECT_REMOVED = (1 << 4),
OBJECT_MODIFIED = (1 << 5),
HOLDOUT_MODIFIED = (1 << 6),
TRANSFORM_MODIFIED = (1 << 7),
/* tag everything in the manager for an update */
UPDATE_ALL = ~0u,