Substance Functions Manual

About

The Substance functions allow to import and handle Allegorithmic Substance assets into a BaseDocument. In a document they can be used with shaders and materials. The Substance functions are defined in the lib_substance.h header file.

Access Assets

Substance assets store a reference to a Substance archive file (.sbsar) and the current value set of its parameters. These assets are stored in the BaseDocument.

// This example accesses the first Substance to loop through all Substances.
BaseList2D* substance = GetFirstSubstance(doc);
while (substance != nullptr)
{
ApplicationOutput("Substance: " + substance->GetName());
substance = substance->GetNext();
}
// This example accesses all selected Substances
if (substances == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
GetSubstances(doc, substances, true);
const Int32 substanceCount = substances->GetCount();
for (Int32 i = 0; i < substanceCount; ++i)
{
C4DAtom* const atom = substances->GetIndex(i);
const BaseList2D* const asset = static_cast<BaseList2D*>(atom);
if (asset == nullptr)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
ApplicationOutput("Selected Substance: " + asset->GetName());
}

Add Assets

A Substance asset can be imported using the Filename of a Substance archive file (.sbsar).

// This example imports a Substance asset with the given filename.
// Then a copy of that asset is created.
BaseList2D* substance = nullptr;
// import Substance
const SUBSTANCE_IMPORT_RESULT res = ImportSubstance(doc, filename, copy, false, false, true, &substance);
// check if the Substance was imported successfully
const Bool importFailure = res != SUBSTANCE_IMPORT_RESULT::SUCCESS;
const Bool invalidSubstance = substance == nullptr;
if (importFailure || invalidSubstance)
return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
// copy Substance
BaseList2D* const copySubstance = static_cast<BaseList2D*>(substance->GetClone(COPYFLAGS::NONE, nullptr));
if (copySubstance == nullptr)
return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
const String originalName = substance->GetName();
const String copyName = originalName + " Copy";
copySubstance->SetName(copyName);
// insert copy
if (!InsertLastSubstance(doc, copySubstance))
return maxon::UnknownError(MAXON_SOURCE_LOCATION);

Get Assets

A Substance asset can contain one or multiple graphs, input parameters and output bitmaps.

// This example loops through the graphs of the given Substance asset.
// The graph is then used to loop through the input parameters and output images.
void* graph = nullptr;
// loop through graphs
do
{
String name;
graph = GetSubstanceGraph(substance, graph, name);
if (graph != nullptr)
{
ApplicationOutput("Graph Name: " + name);
// loop through inputs
void* input = nullptr;
do
{
String inputName;
UInt32 inputID;
Int32 numberElements;
Int32 descID;
input = GetSubstanceInput(substance, graph, input, inputID, descID, numberElements, type, inputName);
if (input != nullptr)
ApplicationOutput("Input: " + inputName);
} while (input != nullptr);
// loop through outputs
void* output = nullptr;
do
{
UInt32 outputID;
String outputName;
output = GetSubstanceOutput(substance, graph, output, outputID, type, outputName, nullptr);
if (output != nullptr)
ApplicationOutput("Output: " + outputName);
} while (output != nullptr);
}
} while (graph != nullptr);

Materials and Shaders

Substance assets are used in shaders and are typically applied (but not limited) to materials:

// This example creates a material from a given Substance asset.
BaseMaterial* const material = CreateMaterial(substance, 0, mode);
if (material == nullptr)
return maxon::UnknownError(MAXON_SOURCE_LOCATION);
const String substanceName = substance->GetName();
const String materialName = substanceName + " Material";
material->SetName(materialName);
doc->InsertMaterial(material);

An example how to configure a Substance shader can be found on Substance Elements Manual.

Substance Preferences

These utility functions allow fast access to the most important Substance preferences.

Utility

Further utility functions are:

// This example checks if the given scene uses Substance assets in the materials.
// get first material
BaseMaterial* material = doc->GetFirstMaterial();
// check all materials
bool useSubstances = false;
while (material != nullptr)
{
// check if the given material uses Substances
if (MaterialUsesSubstance(material))
{
useSubstances = true;
break;
}
material = material->GetNext();
}
if (useSubstances)
ApplicationOutput("This scene uses Substances.");

Further Reading

GetFirstSubstance
BaseList2D * GetFirstSubstance(BaseDocument *const doc)
BaseList2D
Definition: c4d_baselist.h:2144
SUBSTANCE_IMPORT_RESULT::SUCCESS
@ SUCCESS
Success.
C4DAtom::GetClone
C4DAtom * GetClone(COPYFLAGS flags, AliasTrans *trn)
Definition: c4d_baselist.h:1417
GetSubstanceInput
void * GetSubstanceInput(BaseList2D *const asset, void *const graph, void *const prevInput, UInt32 &inputUid, Int32 &firstId, Int32 &numElements, SUBSTANCE_INPUT_TYPE &type, String &name)
UInt32
maxon::UInt32 UInt32
Definition: ge_sys_math.h:59
BaseList2D::GetNext
BaseList2D * GetNext()
Definition: c4d_baselist.h:2183
BaseDocument::GetFirstMaterial
BaseMaterial * GetFirstMaterial(void)
CreateMaterial
BaseMaterial * CreateMaterial(BaseList2D *const asset, Int32 graphIndex, SUBSTANCE_MATERIAL_MODE mode)
AtomArray::GetCount
Int32 GetCount() const
Definition: c4d_baselist.h:1619
MAXON_SOURCE_LOCATION
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:66
GetSubstanceGraph
void * GetSubstanceGraph(BaseList2D *const asset, void *const prevGraph, String &name)
PrefsGetMaterialModeSetting
SUBSTANCE_MATERIAL_MODE PrefsGetMaterialModeSetting()
ImportSubstance
SUBSTANCE_IMPORT_RESULT ImportSubstance(BaseDocument *const doc, const Filename &fn, SUBSTANCE_IMPORT_COPY &copyFile, Bool errPopup, Bool addUndo, Bool createMaterial, BaseList2D **assetPtr)
SUBSTANCE_OUTPUT_TYPE
SUBSTANCE_OUTPUT_TYPE
Definition: lib_substance.h:314
String
Definition: c4d_string.h:38
BaseDocument::InsertMaterial
void InsertMaterial(BaseMaterial *mat, BaseMaterial *pred=nullptr, Bool checknames=false)
GetSubstanceOutput
void * GetSubstanceOutput(BaseList2D *const asset, void *const graph, void *const prevOutput, UInt32 &outputUid, SUBSTANCE_OUTPUT_TYPE &type, String &name, BaseBitmap **bmpPtr)
SUBSTANCE_IMPORT_RESULT
SUBSTANCE_IMPORT_RESULT
Definition: lib_substance.h:265
SUBSTANCE_MATERIAL_MODE
SUBSTANCE_MATERIAL_MODE
Definition: lib_substance.h:251
SUBSTANCE_IMPORT_COPY::NO
@ NO
Do not copy file to project directory (absolute file path).
C4DAtom
Definition: c4d_baselist.h:1331
MaterialUsesSubstance
Bool MaterialUsesSubstance(BaseMaterial *const mat)
BaseList2D::SetName
void SetName(const maxon::String &name)
Definition: c4d_baselist.h:2324
Int32
maxon::Int32 Int32
Definition: ge_sys_math.h:58
ApplicationOutput
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:207
SUBSTANCE_INPUT_TYPE
SUBSTANCE_INPUT_TYPE
Definition: lib_substance.h:291
AutoAlloc
Definition: ge_autoptr.h:36
InsertLastSubstance
Bool InsertLastSubstance(BaseDocument *const doc, BaseList2D *asset)
GetSubstances
void GetSubstances(BaseDocument *const doc, AtomArray *arr, Bool onlySelected)
BaseMaterial::GetNext
BaseMaterial * GetNext(void)
Definition: c4d_basematerial.h:60
Bool
maxon::Bool Bool
Definition: ge_sys_math.h:53
BaseList2D::GetName
String GetName() const
Definition: c4d_baselist.h:2318
SUBSTANCE_IMPORT_COPY
SUBSTANCE_IMPORT_COPY
Definition: lib_substance.h:279
BaseMaterial
Definition: c4d_basematerial.h:27
COPYFLAGS::NONE
@ NONE
None.
AtomArray::GetIndex
C4DAtom * GetIndex(Int32 idx) const
Definition: c4d_baselist.h:1634