Fix #108363: Light linking does not work when linked to self

The code which was preventing this originated to an early days of the
light linking project where bits accumulation was done as part of the
graph evaluation. Since then it was changed to be pre-calculated at
the graph build time.

The updates of the receivers is ensured via the HIERARCHY nodes and
relations between them.

Also made it explicit that the emitter is updated with the tag of
the collection: before it was relying on implicit Copy-on-Write
component tag.

Pull Request: https://projects.blender.org/blender/blender/pulls/108425
This commit is contained in:
Sergey Sharybin 2023-05-30 20:22:30 +02:00 committed by Sergey Sharybin
parent 2d91ebe780
commit 9b946aeecb
3 changed files with 7 additions and 29 deletions

View File

@ -1296,6 +1296,8 @@ void DepsgraphRelationBuilder::build_light_linking_collection(Object *emitter,
&collection->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
const OperationKey collection_parameters_exit_key(
&collection->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
const OperationKey collection_hierarchy_key(
&collection->id, NodeType::HIERARCHY, OperationCode::HIERARCHY);
const OperationKey collection_light_linking_key(
&collection->id, NodeType::PARAMETERS, OperationCode::LIGHT_LINKING_UPDATE);
@ -1313,6 +1315,11 @@ void DepsgraphRelationBuilder::build_light_linking_collection(Object *emitter,
"Collection Light Linking -> Exit",
RELATION_CHECK_BEFORE_ADD);
add_relation(collection_hierarchy_key,
collection_light_linking_key,
"Collection Hierarchy -> Light Linking",
RELATION_CHECK_BEFORE_ADD);
/* Order to ensure the emitter's light linking is only evaluated after the receiver collection.
* This is because light linking runtime data is "cached" om the emitter object for the
* simplicity of access, but the mask is allocated per collection bases (so that if two emitters
@ -1320,19 +1327,6 @@ void DepsgraphRelationBuilder::build_light_linking_collection(Object *emitter,
add_relation(collection_light_linking_key,
emitter_light_linking_key,
"Collection -> Object Light Linking");
/* Relation from the emitter to the receiving object.
* This allows the receiver to access emitter's bit mask. */
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, receiver) {
if (light_linking::can_link_to_emitter(*receiver)) {
const OperationKey receiver_light_linking_key(
&receiver->id, NodeType::SHADING, OperationCode::LIGHT_LINKING_UPDATE);
add_relation(emitter_light_linking_key,
receiver_light_linking_key,
"Emitter -> Receiver Light Linking");
}
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
void DepsgraphRelationBuilder::build_constraints(ID *id,

View File

@ -422,10 +422,6 @@ void Cache::add_receiver_object(const EmitterData &emitter_data,
{
BLI_assert(is_valid_input_id(receiver.id));
if (!can_link_to_emitter(receiver)) {
return;
}
light_linking_.link_object(
emitter_data, eCollectionLightLinkingState(collection_light_linking.link_state), receiver);
}
@ -436,10 +432,6 @@ void Cache::add_blocker_object(const EmitterData &emitter_data,
{
BLI_assert(is_valid_input_id(blocker.id));
if (!can_link_to_emitter(blocker)) {
return;
}
shadow_linking_.link_object(
emitter_data, eCollectionLightLinkingState(collection_light_linking.link_state), blocker);
}

View File

@ -276,12 +276,4 @@ class Cache {
LinkingData shadow_linking_{LIGHT_LINKING_BLOCKER};
};
/* Check whether object can be linked to an emitter without causing feedback loop. */
inline bool can_link_to_emitter(const Object &object)
{
return object.light_linking == nullptr ||
(object.light_linking->receiver_collection == nullptr &&
object.light_linking->blocker_collection == nullptr);
}
} // namespace blender::deg::light_linking