Blender V4.3
depsgraph_light_linking.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#pragma once
10
11#include <cstdint>
12
13#include "BLI_map.hh"
14
15#include "BKE_light_linking.h" /* LightLinkingType */
16
17#include "DNA_collection_types.h" /* eCollectionLightLinkingState */
18#include "DNA_object_types.h"
19
20struct Collection;
22struct Object;
23struct Scene;
24
26
27namespace internal {
28
29/* Set of light as seen from a receiver perspective. */
30class LightSet {
31 public:
32 /* Maximum possible identifier of a light set. The identifier is 0-based.
33 * The limitation is imposed by the fact that its identifier is converted to a bitmask. */
34 static constexpr int MAX_ID = 63;
35
36 /* Identifier of a light set which is not explicitly linked to anything. */
37 static constexpr int DEFAULT_ID = 0;
38
39 bool operator==(const LightSet &other) const;
40 bool operator!=(const LightSet &other) const
41 {
42 return !(*this == other);
43 }
44
45 uint64_t hash() const;
46
47 /* Lights which are explicitly included/excluded into the light set.
48 *
49 * The light is denoted as a bit mask of a light linking collection. This mask is allocated for
50 * every unique light linking collection on an emitter. */
53};
54
56 public:
57 /* Bitmask which indicates the emitter belongs to all light sets. */
58 static constexpr uint64_t SET_MEMBERSHIP_ALL = ~uint64_t(0);
59
60 /* Get final membership mask in the light sets, considering its inclusion and exclusion. */
61 uint64_t get_mask() const;
62
63 /* Bit masks of the emitter membership in the light sets. */
66};
67
68/* Packed information about emitter.
69 * Emitter is actually corresponding to a light linking collection on an object. */
71 public:
72 /* Maximum possible identifier of a light linking collection. The identifier is 0-based.
73 * The limitation is imposed by the fact that its identifier is converted to a bitmask. */
74 static constexpr int MAX_COLLECTION_ID = 63;
75
76 /* Mask of a light linking collection this emitter uses in its configuration.
77 * A single bit is set in this bit-field which corresponds to an identifier of a light linking
78 * collection in the scene. */
80
81 /* Membership masks for the light and shadow linking. */
84};
85
86/* Helper class which deals with keeping per-emitter data. */
89
90 public:
91 explicit EmitterDataMap(const LightLinkingType link_type) : link_type_(link_type) {}
92
93 /* Returns true if there is no information about emitters at all. */
94 bool is_empty() const
95 {
96 return emitter_data_map_.is_empty();
97 }
98
99 /* Entirely clear the state, become ready for a new light linking relations build. */
100 void clear();
101
102 /* Ensure that the data exists for the given emitter.
103 * The emitter must be original and have light linking collection.
104 *
105 * Note that there is limited number of emitters possible within a scene, When this number is
106 * exceeded an error is printed and a nullptr is returned. */
107 EmitterData *ensure_data_if_possible(const Scene &scene, const Object &emitter);
108
109 /* Get emitter data for the given original or evaluated object.
110 * If the light linking is not configured for this emitted nullptr is returned. */
111 const EmitterData *get_data(const Object &emitter) const;
112
113 /* Returns true if the underlying data of the light linking emitter has been handled, and there
114 * is no need to handle the emitter.
115 * The emitter must be original object. */
116 bool can_skip_emitter(const Object &emitter) const;
117
118 /* Returns an iterator over all emitter data in the map. */
119 MapType::MutableValueIterator values()
120 {
121 return emitter_data_map_.values();
122 }
123
124 private:
125 /* Get linked collection depending on whether this is emitter information for light or shadow
126 * linking. */
127 /* TODO(sergey): Check whether template specialization is preferred here. */
128 inline const Collection *get_collection(const Object &emitter) const
129 {
130 return BKE_light_linking_collection_get(&emitter, link_type_);
131 }
132
134
135 /* Emitter-centric information: indexed by an original emitter object, contains accumulated
136 * information about emitter. */
137 MapType emitter_data_map_;
138
139 /* Next unique light linking collection ID. */
140 uint64_t next_collection_id_ = 0;
141};
142
143/* Common part of receiver (for light linking) and blocker (for shadow lining) data. */
145 public:
146 explicit LinkingData(const LightLinkingType link_type) : link_type_(link_type) {}
147
148 /* Entirely clear the state, become ready for a new light linking relations build. */
149 void clear();
150
151 /* Link the given object with the given light linking state. */
152 void link_object(const EmitterData &emitter_data,
154 const Object &object);
155
156 /* Compute unique sets of emitters used by receivers or blockers.
157 *
158 * This must be called at the end of depsgraph relations build after all emitters have been
159 * added, and before runtime data can be set as part of evaluation. */
160 void end_build(const Scene &scene, EmitterDataMap &emitter_data_map);
161
162 /* Get an unique index the given object is receiving light or casting shadow from.
163 * The object can either be original or evaluated.
164 *
165 * If the object is not linked to any emitter LightSet::DEFAULT_ID is returned. */
166 uint64_t get_light_set_for(const Object &object) const;
167
168 private:
169 /* Ensure that the light set exists for the given receiver/blocker object.
170 * The object must be original. */
171 LightSet &ensure_light_set_for(const Object &object);
172
173 /* Update the emitter light/shadow set membership after the final unique light set identifier
174 * is known.
175 * The light_set_mask consists of a single bit set corresponding to the light set index. */
176 void update_emitters_membership(EmitterDataMap &emitter_data_map,
177 const LightSet &light_set,
178 uint64_t light_set_mask);
179
180 /* Clear data which is only needed during the build. */
181 void clear_after_build();
182
183 /* Get light set membership information of the emitter data depending whether this linking
184 * data is a light or shadow linking. */
185 /* TODO(sergey): Check whether template specialization is preferred here. */
186 inline EmitterSetMembership &get_emitter_set_membership(EmitterData &emitter_data) const
187 {
188 if (link_type_ == LIGHT_LINKING_BLOCKER) {
189 return emitter_data.shadow_membership;
190 }
191
192 return emitter_data.light_membership;
193 }
194
196
197 /* Receiver/blocker-centric view of light sets: indexed by an original receiver object, contains
198 * light set which defines from which emitters it receives light from or casts shadow when is lit
199 * ny.
200 *
201 * NOTE: Only available during build. */
202 Map<const Object *, LightSet> light_linked_sets_;
203
204 /* Map from an original receiver/blocker object: map to index of light set for this
205 * receiver/blocker. */
206 /* TODO(sergey): What is the generic term for receiver and blocker which is less generic than
207 * object? */
208 Map<const Object *, uint64_t> object_light_sets_;
209};
210
211} // namespace internal
212
213/* Cached light linking evaluation data.
214 *
215 * This cache is only valid within a specific dependency graph, hence the dependency graph is
216 * expected to own this cache.
217 *
218 * This cache takes care of making it efficient to lookup emitter masks, emitters which affect
219 * given receiver and so on. */
220class Cache {
224
225 public:
226 /* Entirely clear the cache.
227 * Should be called whenever the dependency graph is being re-built, in the beginning of the
228 * build process. */
229 void clear();
230
231 /* Add emitter to the cache.
232 *
233 * This call does nothing if the emitter does not have light configured linking (as in, if it
234 * has light linking collection set to nullptr).
235 *
236 * The emitter must be original. This is asserted, but in release builds passing evaluated
237 * object leads to an undefined behavior. */
238 void add_emitter(const Scene &scene, const Object &emitter);
239
240 /* Compute unique sets of emitters used by receivers and blockers.
241 *
242 * This must be called at the end of depsgraph relations build after all emitters have been
243 * added, and before runtime data can be set as part of evaluation. */
244 void end_build(const Scene &scene);
245
246 /* Set runtime light linking data on evaluated object. */
247 void eval_runtime_data(Object &object_eval) const;
248
249 private:
250 /* Add emitter information specific for light and shadow linking. */
251 void add_light_linking_emitter(const Scene &scene, const Object &emitter);
252 void add_shadow_linking_emitter(const Scene &scene, const Object &emitter);
253
254 /* Add receiver or blocker object with the given light linking configuration.
255 *
256 * The term receiver here is meant in a wider meaning of it. For the light linking it is a
257 * receiver of light, but for the shadow linking is it actually a shadow caster. */
258 void add_receiver_object(const EmitterData &emitter_data,
259 const CollectionLightLinking &collection_light_linking,
260 const Object &receiver);
261 void add_blocker_object(const EmitterData &emitter_data,
262 const CollectionLightLinking &collection_light_linking,
263 const Object &blocker);
264
265 /* Returns true if there is light linking configuration in the scene. */
266 bool has_light_linking() const
267 {
268 return !light_emitter_data_map_.is_empty() || !shadow_emitter_data_map_.is_empty();
269 }
270
271 /* Per-emitter light and shadow linking information. */
272 EmitterDataMap light_emitter_data_map_{LIGHT_LINKING_RECEIVER};
273 EmitterDataMap shadow_emitter_data_map_{LIGHT_LINKING_BLOCKER};
274
275 /* Light and shadow linking data. */
276 LinkingData light_linking_{LIGHT_LINKING_RECEIVER};
277 LinkingData shadow_linking_{LIGHT_LINKING_BLOCKER};
278};
279
280} // namespace blender::deg::light_linking
LightLinkingType
@ LIGHT_LINKING_BLOCKER
@ LIGHT_LINKING_RECEIVER
struct Collection * BKE_light_linking_collection_get(const struct Object *object, LightLinkingType link_type)
Object groups, one object can be in many groups at once.
eCollectionLightLinkingState
Object is a sort of wrapper for general info.
ValueIterator values() const
Definition BLI_map.hh:846
bool is_empty() const
Definition BLI_map.hh:937
void eval_runtime_data(Object &object_eval) const
void add_emitter(const Scene &scene, const Object &emitter)
EmitterData * ensure_data_if_possible(const Scene &scene, const Object &emitter)
const EmitterData * get_data(const Object &emitter) const
void end_build(const Scene &scene, EmitterDataMap &emitter_data_map)
void link_object(const EmitterData &emitter_data, eCollectionLightLinkingState link_state, const Object &object)
unsigned __int64 uint64_t
Definition stdint.h:90