SubstanceNG Gem

Project description

  • SubstanceNG is a re-implementation og the Substance Gem provided by default for Lumberyard.
  • I initiated this project when we realized while working on Lumberyard game that the default Substance Gem had serious limitations: mainly, it seemed to be used an old version of the substance engine, and thus, could not be used to load substance archives generated from Substance Designer 6 for instance (some simple substances could still work, but not the one using the new substance engine 6 features (?)).
  • So I started with some investigation on the available Susbtance plugins for the major engines, and in this process, found the Susbtance plugin for Unreal Engine 4. I downloaded this plugin, and analyzed the sources which were using a completely different API to access the substance engine. Turned out this version was using the substance engine 6.
  • Thus I started with a copy of the Substance Gem sources, and updated them progressively to incorporate this latest version of the Substance engine, and get ride of the all version in parallel.
  • The new substance gem also come with some minor improvements:
    • Support for emissive outputs from substance archives.
    • Support for Lumberyard material reloading when input parameters are changed and saved on a given substance.
  • Yet, for the moment, many of the flow graph nodes available in the legacy Substance Gem are not available yet in this Susbtance NG gem. To be added later ;-).

Skills & Techs

  • Lumberyard
  • C++


  • The sources for this project are available on github.


Implementation notes

  • It seems the gem is not rebuild when changed, need to call instead:
    lmbr_waf build_win_x64_vs2015_profile -p gems
  • Could successfully change the plugin window name to “Substance NG Editor”
  • Also, note that the Substance Editor menu tool bar button is not working with this new plugin.
  • Need to figure out how to link to an external library when building a gem: OK updated our gem wscript file with:
            libpath = [bld.Path('Gems/SubstanceNG/Code/Libs/Win64')],
            lib     = ['pfxlinkercommon','algcompression','tinyxml','substance_linker_static', 'substance_sse2_blend_static','substance_framework'],
            # could also add: 'substance_d3d11pc_blend_static' as engine ?
  • Checking if package can be created: OK (got invalid package as expected!)
  • Now trying to pass real data for package creation: OK
    • We should use SystemFile to read the content of a file.
    • We needto provide a full path for our file to be able to find/open it.
  • Now reading the content of the sbsar:
    • Retrieving graphs: OK
    • Retrieving the outputs: OK
  • Write the smtl file:
    • Got an error when updating the EBus interface for virtual bool CreateProceduralMaterial(const char* basePath, const char* sbsarPath, const char* smtlPath) = 0; ⇒ It seems we still reference the Subtance includes: OK fixed.
  • Now we are at the next error: Failed to create substance material, and with that we have the error message: ProceduralMaterial: Error loading substance (materials/substances/lava.sbsar) for material (materials/substances/lava.smtl)
  • So, the next step is the call to GetMaterialFromPath: note that this method should return NULL if the material file doesn't exist yet.
  • ERROR: We have the problem that the gem is trying to retrieve the Input at index 0 whereas we declared 0 inputs: fixed (⇒ stupid error)
  • Need to fill a STextureLoadData for our substance texture files: OK
  • We still have a problem with the error message: [Error] Unsupported substance pixel format: 28 28 in binary is: 00011100
    • 00 (from right side) ⇒ RAW compression
    • 11 ⇒ Substance_PF_RGBx|Substance_PF_RGB
    • 1 ⇒ 16b channels
  • OK: we now have support for proper import of sbsar files.
  • Add support for emissive texture in materials: OK
    • Not sure how to have Lumberyard find the emittance texture…
    • Where on earth do we specify that *.smtl files should be read as substance materials ?!
    • Could be this is not directly referenced: instead, the reference is done with the .mtl file created in the process (?)
    • Found that the .mtl file is create from QProceduralMaterialEditorMainWindow::CreateMaterial()
    • Checking if we can add support for emissive texture there: OK
    • Note: maybe ambient occlusion can be activated with the EFTT_OCCLUSION slot ?
  • Write the texture files when saving material with new name: OK
    • Avoid duplicating material when saving procedural mat:
    • ERROR: Could not link CMaterial::Reload() function…
  • When writing susbtance smtl files we should also write the input values: OK


  • Clean the Gem removing all references on the previous version of the Substance API
  • Add supprot for channel orders