Fix #117280: Cycles: Lights from instancer not working randomly #117301

Merged
Sergey Sharybin merged 4 commits from Sergey/blender:fix_light_linking into main 2024-01-19 09:25:07 +01:00
11 changed files with 82 additions and 39 deletions

View File

@ -833,13 +833,17 @@ void DepsgraphNodeBuilder::build_object(int base_index,
build_texture(object->pd->tex);
}
/* Object dupligroup. */
/* Object instancing. */
if (object->instance_collection != nullptr) {
build_object_instance_collection(object, is_visible);
OperationNode *op_node = add_operation_node(
&object->id, NodeType::DUPLI, OperationCode::DUPLI);
op_node->flag |= OperationFlag::DEPSOP_FLAG_PINNED;
OperationNode *instancer_node = add_operation_node(
&object->id, NodeType::INSTANCING, OperationCode::INSTANCER);
instancer_node->flag |= OperationFlag::DEPSOP_FLAG_PINNED;
}
OperationNode *instance_node = add_operation_node(
&object->id, NodeType::INSTANCING, OperationCode::INSTANCE);
instance_node->flag |= OperationFlag::DEPSOP_FLAG_PINNED;
build_object_light_linking(object);
@ -1179,6 +1183,10 @@ void DepsgraphNodeBuilder::build_object_shading(Object *object)
NodeType::SHADING,
OperationCode::SHADING,
[object_cow](::Depsgraph *depsgraph) { BKE_object_eval_shading(depsgraph, object_cow); });
OperationNode *done_node = add_operation_node(
&object->id, NodeType::SHADING, OperationCode::SHADING_DONE);
done_node->set_as_exit();
}
void DepsgraphNodeBuilder::build_animdata(ID *id)

View File

@ -690,17 +690,9 @@ void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_coll
const ComponentKey object_hierarchy_key{&object->id, NodeType::HIERARCHY};
add_relation(collection_hierarchy_key, object_hierarchy_key, "Collection -> Object hierarchy");
/* The geometry of a collection depends on the positions of the elements in it. */
const OperationKey object_transform_key{
&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL};
add_relation(object_transform_key, collection_geometry_key, "Collection Geometry");
/* Only create geometry relations to child objects, if they have a geometry component. */
const OperationKey object_geometry_key{
&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL};
if (find_node(object_geometry_key) != nullptr) {
add_relation(object_geometry_key, collection_geometry_key, "Collection Geometry");
}
const OperationKey object_instance_key{
&object->id, NodeType::INSTANCING, OperationCode::INSTANCE};
add_relation(object_instance_key, collection_geometry_key, "Collection Geometry");
/* An instance is part of the geometry of the collection. */
if (object->type == OB_EMPTY) {
@ -758,6 +750,10 @@ void DepsgraphRelationBuilder::build_object(Object *object)
add_relation(local_transform_key, parent_transform_key, "ObLocal -> ObParent");
}
add_relation(ComponentKey(&object->id, NodeType::TRANSFORM),
OperationKey{&object->id, NodeType::INSTANCING, OperationCode::INSTANCE},
"Transform -> Instance");
/* Modifiers. */
build_object_modifiers(object);
@ -831,6 +827,8 @@ void DepsgraphRelationBuilder::build_object(Object *object)
build_object_instance_collection(object);
build_object_pointcache(object);
build_object_shading(object);
build_object_light_linking(object);
/* Synchronization back to original object. */
@ -1257,31 +1255,47 @@ void DepsgraphRelationBuilder::build_object_instance_collection(Object *object)
const OperationKey object_transform_final_key(
&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
const ComponentKey duplicator_key(&object->id, NodeType::DUPLI);
const OperationKey instancer_key(&object->id, NodeType::INSTANCING, OperationCode::INSTANCER);
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (instance_collection, ob, graph_->mode) {
const ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
add_relation(dupli_transform_key, object_transform_final_key, "Dupligroup");
/* Hook to special component, to ensure proper visibility/evaluation optimizations. */
add_relation(dupli_transform_key, duplicator_key, "Dupligroup");
const NodeType dupli_geometry_component_type = geometry_tag_to_component(&ob->id);
if (dupli_geometry_component_type != NodeType::UNDEFINED) {
ComponentKey dupli_geometry_component_key(&ob->id, dupli_geometry_component_type);
add_relation(dupli_geometry_component_key, duplicator_key, "Dupligroup");
}
add_relation(OperationKey(&ob->id, NodeType::INSTANCING, OperationCode::INSTANCE),
instancer_key,
"Instance -> Instancer");
}
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
}
void DepsgraphRelationBuilder::build_object_shading(Object *object)
{
const OperationKey shading_done_key(&object->id, NodeType::SHADING, OperationCode::SHADING_DONE);
const OperationKey shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
add_relation(shading_key, shading_done_key, "Shading -> Done");
/* Hook up shading component to the instance, so that if the object is instanced by a visible
* object the shading component is ensured to be evaluated.
* Don't to flushing to avoid re-evaluation of geometry when the object is used as part of a
* collection used as a boolean modifier operand. */
add_relation(shading_done_key,
OperationKey(&object->id, NodeType::INSTANCING, OperationCode::INSTANCE),
"Light Linking -> Instance",
RELATION_FLAG_NO_FLUSH);
}
void DepsgraphRelationBuilder::build_object_light_linking(Object *emitter)
{
const ComponentKey hierarchy_key(&emitter->id, NodeType::HIERARCHY);
const OperationKey shading_done_key(
&emitter->id, NodeType::SHADING, OperationCode::SHADING_DONE);
const OperationKey light_linking_key(
&emitter->id, NodeType::SHADING, OperationCode::LIGHT_LINKING_UPDATE);
add_relation(hierarchy_key, light_linking_key, "Light Linking From Layer");
add_relation(light_linking_key, shading_done_key, "Light Linking -> Shading Done");
if (emitter->light_linking) {
LightLinking &light_linking = *emitter->light_linking;
@ -2477,6 +2491,10 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
* evaluated prior to Scene's CoW is ready. */
OperationKey scene_key(&scene_->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
add_relation(scene_key, obdata_ubereval_key, "CoW Relation", RELATION_FLAG_NO_FLUSH);
/* Relation to the instance, so that instancer can use geometry of this object. */
add_relation(ComponentKey(&object->id, NodeType::GEOMETRY),
OperationKey(&object->id, NodeType::INSTANCING, OperationCode::INSTANCE),
"Transform -> Instance");
/* Grease Pencil Modifiers. */
if (object->greasepencil_modifiers.first != nullptr) {
ModifierUpdateDepsgraphContext ctx = {};

View File

@ -153,6 +153,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_object_pointcache(Object *object);
virtual void build_object_instance_collection(Object *object);
virtual void build_object_shading(Object *object);
virtual void build_object_light_linking(Object *emitter);
virtual void build_light_linking_collection(Object *emitter, Collection *collection);

View File

@ -306,6 +306,11 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
add_relation(armature_key, pose_init_key, "Data dependency");
/* Run cleanup even when there are no bones. */
add_relation(pose_init_key, pose_cleanup_key, "Init -> Cleanup");
/* Relation to the instance, so that instancer can use pose of this object. */
add_relation(ComponentKey(&object->id, NodeType::EVAL_POSE),
OperationKey{&object->id, NodeType::INSTANCING, OperationCode::INSTANCE},
"Transform -> Instance");
/* IK Solvers.
*
* - These require separate processing steps are pose-level to be executed

View File

@ -407,7 +407,7 @@ static void deg_debug_graphviz_node(DotExportContext &ctx,
case NodeType::OBJECT_FROM_LAYER:
case NodeType::HIERARCHY:
case NodeType::BATCH_CACHE:
case NodeType::DUPLI:
case NodeType::INSTANCING:
case NodeType::SYNCHRONIZATION:
case NodeType::AUDIO:
case NodeType::ARMATURE:

View File

@ -87,8 +87,8 @@ const char *nodeTypeAsString(NodeType type)
return "IMAGE_ANIMATION";
case NodeType::BATCH_CACHE:
return "BATCH_CACHE";
case NodeType::DUPLI:
return "DUPLI";
case NodeType::INSTANCING:
return "INSTANCING";
case NodeType::SYNCHRONIZATION:
return "SYNCHRONIZATION";
case NodeType::AUDIO:
@ -150,7 +150,7 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type)
case NodeType::POINT_CACHE:
case NodeType::IMAGE_ANIMATION:
case NodeType::BATCH_CACHE:
case NodeType::DUPLI:
case NodeType::INSTANCING:
case NodeType::SYNCHRONIZATION:
case NodeType::UNDEFINED:
case NodeType::NUM_TYPES:
@ -233,7 +233,7 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type)
case NodeType::POINT_CACHE:
case NodeType::IMAGE_ANIMATION:
case NodeType::BATCH_CACHE:
case NodeType::DUPLI:
case NodeType::INSTANCING:
case NodeType::SYNCHRONIZATION:
case NodeType::NTREE_OUTPUT:
case NodeType::NTREE_GEOMETRY_PREPROCESS:

View File

@ -124,9 +124,9 @@ enum class NodeType {
/* Batch Cache Component.
* TODO(dfelinto/sergey): rename to make it more generic. */
BATCH_CACHE,
/* Duplication system. Used to force duplicated objects visible when
* when duplicator is visible. */
DUPLI,
/* Instancing system.
* Used to control visibility flags of dependencies. */
INSTANCING,
/* Synchronization back to original datablock. */
SYNCHRONIZATION,
/* Node tree output component. */

View File

@ -333,7 +333,7 @@ DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_SHADING);
DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, 0);
DEG_COMPONENT_NODE_DEFINE(Hierarchy, HIERARCHY, 0);
DEG_COMPONENT_NODE_DEFINE(Dupli, DUPLI, 0);
DEG_COMPONENT_NODE_DEFINE(Instancing, INSTANCING, 0);
DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0);
DEG_COMPONENT_NODE_DEFINE(Audio, AUDIO, 0);
DEG_COMPONENT_NODE_DEFINE(Armature, ARMATURE, 0);
@ -368,7 +368,7 @@ void deg_register_component_depsnodes()
register_node_typeinfo(&DNTI_TRANSFORM);
register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
register_node_typeinfo(&DNTI_HIERARCHY);
register_node_typeinfo(&DNTI_DUPLI);
register_node_typeinfo(&DNTI_INSTANCING);
register_node_typeinfo(&DNTI_SYNCHRONIZATION);
register_node_typeinfo(&DNTI_AUDIO);
register_node_typeinfo(&DNTI_ARMATURE);

View File

@ -202,7 +202,7 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Transform);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(ObjectFromLayer);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(Hierarchy);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Dupli);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Instancing);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Armature);

View File

@ -168,6 +168,8 @@ const char *operationCodeAsString(OperationCode opcode)
/* Shading. */
case OperationCode::SHADING:
return "SHADING";
case OperationCode::SHADING_DONE:
return "SHADING_DONE";
case OperationCode::MATERIAL_UPDATE:
return "MATERIAL_UPDATE";
case OperationCode::LIGHT_UPDATE:
@ -197,9 +199,11 @@ const char *operationCodeAsString(OperationCode opcode)
/* Sequencer. */
case OperationCode::SEQUENCES_EVAL:
return "SEQUENCES_EVAL";
/* instancing/duplication. */
case OperationCode::DUPLI:
return "DUPLI";
/* instancing. */
case OperationCode::INSTANCER:
return "INSTANCER";
case OperationCode::INSTANCE:
return "INSTANCE";
}
BLI_assert_msg(0, "Unhandled operation code, should never happen.");
return "UNKNOWN";

View File

@ -163,6 +163,7 @@ enum class OperationCode {
/* Shading. ------------------------------------------------------------- */
SHADING,
SHADING_DONE,
MATERIAL_UPDATE,
LIGHT_UPDATE,
WORLD_UPDATE,
@ -197,8 +198,13 @@ enum class OperationCode {
SEQUENCES_EVAL,
/* Duplication/instancing system. --------------------------------------- */
DUPLI,
/* instancing system. --------------------------------------------------- */
/* Operation on an instancer object. Relations from instanced objects go here. */
INSTANCER,
/* Operation on an object which is being instanced. */
INSTANCE,
};
const char *operationCodeAsString(OperationCode opcode);