HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
materialOverrideResolvingSceneIndex.h
Go to the documentation of this file.
1 //
2 // Copyright 2024 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_IMAGING_HDSI_MATERIAL_OVERRIDE_RESOLVING_SCENE_INDEX_H
8 #define PXR_IMAGING_HDSI_MATERIAL_OVERRIDE_RESOLVING_SCENE_INDEX_H
9 
14 #include "pxr/imaging/hdsi/api.h"
15 
16 #include <optional>
17 #include <unordered_map>
18 #include <unordered_set>
19 
21 
22 using PathSet = std::unordered_set<SdfPath, SdfPath::Hash>;
23 
25 
26 /*
27 HdsiMaterialOverrideResolvingSceneIndex applies material overrides in the form
28 of edits to a material's interface or directly to parameters of its shader nodes.
29 
30 Overrides to a material's interface are only applied if their interface mappings
31 are found.
32 The overrides for a particular 'publicUIName' are specified at path like this:
33 
34 materialOverride.interfaceValues.<publicUIName>.value
35  -> overrideValueDataSource
36 
37 The 'overrideValueDataSource' is copied over a network node parameter's original
38 'valueDataSource' at paths like this:
39 
40 material.<renderContext>.nodes.<nodePath>.parameters.<inputName>.value
41  -> valueDataSource
42 
43 The scene index identifies which network node parameter to override by using
44 the material's interface mappings which are defined at paths like this:
45 
46 material.<renderContext>.interface.parameters.<publicUIName>.mappings
47  -> [(nodePath, inputName), (nodePath, inputName), ...]
48 
49 Edits of input parameters of shaders within the material are specified at a path
50 like this:
51 materialOverride.parameterValues.<shaderNodeName>.<parameterName>.value ->
52  paramEditValueDataSource
53 
54 The 'paramEditValueDataSource' is copied over a network node parameter's original
55 'valueDataSource' at paths like this:
56 
57 material.<renderContext>.nodes.<nodePath>.parameters.<inputName>.value
58  -> valueDataSource
59 
60 If the same input parameter is overridden both by an edit to the material
61 interface and by a direct parameter edit, the interface override will take
62 precedence.
63 
64 If a geometry prim contains materialOverride data sources, a copy of
65 the material bound to that location will be generated, and the overrides will
66 only be applied to the generated material.
67 Any changes to the original material will be reflected in the generated material.
68 Geometry prims that contain materialOverride data sources are only
69 processed by this Scene Index if they contain a materialBindings data source
70 with material binds for one of the following purposes: full, allPurpose.
71 A minimum set of materials will be generated to satisfy material overrides: two
72 geometry prims bound to the same material and containing the same set of
73 material overrides will share the same generated material.
74 
75 Below is a diagram of the expected attributes needed for material interface
76 and parameter edits on a scene index prim of type 'material':
77 
78 MaterialPrim
79 |
80 +------materialOverride
81 | |
82 | +----interfaceValues
83 | | |
84 | | +-publicUIName
85 | | | |
86 | | | +---value -> overrideValueDataSource
87 | | |
88 | | +-publicUIName
89 | | | |
90 | | | +---value -> overrideValueDataSource
91 | | |
92 | | +-...
93 | |
94 | +----parameterValues
95 | |
96 | +-nodePath
97 | | |
98 | | +---inputName
99 | | | |
100 | | | +---value -> paramEditValueDataSource
101 | | |
102 | | +---inputName
103 | | | |
104 | | | +---value -> paramEditValueDataSource
105 | | |
106 | | +---...
107 | |
108 | +-...
109 |
110 +------material
111  |
112  +----ri
113  |
114  +--nodes
115  | |
116  | +-nodePath
117  | | |
118  | | +-parameters
119  | | |
120  | | +-inputName
121  | | | |
122  | | | +-value -> valueDataSource
123  | | |
124  | | +-inputName
125  | | |
126  | | +-value -> valueDataSource
127  | |
128  | +-nodePath
129  | |
130  | +-parameters
131  | |
132  | +-...
133  |
134  +--interface
135  |
136  +-parameters
137  | |
138  | +-publicUIName
139  | | |
140  | | +-mappings
141  | | +-i0
142  | | | |
143  | | | +----nodePath
144  | | | |
145  | | | +----inputName
146  | | |
147  | | +-i1
148  | | | |
149  | | | +----nodePath
150  | | | |
151  | | | +----inputName
152  | | |
153  | | +-...
154  | |
155  | +-publicUIName
156  | | |
157  | | +-mappings
158  | | +-i0
159  | | | |
160  | | | +----nodePath
161  | | | |
162  | | | +----inputName
163  | | |
164  | | +-i1
165  | | | |
166  | | | +----nodePath
167  | | | |
168  | | | +----inputName
169  | | |
170  | | +-...
171  | +-...
172  |
173  +-parameterOrder = ...
174 */
175 
178 {
179  // Forward Declarations
180  struct MaterialData;
181  struct PrimData;
182 
183  // Type Definitions
184  using PrimDataMap = std::unordered_map<SdfPath, PrimData, SdfPath::Hash>;
185  using MaterialPathsMap = std::unordered_map<SdfPath, PathSet, SdfPath::Hash>;
186  using MaterialDataMap = std::unordered_map<SdfPath, MaterialData,
187  SdfPath::Hash>;
188  using HashToMaterialPathMap = std::unordered_map<uint64_t, SdfPath>;
189  using MaterialHashMap = std::unordered_map<SdfPath, HashToMaterialPathMap,
190  SdfPath::Hash>;
191 
192 public:
193  static HdsiMaterialOverrideResolvingSceneIndexRefPtr New(
194  const HdSceneIndexBaseRefPtr &inputScene)
195  {
196  return TfCreateRefPtr(
198  }
199 
200  // HdSceneIndexBase overrides
201  HDSI_API
202  HdSceneIndexPrim GetPrim(const SdfPath &primPath) const override;
203 
204  HDSI_API
205  SdfPathVector GetChildPrimPaths(const SdfPath &primPath) const override;
206 
207 protected:
208 
209  HDSI_API
211  const HdSceneIndexBaseRefPtr &inputScene);
212 
213  // HdSingleInputFilteringSceneIndexBase overrides
214  void _PrimsAdded(
215  const HdSceneIndexBase &sender,
216  const HdSceneIndexObserver::AddedPrimEntries &entries) override;
217 
218  void _PrimsRemoved(
219  const HdSceneIndexBase &sender,
220  const HdSceneIndexObserver::RemovedPrimEntries &entries) override;
221 
222  void _PrimsDirtied(
223  const HdSceneIndexBase &sender,
224  const HdSceneIndexObserver::DirtiedPrimEntries &entries) override;
225 
226 private:
227  /// Returns the Material Override Schema for the prim at \p primPath
228  /// The returned schema can be invalid.
229  HdMaterialOverrideSchema _GetMaterialOverrides(
230  const SdfPath& primPath) const;
231 
232  /// Given a vector of AddedPrimEntry \p entries, decide whether new
233  /// materials need be generated to resolve material overrides.
234  /// Returns a vector of AddedPrimEntry that includes all elements of
235  /// \p entries plus any that were added to account for generated materials.
236  HdSceneIndexObserver::AddedPrimEntries _AddGeneratedMaterials(
238 
239  /// Given a Hydra prim described by its type \p primType and its path
240  /// \p primPath decide whether a generated material is needed to
241  /// satisfy its material overrides.
242  /// Returns the path to the generated material, or an empty path is no
243  /// new generated material is required.
244  SdfPath _AddGeneratedMaterial(
245  const TfToken& primType,
246  const SdfPath& primPath);
247 
248  /// Given a vector of DirtiedPrimEntry \p entries, create extra entries
249  /// for generated materials, as needed.
250  /// Returns a vector of DirtiedPrimEntry that includes all elements of
251  /// \p entries plus any that were added to account for generated materials.
252  HdSceneIndexObserver::DirtiedPrimEntries _DirtyGeneratedMaterials(
254 
255  /// Process dirty notices for materials used to generated override
256  /// materials in this scene index.
257  /// This function is responsible for propagating changes from base materials
258  /// to the materials generated from them.
259  /// \p primPath is the path of the dirty material prim
260  /// \p generatedMaterials is a list of materials generated from \p primPath
261  /// \p dirtiedPaths which is returned to the caller, will contain a set
262  /// of paths dirtied by this call. New elements are appended to any
263  /// already there.
264  void _DirtyBaseMaterial(
265  const SdfPath& primPath,
266  const PathSet& generatedMaterials,
267  PathSet* dirtiedPaths) const;
268 
269  /// Process dirty notices for geometry that has received material overrides.
270  /// \p entry is the dirty entry to operate on
271  /// \p inputScene is a pointer to this Scene Index's input Scene Index
272  /// \p primData contains material override data for the dirtied prim
273  /// \p processedPrimsSet which is returned to the caller, will contain a set
274  /// of paths for prims that have been processed by this function in addition
275  /// to the prim described by \p entry. New elements are appended to any
276  /// already there.
277  /// \p addedPaths \p dirtiedPaths and \p removedPaths which are all returned
278  /// to the caller will contain sets of paths that have been added, dirtied
279  /// or removed by this call. New elements are appended to any
280  /// already there.
281  void _DirtyGeometry(
283  const HdSceneIndexBaseRefPtr inputScene,
284  const PrimData& primData,
285  PathSet* processedPrimsSet,
286  PathSet* addedPaths,
287  PathSet* dirtiedPaths,
288  PathSet* removedPaths);
289 
290  /// Process dirty notices to the materialOverride locator for prims which
291  /// are receiving a material override for the first time.
292  /// \p primPath is the dirty prim
293  /// \p inputScene is a pointer to this Scene Index's input Scene Index
294  /// \p addedPaths and \p dirtiedPaths which are all returned
295  /// to the caller will contain sets of paths that have been added or dirtied
296  /// by this call. New elements are appended to any already there.
297  void _DirtyMaterialOverrideLocator(
298  const SdfPath& primPath,
299  const HdSceneIndexBaseRefPtr inputScene,
300  PathSet* addedPaths,
301  PathSet* dirtiedPaths);
302 
303  /// Given a path \p primPath to a material scope, return a set of
304  /// generated materials that are located under it
305  PathSet _GetGeneratedMaterials(const SdfPath& primPath) const;
306 
307  /// Returns true if the Hydra Material at \p primPath was generated by
308  /// this scene index. Returns false otherwise
309  bool _IsGeneratedMaterial(const SdfPath& primPath) const;
310 
311  /// Given a Hydra Material \p prim at location \p primPath which was
312  /// generated by this scene index, populate its data source.
313  void _CreateGeneratedMaterialDataSource(
314  HdSceneIndexPrim& prim,
315  const SdfPath& primPath) const;
316 
317  /// Returns a hashed value for the \p materialOverrides schema
318  uint64_t _GetHash(const HdMaterialOverrideSchema& materialOverrides) const;
319 
320  /// Invalidate the portion of the bookkeeping maps of this scene index
321  /// that contain data about the prim located at \p primPath
322  void _InvalidateMaps(const SdfPath& primPath);
323 
324  /// Struct describing data for materials generated in the process of
325  /// resolving overrides set on non-material locations
326  struct MaterialData
327  {
328  // Path to the material bound to materialOverridePrimPath
329  // before any changes are made by this scene index
330  SdfPath originalMaterialPath;
331 
332  // Set of geometry prims using this generated material
333  PathSet boundPrims;
334  };
335 
336  /// Struct describing data for geometry prims using generated materials to
337  /// express material overrides
338  struct PrimData
339  {
340  // Path to the generated material bound to this geometry prim
341  SdfPath generatedMaterialPath;
342 
343  // Hash of the material overrides found on this prim
344  uint64_t materialOverrideHash;
345  };
346 
347  // Map linking a path of a material scope to a set of materials that are
348  // generated by this scene index as a result of resolving material
349  // overrides at non-material locations.
350  MaterialPathsMap _scopeToNewMaterialPaths;
351 
352  // Map linking a material to a set of materials generated from it.
353  MaterialPathsMap _oldToNewMaterialPaths;
354 
355  // Map linking geometry prims to the path of the generated material that
356  // will be bound to them and to the hash for their material overrides.
357  // The keys in this map represent geometry prims that have
358  // a material binding and a material override data source.
359  PrimDataMap _primData;
360 
361  // Map linking materials generated in the process of resolving material
362  // overrides to their data.
363  MaterialDataMap _materialData;
364 
365  // Map relating a geometry prim's bound material (before this scene index
366  // executes) and the hash of its material override data source to the path
367  // of a generated material.
368  // Used to allow multiple geometry prims that share the same starting
369  // material and material overrides to use the same generated material.
370  // For example:
371  // PlasticMaterial --> ..0123 --> __MOR_PlasticMaterial_Mesh
372  // --> ..4567 --> __MOR_PlasticMaterial_AnotherMesh
373  // WoodMaterial --> ..0123 --> __MOR_WoodMaterial_Mesh
374  // MetalMaterial --> ..4567 --> __MOR_MetalMaterial_Point
375  MaterialHashMap _materialHashMap;
376 };
377 
379 
380 #endif // PXR_IMAGING_HDSI_MATERIAL_OVERRIDE_RESOLVING_SCENE_INDEX_H
TfRefPtr< T > TfCreateRefPtr(T *ptr)
Definition: refPtr.h:1190
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
void _PrimsRemoved(const HdSceneIndexBase &sender, const HdSceneIndexObserver::RemovedPrimEntries &entries) override
HDSI_API SdfPathVector GetChildPrimPaths(const SdfPath &primPath) const override
HDSI_API HdSceneIndexPrim GetPrim(const SdfPath &primPath) const override
Definition: token.h:70
std::unordered_set< SdfPath, SdfPath::Hash > PathSet
std::vector< class SdfPath > SdfPathVector
static HdsiMaterialOverrideResolvingSceneIndexRefPtr New(const HdSceneIndexBaseRefPtr &inputScene)
HDSI_API HdsiMaterialOverrideResolvingSceneIndex(const HdSceneIndexBaseRefPtr &inputScene)
Definition: path.h:280
#define HDSI_API
Definition: api.h:23
void _PrimsDirtied(const HdSceneIndexBase &sender, const HdSceneIndexObserver::DirtiedPrimEntries &entries) override
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
TF_DECLARE_WEAK_AND_REF_PTRS(HdsiMaterialOverrideResolvingSceneIndex)
void _PrimsAdded(const HdSceneIndexBase &sender, const HdSceneIndexObserver::AddedPrimEntries &entries) override