| 
 | 1 | +### [Index](../index.md) | [Usage](./index.md) | Materials  | 
 | 2 | + | 
 | 3 | +--------  | 
 | 4 | + | 
 | 5 | +# Materials  | 
 | 6 | + | 
 | 7 | +Starting with Falcor 5.0 there is a new material system that allows creation and rendering of different materials  | 
 | 8 | +types at runtime. In previous versions, a fixed diffuse+GGX material model was assumed.  | 
 | 9 | + | 
 | 10 | +All materials and their resources are managed by the `MaterialSystem` C++ class and matching Slang module.  | 
 | 11 | +The material system is owned by `Scene` object and bound together with its other resources when rendering.  | 
 | 12 | + | 
 | 13 | +In order to access the material system in shader code, the following module must be imported:  | 
 | 14 | + | 
 | 15 | +```c++  | 
 | 16 | +import Scene.Shading;  | 
 | 17 | +```  | 
 | 18 | + | 
 | 19 | +## Data layout  | 
 | 20 | + | 
 | 21 | +For efficient access, each material is described by a data blob of fixed size (currently 128B).  | 
 | 22 | +The data blob consists of a header (see `MaterialHeader` declared in `Falcor/Scene/Material/MaterialData.slang`)  | 
 | 23 | +followed by a data payload. The header always exists and holds material type ID and auxiliary flags etc.  | 
 | 24 | + | 
 | 25 | +The format of the data payload is opaque and depends on the material type. If a material needs more data  | 
 | 26 | +than what fits in the payload, it can store additional sideband data in a buffer.  | 
 | 27 | + | 
 | 28 | +All resources (textures, samplers, buffers) are accessed via bindless resource IDs, where the actual GPU  | 
 | 29 | +resources are managed by `MaterialSystem` and the IDs are allocated when resources are added.  | 
 | 30 | +These bindless IDs are stored as part of the data payload, so that a material is self-contained and fully  | 
 | 31 | +desribed by its data blob.  | 
 | 32 | + | 
 | 33 | +## Material class (host side)  | 
 | 34 | + | 
 | 35 | +On the host side, all materials are derived from the `Material` base class declared in `Scene/Material/Material.h`.  | 
 | 36 | + | 
 | 37 | +In order to add a new material, a new class should be added that inherits from `Material` and implements  | 
 | 38 | +its pure virtual member functions. The most important ones are:  | 
 | 39 | + | 
 | 40 | +```c++  | 
 | 41 | +// Called once per frame to prepare the material for rendering.  | 
 | 42 | +Material::UpdateFlags Material::update(MaterialSystem* pOwner);  | 
 | 43 | + | 
 | 44 | +// Returns the material data blob.  | 
 | 45 | +MaterialDataBlob Material::getDataBlob() const;  | 
 | 46 | +```  | 
 | 47 | +
  | 
 | 48 | +The base class holds the `MaterialHeader` struct and the derived material class is responsible  | 
 | 49 | +for holding the data payload. The `getDataBlob()` returns the final data blob, which will be uploaded to the  | 
 | 50 | +GPU by the material system for access on the shader side.  | 
 | 51 | +
  | 
 | 52 | +## Python bindings  | 
 | 53 | +
  | 
 | 54 | +To allow creation of materials and setting of the parameters from Python scripts (including `.pyscene` files),  | 
 | 55 | +each material class is expected to export Python bindings.  | 
 | 56 | +
  | 
 | 57 | +These bindings are defined in the `FALCOR_SCRIPT_BINDING` block, usually placed at the bottom of the material's `.cpp` file.  | 
 | 58 | +
  | 
 | 59 | +Example usage:  | 
 | 60 | +
  | 
 | 61 | +```c++  | 
 | 62 | +glass = StandardMaterial("WindowGlass")  | 
 | 63 | +glass.roughness = 0  | 
 | 64 | +glass.metallic = 0  | 
 | 65 | +glass.indexOfRefraction = 1.52  | 
 | 66 | +glass.specularTransmission = 1  | 
 | 67 | +glass.doubleSided = True  | 
 | 68 | +glass.nestedPriority = 2  | 
 | 69 | +glass.volumeAbsorption = float3(2.0, 1.0, 1.5)  | 
 | 70 | +```  | 
 | 71 | + | 
 | 72 | +For more examples of how material's are created from Python, refer to the test scenes in `Media/TestScenes/`  | 
 | 73 | +(this directory is automatically fetched when the solution is built the first time).  | 
 | 74 | + | 
 | 75 | +## Material module (shader side)  | 
 | 76 | + | 
 | 77 | +On the shader side, each material class has a corresponding Slang module stored in `Falcor/Rendering/Materials/`.  | 
 | 78 | +These modules implement the `IMaterial` Slang interface (see `Rendering/Materials/IMaterial.slang`).  | 
 | 79 | + | 
 | 80 | +The main purpose of the material module is to:  | 
 | 81 | +1. hold the material data, and  | 
 | 82 | +2. hold the code for setting up a BSDF at a shading point.  | 
 | 83 | + | 
 | 84 | +The latter is referred to as "pattern generation", which may involve sampling textures, evaluating  | 
 | 85 | +procedural functions, and any other setup needed for shading.  | 
 | 86 | + | 
 | 87 | +The first data field in the material module has to be the material header. This should be followed by the  | 
 | 88 | +material payload as declared for the material type. For example, the standard material is declared:  | 
 | 89 | + | 
 | 90 | +```c++  | 
 | 91 | +struct StandardMaterial : IMaterial  | 
 | 92 | +{  | 
 | 93 | +    MaterialHeader header;  | 
 | 94 | +    BasicMaterialData data;  | 
 | 95 | +    ...  | 
 | 96 | +};  | 
 | 97 | +```  | 
 | 98 | + | 
 | 99 | +An instance of the material is created by calling the material system as follows:  | 
 | 100 | + | 
 | 101 | +```c++  | 
 | 102 | +IMaterial material = gScene.materials.getMaterial(materialID);  | 
 | 103 | +```  | 
 | 104 | + | 
 | 105 | +Internally, this function accesses the material header to fetch the material type, and then it calls  | 
 | 106 | +Slang's `createDynamicObject<..>` function to create an instance of the right type.  | 
 | 107 | +The opaque material data blob is cast to the data types used in the material module, so its fields are  | 
 | 108 | +directly accessible internally in the material module.  | 
 | 109 | + | 
 | 110 | +## BSDF module (shader side)  | 
 | 111 | + | 
 | 112 | +Each material module has an associated BSDF type, which implements the `IBSDF` Slang interface.  | 
 | 113 | +For example, `StandardMaterial` has an associated `StandardBSDF` type.  | 
 | 114 | + | 
 | 115 | +An instance of the BSDF type is created for a specific shading point in the scene, and it exposes  | 
 | 116 | +interfaces for evaluating and sampling the BSDF at that point.  | 
 | 117 | +The `IBSDF` interface also has functions for querying additional BSDF properties  | 
 | 118 | +at the shading point, such as albedo, emission, etc.  | 
 | 119 | + | 
 | 120 | +A BSDF instance is created by calling the following function on the material:  | 
 | 121 | + | 
 | 122 | +```c++  | 
 | 123 | +ShadingData sd = ...       // struct describing the shading point  | 
 | 124 | +ITextureSampler lod = ...  // method for texture level-of-detail computation  | 
 | 125 | + | 
 | 126 | +IBSDF bsdf = material.setupBSDF(gScene.materials, sd, lod);  | 
 | 127 | +```  | 
 | 128 | + | 
 | 129 | +Internally, the `setupBSDF` function accesses the material system to fetch/evaluate all resources needed at the  | 
 | 130 | +shading point. It returns an instance of the material's associated BSDF type,  | 
 | 131 | +which the caller can then use to evaluate or sample the BSDF at the shading point.  | 
 | 132 | + | 
 | 133 | +Since creating the material followed by instantiating the BSDF is very common,  | 
 | 134 | +there is a convenience function `getBSDF()` on `MaterialSystem` that does both operations in one step:  | 
 | 135 | + | 
 | 136 | +```c++  | 
 | 137 | +IBSDF bsdf = gScene.materials.getBSDF(sd, lod);  | 
 | 138 | +```  | 
 | 139 | + | 
 | 140 | +In the above interfaces, a `ShadingData` struct is needed to describe the shading point.  | 
 | 141 | +This is generated at a hit point by calling the `prepareShadingData()` function.  | 
 | 142 | +This function is responsible for setting up the shading frame (normal, tangent, bitangent)  | 
 | 143 | +including evaluating normal mapping and material opacity for alpha testing.  | 
 | 144 | + | 
 | 145 | +In addition to this, a `ITextureSampler` instance is needed to describe how textures should  | 
 | 146 | +be sampled (if there are any). The caller is responsible for deciding this based on which  | 
 | 147 | +method for texture LOD it is using (e.g. ray cones, ray differentials, fixed mip level, etc).  | 
 | 148 | +See available choices in `Scene/Material/TextureSampler.slang`).  | 
0 commit comments