Skip to content
On this page

Impostor processor

For more detailed description please see impostor processor overview.

Impostor processor settings

This settings object contains the settings for the impostor generation that is performed by the impostor processor. These settings include parameters for choosing the impostor type and fetching the settings for that impostor type.

  • Billboard cloud settings, the settings controlling the billboard cloud generation
  • Flipbook settings, the settings controlling the flipbook generation
  • Impostor from single view settings, the settings controlling the single view impostor generation

Following settings objects are available in impostor processor:

Examples

The following examples shows how to use the different impostor types.

Billboard cloud, mode: Foliage

This example shows how to use the Impostor processor type: Billboard cloud with mode: Foliage.

cpp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

#include <string>
#include <stdlib.h>
#include <filesystem>
#include <future>
#include "SimplygonLoader.h"


Simplygon::spScene LoadScene(Simplygon::ISimplygon* sg, const char* path)
{
	// Create scene importer 
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath(path);
	
	// Run scene importer. 
	auto importResult = sgSceneImporter->Run();
	if (Simplygon::Failed(importResult))
	{
		throw std::exception("Failed to load scene.");
	}
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();
	return sgScene;
}

void SaveScene(Simplygon::ISimplygon* sg, Simplygon::spScene sgScene, const char* path)
{
	// Create scene exporter. 
	Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
	std::string outputScenePath = std::string("output\\") + std::string("ImpostorBillboardCloudFoliage") + std::string("_") + std::string(path);
	sgSceneExporter->SetExportFilePath(outputScenePath.c_str());
	sgSceneExporter->SetScene(sgScene);
	
	// Run scene exporter. 
	auto exportResult = sgSceneExporter->Run();
	if (Simplygon::Failed(exportResult))
	{
		throw std::exception("Failed to save scene.");
	}
}

void CheckLog(Simplygon::ISimplygon* sg)
{
	// Check if any errors occurred. 
	bool hasErrors = sg->ErrorOccurred();
	if (hasErrors)
	{
		Simplygon::spStringArray errors = sg->CreateStringArray();
		sg->GetErrorMessages(errors);
		auto errorCount = errors->GetItemCount();
		if (errorCount > 0)
		{
			printf("%s\n", "CheckLog: Errors:");
			for (auto errorIndex = 0U; errorIndex < errorCount; ++errorIndex)
			{
				Simplygon::spString errorString = errors->GetItem((int)errorIndex);
				printf("%s\n", errorString.c_str());
			}
			sg->ClearErrorMessages();
		}
	}
	else
	{
		printf("%s\n", "CheckLog: No errors.");
	}
	
	// Check if any warnings occurred. 
	bool hasWarnings = sg->WarningOccurred();
	if (hasWarnings)
	{
		Simplygon::spStringArray warnings = sg->CreateStringArray();
		sg->GetWarningMessages(warnings);
		auto warningCount = warnings->GetItemCount();
		if (warningCount > 0)
		{
			printf("%s\n", "CheckLog: Warnings:");
			for (auto warningIndex = 0U; warningIndex < warningCount; ++warningIndex)
			{
				Simplygon::spString warningString = warnings->GetItem((int)warningIndex);
				printf("%s\n", warningString.c_str());
			}
			sg->ClearWarningMessages();
		}
	}
	else
	{
		printf("%s\n", "CheckLog: No warnings.");
	}
	
	// Error out if Simplygon has errors. 
	if (hasErrors)
	{
		throw std::exception("Processing failed with an error");
	}
}

void RunBillboardCloudFoliage(Simplygon::ISimplygon* sg)
{
	// Load scene to process. 	
	printf("%s\n", "Load scene to process.");
	Simplygon::spScene sgScene = LoadScene(sg, "../../../Assets/Bush/Bush.fbx");
	
	// For all materials in the scene set the blend mode to blend (instead of opaque) 
	for (int i = 0; i < (int)sgScene->GetMaterialTable()->GetMaterialsCount(); ++i)
	{
		sgScene->GetMaterialTable()->GetMaterial(i)->SetBlendMode(Simplygon::EMaterialBlendMode::Blend);
	}
	
	// Create the Impostor processor. 
	Simplygon::spImpostorProcessor sgImpostorProcessor = sg->CreateImpostorProcessor();
	sgImpostorProcessor->SetScene( sgScene );
	Simplygon::spImpostorSettings sgImpostorSettings = sgImpostorProcessor->GetImpostorSettings();
	
	// Set impostor type to Billboard cloud. 
	sgImpostorSettings->SetImpostorType( Simplygon::EImpostorType::BillboardCloud );
	Simplygon::spBillboardCloudSettings sgBillboardCloudSettings = sgImpostorSettings->GetBillboardCloudSettings();
	
	// Set billboard cloud mode to Foliage. 
	sgBillboardCloudSettings->SetBillboardMode( Simplygon::EBillboardMode::Foliage );
	sgBillboardCloudSettings->SetBillboardDensity( 0.5f );
	sgBillboardCloudSettings->SetGeometricComplexity( 0.9f );
	sgBillboardCloudSettings->SetMaxPlaneCount( 10 );
	sgBillboardCloudSettings->SetTwoSided( true );
	Simplygon::spFoliageSettings sgFoliageSettings = sgBillboardCloudSettings->GetFoliageSettings();
	
	// Set the parameters for separating foliage and trunk. 
	sgFoliageSettings->SetSeparateTrunkAndFoliage( true );
	sgFoliageSettings->SetSeparateFoliageTriangleRatio( 0.5f );
	sgFoliageSettings->SetSeparateFoliageTriangleThreshold( 10 );
	sgFoliageSettings->SetSeparateFoliageAreaThreshold( 0.1f );
	sgFoliageSettings->SetSeparateFoliageSizeThreshold( 0.1f );
	sgFoliageSettings->SetTrunkReductionRatio( 0.5f );
	Simplygon::spMappingImageSettings sgMappingImageSettings = sgImpostorProcessor->GetMappingImageSettings();
	sgMappingImageSettings->SetMaximumLayers( 10 );
	Simplygon::spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings->GetOutputMaterialSettings(0);
	
	// Setting the size of the output material for the mapping image. This will be the output size of the 
	// textures when we do material casting in a later stage. 
	sgOutputMaterialSettings->SetTextureWidth( 1024 );
	sgOutputMaterialSettings->SetTextureHeight( 1024 );
	sgOutputMaterialSettings->SetMultisamplingLevel( 2 );
	
	// Start the impostor process. 	
	printf("%s\n", "Start the impostor process.");
	sgImpostorProcessor->RunProcessing();
	
	// Setup and run the diffuse material casting. 	
	printf("%s\n", "Setup and run the diffuse material casting.");
	Simplygon::spColorCaster sgDiffuseCaster = sg->CreateColorCaster();
	sgDiffuseCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgDiffuseCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgDiffuseCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgDiffuseCaster->SetOutputFilePath( "DiffuseTexture" );

	Simplygon::spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster->GetColorCasterSettings();
	sgDiffuseCasterSettings->SetMaterialChannel( "Diffuse" );
	sgDiffuseCasterSettings->SetOpacityChannel( "Opacity" );
	sgDiffuseCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgDiffuseCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgDiffuseCasterSettings->SetBakeOpacityInAlpha( false );
	sgDiffuseCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8G8B8 );
	sgDiffuseCasterSettings->SetDilation( 10 );
	sgDiffuseCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgDiffuseCaster->RunProcessing();
	std::string diffuseTextureFilePath = sgDiffuseCaster->GetOutputFilePath().c_str();
	
	// Setup and run the specular material casting. 	
	printf("%s\n", "Setup and run the specular material casting.");
	Simplygon::spColorCaster sgSpecularCaster = sg->CreateColorCaster();
	sgSpecularCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgSpecularCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgSpecularCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgSpecularCaster->SetOutputFilePath( "SpecularTexture" );

	Simplygon::spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster->GetColorCasterSettings();
	sgSpecularCasterSettings->SetMaterialChannel( "Specular" );
	sgSpecularCasterSettings->SetOpacityChannel( "Opacity" );
	sgSpecularCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgSpecularCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgSpecularCasterSettings->SetDilation( 10 );
	sgSpecularCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgSpecularCaster->RunProcessing();
	std::string specularTextureFilePath = sgSpecularCaster->GetOutputFilePath().c_str();
	
	// Setup and run the normals material casting. 	
	printf("%s\n", "Setup and run the normals material casting.");
	Simplygon::spNormalCaster sgNormalsCaster = sg->CreateNormalCaster();
	sgNormalsCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgNormalsCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgNormalsCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgNormalsCaster->SetOutputFilePath( "NormalsTexture" );

	Simplygon::spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster->GetNormalCasterSettings();
	sgNormalsCasterSettings->SetMaterialChannel( "Normals" );
	sgNormalsCasterSettings->SetGenerateTangentSpaceNormals( true );
	sgNormalsCasterSettings->SetOpacityChannel( "Opacity" );
	sgNormalsCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgNormalsCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgNormalsCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8G8B8 );
	sgNormalsCasterSettings->SetDilation( 10 );
	sgNormalsCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgNormalsCaster->RunProcessing();
	std::string normalsTextureFilePath = sgNormalsCaster->GetOutputFilePath().c_str();
	
	// Setup and run the opacity material casting. Make sure there is no dilation or fill. 	
	printf("%s\n", "Setup and run the opacity material casting. Make sure there is no dilation or fill.");
	Simplygon::spOpacityCaster sgOpacityCaster = sg->CreateOpacityCaster();
	sgOpacityCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgOpacityCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgOpacityCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgOpacityCaster->SetOutputFilePath( "OpacityTexture" );

	Simplygon::spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster->GetOpacityCasterSettings();
	sgOpacityCasterSettings->SetMaterialChannel( "Opacity" );
	sgOpacityCasterSettings->SetOpacityChannel( "Opacity" );
	sgOpacityCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgOpacityCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgOpacityCasterSettings->SetDilation( 0 );
	sgOpacityCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::NoFill );
	sgOpacityCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8 );

	sgOpacityCaster->RunProcessing();
	std::string opacityTextureFilePath = sgOpacityCaster->GetOutputFilePath().c_str();
	
	// Update scene with new casted textures. 
	Simplygon::spMaterialTable sgMaterialTable = sgScene->GetMaterialTable();
	Simplygon::spTextureTable sgTextureTable = sgScene->GetTextureTable();
	Simplygon::spMaterial sgMaterial = sgMaterialTable->GetMaterial(sgImpostorProcessor->GetBillboardCloudMaterialId());

	Simplygon::spTexture sgDiffuseTexture = sg->CreateTexture();
	sgDiffuseTexture->SetName( "Diffuse" );
	sgDiffuseTexture->SetFilePath( diffuseTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgDiffuseTexture );

	Simplygon::spShadingTextureNode sgDiffuseTextureShadingNode = sg->CreateShadingTextureNode();
	sgDiffuseTextureShadingNode->SetTexCoordLevel( 0 );
	sgDiffuseTextureShadingNode->SetTextureName( "Diffuse" );
	sgMaterial->AddMaterialChannel( "Diffuse" );
	sgMaterial->SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );

	Simplygon::spTexture sgSpecularTexture = sg->CreateTexture();
	sgSpecularTexture->SetName( "Specular" );
	sgSpecularTexture->SetFilePath( specularTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgSpecularTexture );

	Simplygon::spShadingTextureNode sgSpecularTextureShadingNode = sg->CreateShadingTextureNode();
	sgSpecularTextureShadingNode->SetTexCoordLevel( 0 );
	sgSpecularTextureShadingNode->SetTextureName( "Specular" );
	sgMaterial->AddMaterialChannel( "Specular" );
	sgMaterial->SetShadingNetwork( "Specular", sgSpecularTextureShadingNode );

	Simplygon::spTexture sgNormalsTexture = sg->CreateTexture();
	sgNormalsTexture->SetName( "Normals" );
	sgNormalsTexture->SetFilePath( normalsTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgNormalsTexture );

	Simplygon::spShadingTextureNode sgNormalsTextureShadingNode = sg->CreateShadingTextureNode();
	sgNormalsTextureShadingNode->SetTexCoordLevel( 0 );
	sgNormalsTextureShadingNode->SetTextureName( "Normals" );
	sgMaterial->AddMaterialChannel( "Normals" );
	sgMaterial->SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );

	Simplygon::spTexture sgOpacityTexture = sg->CreateTexture();
	sgOpacityTexture->SetName( "Opacity" );
	sgOpacityTexture->SetFilePath( opacityTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgOpacityTexture );

	Simplygon::spShadingTextureNode sgOpacityTextureShadingNode = sg->CreateShadingTextureNode();
	sgOpacityTextureShadingNode->SetTexCoordLevel( 0 );
	sgOpacityTextureShadingNode->SetTextureName( "Opacity" );
	sgMaterial->AddMaterialChannel( "Opacity" );
	sgMaterial->SetShadingNetwork( "Opacity", sgOpacityTextureShadingNode );
	sgMaterial->SetBlendMode(Simplygon::EMaterialBlendMode::Mask);
	
	// Save processed scene. 	
	printf("%s\n", "Save processed scene.");
	SaveScene(sg, sgScene, "Output.glb");
	
	// Check log for any warnings or errors. 	
	printf("%s\n", "Check log for any warnings or errors.");
	CheckLog(sg);
}

int main()
{
	Simplygon::ISimplygon* sg = NULL;
	Simplygon::EErrorCodes initval = Simplygon::Initialize( &sg );
	if( initval != Simplygon::EErrorCodes::NoError )
	{
		printf( "Failed to initialize Simplygon: ErrorCode(%d)", (int)initval );
		return int(initval);
	}

	RunBillboardCloudFoliage(sg);

	Simplygon::Deinitialize(sg);

	return 0;
}
csharp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

using System;
using System.IO;
using System.Threading.Tasks;

public class Program
{
    static Simplygon.spScene LoadScene(Simplygon.ISimplygon sg, string path)
    {
        // Create scene importer 
        using Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter();
        sgSceneImporter.SetImportFilePath(path);
        
        // Run scene importer. 
        var importResult = sgSceneImporter.Run();
        if (Simplygon.Simplygon.Failed(importResult))
        {
            throw new System.Exception("Failed to load scene.");
        }
        Simplygon.spScene sgScene = sgSceneImporter.GetScene();
        return sgScene;
    }

    static void SaveScene(Simplygon.ISimplygon sg, Simplygon.spScene sgScene, string path)
    {
        // Create scene exporter. 
        using Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter();
        string outputScenePath = string.Join("", new string[] { "output\\", "ImpostorBillboardCloudFoliage", "_", path });
        sgSceneExporter.SetExportFilePath(outputScenePath);
        sgSceneExporter.SetScene(sgScene);
        
        // Run scene exporter. 
        var exportResult = sgSceneExporter.Run();
        if (Simplygon.Simplygon.Failed(exportResult))
        {
            throw new System.Exception("Failed to save scene.");
        }
    }

    static void CheckLog(Simplygon.ISimplygon sg)
    {
        // Check if any errors occurred. 
        bool hasErrors = sg.ErrorOccurred();
        if (hasErrors)
        {
            Simplygon.spStringArray errors = sg.CreateStringArray();
            sg.GetErrorMessages(errors);
            var errorCount = errors.GetItemCount();
            if (errorCount > 0)
            {
                Console.WriteLine("CheckLog: Errors:");
                for (uint errorIndex = 0; errorIndex < errorCount; ++errorIndex)
                {
                    string errorString = errors.GetItem((int)errorIndex);
                    Console.WriteLine(errorString);
                }
                sg.ClearErrorMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No errors.");
        }
        
        // Check if any warnings occurred. 
        bool hasWarnings = sg.WarningOccurred();
        if (hasWarnings)
        {
            Simplygon.spStringArray warnings = sg.CreateStringArray();
            sg.GetWarningMessages(warnings);
            var warningCount = warnings.GetItemCount();
            if (warningCount > 0)
            {
                Console.WriteLine("CheckLog: Warnings:");
                for (uint warningIndex = 0; warningIndex < warningCount; ++warningIndex)
                {
                    string warningString = warnings.GetItem((int)warningIndex);
                    Console.WriteLine(warningString);
                }
                sg.ClearWarningMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No warnings.");
        }
        
        // Error out if Simplygon has errors. 
        if (hasErrors)
        {
            throw new System.Exception("Processing failed with an error");
        }
    }

    static void RunBillboardCloudFoliage(Simplygon.ISimplygon sg)
    {
        // Load scene to process.         
        Console.WriteLine("Load scene to process.");
        Simplygon.spScene sgScene = LoadScene(sg, "../../../Assets/Bush/Bush.fbx");
        
        // For all materials in the scene set the blend mode to blend (instead of opaque) 
        for (int i = 0; i < (int)sgScene.GetMaterialTable().GetMaterialsCount(); ++i)
        {
            sgScene.GetMaterialTable().GetMaterial(i).SetBlendMode(Simplygon.EMaterialBlendMode.Blend);
        }
        
        // Create the Impostor processor. 
        using Simplygon.spImpostorProcessor sgImpostorProcessor = sg.CreateImpostorProcessor();
        sgImpostorProcessor.SetScene( sgScene );
        using Simplygon.spImpostorSettings sgImpostorSettings = sgImpostorProcessor.GetImpostorSettings();
        
        // Set impostor type to Billboard cloud. 
        sgImpostorSettings.SetImpostorType( Simplygon.EImpostorType.BillboardCloud );
        using Simplygon.spBillboardCloudSettings sgBillboardCloudSettings = sgImpostorSettings.GetBillboardCloudSettings();
        
        // Set billboard cloud mode to Foliage. 
        sgBillboardCloudSettings.SetBillboardMode( Simplygon.EBillboardMode.Foliage );
        sgBillboardCloudSettings.SetBillboardDensity( 0.5f );
        sgBillboardCloudSettings.SetGeometricComplexity( 0.9f );
        sgBillboardCloudSettings.SetMaxPlaneCount( 10 );
        sgBillboardCloudSettings.SetTwoSided( true );
        using Simplygon.spFoliageSettings sgFoliageSettings = sgBillboardCloudSettings.GetFoliageSettings();
        
        // Set the parameters for separating foliage and trunk. 
        sgFoliageSettings.SetSeparateTrunkAndFoliage( true );
        sgFoliageSettings.SetSeparateFoliageTriangleRatio( 0.5f );
        sgFoliageSettings.SetSeparateFoliageTriangleThreshold( 10 );
        sgFoliageSettings.SetSeparateFoliageAreaThreshold( 0.1f );
        sgFoliageSettings.SetSeparateFoliageSizeThreshold( 0.1f );
        sgFoliageSettings.SetTrunkReductionRatio( 0.5f );
        using Simplygon.spMappingImageSettings sgMappingImageSettings = sgImpostorProcessor.GetMappingImageSettings();
        sgMappingImageSettings.SetMaximumLayers( 10 );
        using Simplygon.spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0);
        
        // Setting the size of the output material for the mapping image. This will be the output size of the 
        // textures when we do material casting in a later stage. 
        sgOutputMaterialSettings.SetTextureWidth( 1024 );
        sgOutputMaterialSettings.SetTextureHeight( 1024 );
        sgOutputMaterialSettings.SetMultisamplingLevel( 2 );
        
        // Start the impostor process.         
        Console.WriteLine("Start the impostor process.");
        sgImpostorProcessor.RunProcessing();
        
        // Setup and run the diffuse material casting.         
        Console.WriteLine("Setup and run the diffuse material casting.");
        string diffuseTextureFilePath;
        using Simplygon.spColorCaster sgDiffuseCaster = sg.CreateColorCaster();
        sgDiffuseCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgDiffuseCaster.SetOutputFilePath( "DiffuseTexture" );

        using Simplygon.spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings();
        sgDiffuseCasterSettings.SetMaterialChannel( "Diffuse" );
        sgDiffuseCasterSettings.SetOpacityChannel( "Opacity" );
        sgDiffuseCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgDiffuseCasterSettings.SetBakeOpacityInAlpha( false );
        sgDiffuseCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8G8B8 );
        sgDiffuseCasterSettings.SetDilation( 10 );
        sgDiffuseCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgDiffuseCaster.RunProcessing();
        diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath();
        
        // Setup and run the specular material casting.         
        Console.WriteLine("Setup and run the specular material casting.");
        string specularTextureFilePath;
        using Simplygon.spColorCaster sgSpecularCaster = sg.CreateColorCaster();
        sgSpecularCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgSpecularCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgSpecularCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgSpecularCaster.SetOutputFilePath( "SpecularTexture" );

        using Simplygon.spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster.GetColorCasterSettings();
        sgSpecularCasterSettings.SetMaterialChannel( "Specular" );
        sgSpecularCasterSettings.SetOpacityChannel( "Opacity" );
        sgSpecularCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgSpecularCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgSpecularCasterSettings.SetDilation( 10 );
        sgSpecularCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgSpecularCaster.RunProcessing();
        specularTextureFilePath = sgSpecularCaster.GetOutputFilePath();
        
        // Setup and run the normals material casting.         
        Console.WriteLine("Setup and run the normals material casting.");
        string normalsTextureFilePath;
        using Simplygon.spNormalCaster sgNormalsCaster = sg.CreateNormalCaster();
        sgNormalsCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgNormalsCaster.SetOutputFilePath( "NormalsTexture" );

        using Simplygon.spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings();
        sgNormalsCasterSettings.SetMaterialChannel( "Normals" );
        sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( true );
        sgNormalsCasterSettings.SetOpacityChannel( "Opacity" );
        sgNormalsCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgNormalsCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8G8B8 );
        sgNormalsCasterSettings.SetDilation( 10 );
        sgNormalsCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgNormalsCaster.RunProcessing();
        normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath();
        
        // Setup and run the opacity material casting. Make sure there is no dilation or fill.         
        Console.WriteLine("Setup and run the opacity material casting. Make sure there is no dilation or fill.");
        string opacityTextureFilePath;
        using Simplygon.spOpacityCaster sgOpacityCaster = sg.CreateOpacityCaster();
        sgOpacityCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgOpacityCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgOpacityCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgOpacityCaster.SetOutputFilePath( "OpacityTexture" );

        using Simplygon.spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster.GetOpacityCasterSettings();
        sgOpacityCasterSettings.SetMaterialChannel( "Opacity" );
        sgOpacityCasterSettings.SetOpacityChannel( "Opacity" );
        sgOpacityCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgOpacityCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgOpacityCasterSettings.SetDilation( 0 );
        sgOpacityCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.NoFill );
        sgOpacityCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8 );

        sgOpacityCaster.RunProcessing();
        opacityTextureFilePath = sgOpacityCaster.GetOutputFilePath();
        
        // Update scene with new casted textures. 
        using Simplygon.spMaterialTable sgMaterialTable = sgScene.GetMaterialTable();
        using Simplygon.spTextureTable sgTextureTable = sgScene.GetTextureTable();
        using Simplygon.spMaterial sgMaterial = sgMaterialTable.GetMaterial(sgImpostorProcessor.GetBillboardCloudMaterialId());

        using Simplygon.spTexture sgDiffuseTexture = sg.CreateTexture();
        sgDiffuseTexture.SetName( "Diffuse" );
        sgDiffuseTexture.SetFilePath( diffuseTextureFilePath );
        sgTextureTable.AddTexture( sgDiffuseTexture );

        using Simplygon.spShadingTextureNode sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode();
        sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 );
        sgDiffuseTextureShadingNode.SetTextureName( "Diffuse" );

        sgMaterial.AddMaterialChannel( "Diffuse" );
        sgMaterial.SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );

        using Simplygon.spTexture sgSpecularTexture = sg.CreateTexture();
        sgSpecularTexture.SetName( "Specular" );
        sgSpecularTexture.SetFilePath( specularTextureFilePath );
        sgTextureTable.AddTexture( sgSpecularTexture );

        using Simplygon.spShadingTextureNode sgSpecularTextureShadingNode = sg.CreateShadingTextureNode();
        sgSpecularTextureShadingNode.SetTexCoordLevel( 0 );
        sgSpecularTextureShadingNode.SetTextureName( "Specular" );

        sgMaterial.AddMaterialChannel( "Specular" );
        sgMaterial.SetShadingNetwork( "Specular", sgSpecularTextureShadingNode );

        using Simplygon.spTexture sgNormalsTexture = sg.CreateTexture();
        sgNormalsTexture.SetName( "Normals" );
        sgNormalsTexture.SetFilePath( normalsTextureFilePath );
        sgTextureTable.AddTexture( sgNormalsTexture );

        using Simplygon.spShadingTextureNode sgNormalsTextureShadingNode = sg.CreateShadingTextureNode();
        sgNormalsTextureShadingNode.SetTexCoordLevel( 0 );
        sgNormalsTextureShadingNode.SetTextureName( "Normals" );

        sgMaterial.AddMaterialChannel( "Normals" );
        sgMaterial.SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );

        using Simplygon.spTexture sgOpacityTexture = sg.CreateTexture();
        sgOpacityTexture.SetName( "Opacity" );
        sgOpacityTexture.SetFilePath( opacityTextureFilePath );
        sgTextureTable.AddTexture( sgOpacityTexture );

        using Simplygon.spShadingTextureNode sgOpacityTextureShadingNode = sg.CreateShadingTextureNode();
        sgOpacityTextureShadingNode.SetTexCoordLevel( 0 );
        sgOpacityTextureShadingNode.SetTextureName( "Opacity" );

        sgMaterial.AddMaterialChannel( "Opacity" );
        sgMaterial.SetShadingNetwork( "Opacity", sgOpacityTextureShadingNode );
        sgMaterial.SetBlendMode(Simplygon.EMaterialBlendMode.Mask);
        
        // Save processed scene.         
        Console.WriteLine("Save processed scene.");
        SaveScene(sg, sgScene, "Output.glb");
        
        // Check log for any warnings or errors.         
        Console.WriteLine("Check log for any warnings or errors.");
        CheckLog(sg);
    }

    static int Main(string[] args)
    {
        using var sg = Simplygon.Loader.InitSimplygon(out var errorCode, out var errorMessage);
        if (errorCode != Simplygon.EErrorCodes.NoError)
        {
            Console.WriteLine( $"Failed to initialize Simplygon: ErrorCode({(int)errorCode}) {errorMessage}" );
            return (int)errorCode;
        }
        RunBillboardCloudFoliage(sg);

        return 0;
    }

}
python
# Copyright (c) Microsoft Corporation. 
# Licensed under the MIT License. 

import math
import os
import sys
import glob
import gc
import threading

from pathlib import Path
from simplygon10 import simplygon_loader
from simplygon10 import Simplygon


def LoadScene(sg: Simplygon.ISimplygon, path: str):
    # Create scene importer 
    sgSceneImporter = sg.CreateSceneImporter()
    sgSceneImporter.SetImportFilePath(path)
    
    # Run scene importer. 
    importResult = sgSceneImporter.Run()
    if Simplygon.Failed(importResult):
        raise Exception('Failed to load scene.')
    sgScene = sgSceneImporter.GetScene()
    return sgScene

def SaveScene(sg: Simplygon.ISimplygon, sgScene: Simplygon.spScene, path: str):
    # Create scene exporter. 
    sgSceneExporter = sg.CreateSceneExporter()
    outputScenePath = ''.join(['output\\', 'ImpostorBillboardCloudFoliage', '_', path])
    sgSceneExporter.SetExportFilePath(outputScenePath)
    sgSceneExporter.SetScene(sgScene)
    
    # Run scene exporter. 
    exportResult = sgSceneExporter.Run()
    if Simplygon.Failed(exportResult):
        raise Exception('Failed to save scene.')

def CheckLog(sg: Simplygon.ISimplygon):
    # Check if any errors occurred. 
    hasErrors = sg.ErrorOccurred()
    if hasErrors:
        errors = sg.CreateStringArray()
        sg.GetErrorMessages(errors)
        errorCount = errors.GetItemCount()
        if errorCount > 0:
            print('CheckLog: Errors:')
            for errorIndex in range(errorCount):
                errorString = errors.GetItem(errorIndex)
                print(errorString)
            sg.ClearErrorMessages()
    else:
        print('CheckLog: No errors.')
    
    # Check if any warnings occurred. 
    hasWarnings = sg.WarningOccurred()
    if hasWarnings:
        warnings = sg.CreateStringArray()
        sg.GetWarningMessages(warnings)
        warningCount = warnings.GetItemCount()
        if warningCount > 0:
            print('CheckLog: Warnings:')
            for warningIndex in range(warningCount):
                warningString = warnings.GetItem(warningIndex)
                print(warningString)
            sg.ClearWarningMessages()
    else:
        print('CheckLog: No warnings.')
    
    # Error out if Simplygon has errors. 
    if hasErrors:
        raise Exception('Processing failed with an error')

def RunBillboardCloudFoliage(sg: Simplygon.ISimplygon):
    # Load scene to process.     
    print("Load scene to process.")
    sgScene = LoadScene(sg, '../../../Assets/Bush/Bush.fbx')
    
    # For all materials in the scene set the blend mode to blend (instead of opaque) 
    materialCount = sgScene.GetMaterialTable().GetMaterialsCount()
    for i in range(0, materialCount):
        sgScene.GetMaterialTable().GetMaterial(i).SetBlendMode(Simplygon.EMaterialBlendMode_Blend)
    
    # Create the Impostor processor. 
    sgImpostorProcessor = sg.CreateImpostorProcessor()
    sgImpostorProcessor.SetScene( sgScene )
    sgImpostorSettings = sgImpostorProcessor.GetImpostorSettings()
    
    # Set impostor type to Billboard cloud. 
    sgImpostorSettings.SetImpostorType( Simplygon.EImpostorType_BillboardCloud )
    sgBillboardCloudSettings = sgImpostorSettings.GetBillboardCloudSettings()
    
    # Set billboard cloud mode to Foliage. 
    sgBillboardCloudSettings.SetBillboardMode( Simplygon.EBillboardMode_Foliage )
    sgBillboardCloudSettings.SetBillboardDensity( 0.5 )
    sgBillboardCloudSettings.SetGeometricComplexity( 0.9 )
    sgBillboardCloudSettings.SetMaxPlaneCount( 10 )
    sgBillboardCloudSettings.SetTwoSided( True )
    sgFoliageSettings = sgBillboardCloudSettings.GetFoliageSettings()
    
    # Set the parameters for separating foliage and trunk. 
    sgFoliageSettings.SetSeparateTrunkAndFoliage( True )
    sgFoliageSettings.SetSeparateFoliageTriangleRatio( 0.5 )
    sgFoliageSettings.SetSeparateFoliageTriangleThreshold( 10 )
    sgFoliageSettings.SetSeparateFoliageAreaThreshold( 0.1 )
    sgFoliageSettings.SetSeparateFoliageSizeThreshold( 0.1 )
    sgFoliageSettings.SetTrunkReductionRatio( 0.5 )
    sgMappingImageSettings = sgImpostorProcessor.GetMappingImageSettings()
    sgMappingImageSettings.SetMaximumLayers( 10 )
    sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0)
    
    # Setting the size of the output material for the mapping image. This will be the output size of the 
    # textures when we do material casting in a later stage. 
    sgOutputMaterialSettings.SetTextureWidth( 1024 )
    sgOutputMaterialSettings.SetTextureHeight( 1024 )
    sgOutputMaterialSettings.SetMultisamplingLevel( 2 )
    
    # Start the impostor process.     
    print("Start the impostor process.")
    sgImpostorProcessor.RunProcessing()
    
    # Setup and run the diffuse material casting.     
    print("Setup and run the diffuse material casting.")
    sgDiffuseCaster = sg.CreateColorCaster()
    sgDiffuseCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgDiffuseCaster.SetOutputFilePath( 'DiffuseTexture' )

    sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings()
    sgDiffuseCasterSettings.SetMaterialChannel( 'Diffuse' )
    sgDiffuseCasterSettings.SetOpacityChannel( 'Opacity' )
    sgDiffuseCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgDiffuseCasterSettings.SetBakeOpacityInAlpha( False )
    sgDiffuseCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8G8B8 )
    sgDiffuseCasterSettings.SetDilation( 10 )
    sgDiffuseCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgDiffuseCaster.RunProcessing()
    diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath()
    
    # Setup and run the specular material casting.     
    print("Setup and run the specular material casting.")
    sgSpecularCaster = sg.CreateColorCaster()
    sgSpecularCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgSpecularCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgSpecularCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgSpecularCaster.SetOutputFilePath( 'SpecularTexture' )

    sgSpecularCasterSettings = sgSpecularCaster.GetColorCasterSettings()
    sgSpecularCasterSettings.SetMaterialChannel( 'Specular' )
    sgSpecularCasterSettings.SetOpacityChannel( 'Opacity' )
    sgSpecularCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgSpecularCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgSpecularCasterSettings.SetDilation( 10 )
    sgSpecularCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgSpecularCaster.RunProcessing()
    specularTextureFilePath = sgSpecularCaster.GetOutputFilePath()
    
    # Setup and run the normals material casting.     
    print("Setup and run the normals material casting.")
    sgNormalsCaster = sg.CreateNormalCaster()
    sgNormalsCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgNormalsCaster.SetOutputFilePath( 'NormalsTexture' )

    sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings()
    sgNormalsCasterSettings.SetMaterialChannel( 'Normals' )
    sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( True )
    sgNormalsCasterSettings.SetOpacityChannel( 'Opacity' )
    sgNormalsCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgNormalsCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8G8B8 )
    sgNormalsCasterSettings.SetDilation( 10 )
    sgNormalsCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgNormalsCaster.RunProcessing()
    normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath()
    
    # Setup and run the opacity material casting. Make sure there is no dilation or fill.     
    print("Setup and run the opacity material casting. Make sure there is no dilation or fill.")
    sgOpacityCaster = sg.CreateOpacityCaster()
    sgOpacityCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgOpacityCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgOpacityCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgOpacityCaster.SetOutputFilePath( 'OpacityTexture' )

    sgOpacityCasterSettings = sgOpacityCaster.GetOpacityCasterSettings()
    sgOpacityCasterSettings.SetMaterialChannel( 'Opacity' )
    sgOpacityCasterSettings.SetOpacityChannel( 'Opacity' )
    sgOpacityCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgOpacityCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgOpacityCasterSettings.SetDilation( 0 )
    sgOpacityCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_NoFill )
    sgOpacityCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8 )

    sgOpacityCaster.RunProcessing()
    opacityTextureFilePath = sgOpacityCaster.GetOutputFilePath()
    
    # Update scene with new casted textures. 
    sgMaterialTable = sgScene.GetMaterialTable()
    sgTextureTable = sgScene.GetTextureTable()
    sgMaterial = sgMaterialTable.GetMaterial(sgImpostorProcessor.GetBillboardCloudMaterialId())

    sgDiffuseTexture = sg.CreateTexture()
    sgDiffuseTexture.SetName( 'Diffuse' )
    sgDiffuseTexture.SetFilePath( diffuseTextureFilePath )
    sgTextureTable.AddTexture( sgDiffuseTexture )

    sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode()
    sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 )
    sgDiffuseTextureShadingNode.SetTextureName( 'Diffuse' )

    sgMaterial.AddMaterialChannel( 'Diffuse' )
    sgMaterial.SetShadingNetwork( 'Diffuse', sgDiffuseTextureShadingNode )

    sgSpecularTexture = sg.CreateTexture()
    sgSpecularTexture.SetName( 'Specular' )
    sgSpecularTexture.SetFilePath( specularTextureFilePath )
    sgTextureTable.AddTexture( sgSpecularTexture )

    sgSpecularTextureShadingNode = sg.CreateShadingTextureNode()
    sgSpecularTextureShadingNode.SetTexCoordLevel( 0 )
    sgSpecularTextureShadingNode.SetTextureName( 'Specular' )

    sgMaterial.AddMaterialChannel( 'Specular' )
    sgMaterial.SetShadingNetwork( 'Specular', sgSpecularTextureShadingNode )

    sgNormalsTexture = sg.CreateTexture()
    sgNormalsTexture.SetName( 'Normals' )
    sgNormalsTexture.SetFilePath( normalsTextureFilePath )
    sgTextureTable.AddTexture( sgNormalsTexture )

    sgNormalsTextureShadingNode = sg.CreateShadingTextureNode()
    sgNormalsTextureShadingNode.SetTexCoordLevel( 0 )
    sgNormalsTextureShadingNode.SetTextureName( 'Normals' )

    sgMaterial.AddMaterialChannel( 'Normals' )
    sgMaterial.SetShadingNetwork( 'Normals', sgNormalsTextureShadingNode )

    sgOpacityTexture = sg.CreateTexture()
    sgOpacityTexture.SetName( 'Opacity' )
    sgOpacityTexture.SetFilePath( opacityTextureFilePath )
    sgTextureTable.AddTexture( sgOpacityTexture )

    sgOpacityTextureShadingNode = sg.CreateShadingTextureNode()
    sgOpacityTextureShadingNode.SetTexCoordLevel( 0 )
    sgOpacityTextureShadingNode.SetTextureName( 'Opacity' )

    sgMaterial.AddMaterialChannel( 'Opacity' )
    sgMaterial.SetShadingNetwork( 'Opacity', sgOpacityTextureShadingNode )
    sgMaterial.SetBlendMode(Simplygon.EMaterialBlendMode_Mask);
    
    # Save processed scene.     
    print("Save processed scene.")
    SaveScene(sg, sgScene, 'Output.glb')
    
    # Check log for any warnings or errors.     
    print("Check log for any warnings or errors.")
    CheckLog(sg)

if __name__ == '__main__':
        sg = simplygon_loader.init_simplygon()
        if sg is None:
            exit(Simplygon.GetLastInitializationError())

        RunBillboardCloudFoliage(sg)

        sg = None
        gc.collect()

Billboard cloud, mode: Outer shell

This example shows how to use the Impostor processor type: Billboard cloud with mode: OuterShell.

cpp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

#include <string>
#include <stdlib.h>
#include <filesystem>
#include <future>
#include "SimplygonLoader.h"


Simplygon::spScene LoadScene(Simplygon::ISimplygon* sg, const char* path)
{
	// Create scene importer 
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath(path);
	
	// Run scene importer. 
	auto importResult = sgSceneImporter->Run();
	if (Simplygon::Failed(importResult))
	{
		throw std::exception("Failed to load scene.");
	}
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();
	return sgScene;
}

void SaveScene(Simplygon::ISimplygon* sg, Simplygon::spScene sgScene, const char* path)
{
	// Create scene exporter. 
	Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
	std::string outputScenePath = std::string("output\\") + std::string("ImpostorBillboardCloudOuterShell") + std::string("_") + std::string(path);
	sgSceneExporter->SetExportFilePath(outputScenePath.c_str());
	sgSceneExporter->SetScene(sgScene);
	
	// Run scene exporter. 
	auto exportResult = sgSceneExporter->Run();
	if (Simplygon::Failed(exportResult))
	{
		throw std::exception("Failed to save scene.");
	}
}

void CheckLog(Simplygon::ISimplygon* sg)
{
	// Check if any errors occurred. 
	bool hasErrors = sg->ErrorOccurred();
	if (hasErrors)
	{
		Simplygon::spStringArray errors = sg->CreateStringArray();
		sg->GetErrorMessages(errors);
		auto errorCount = errors->GetItemCount();
		if (errorCount > 0)
		{
			printf("%s\n", "CheckLog: Errors:");
			for (auto errorIndex = 0U; errorIndex < errorCount; ++errorIndex)
			{
				Simplygon::spString errorString = errors->GetItem((int)errorIndex);
				printf("%s\n", errorString.c_str());
			}
			sg->ClearErrorMessages();
		}
	}
	else
	{
		printf("%s\n", "CheckLog: No errors.");
	}
	
	// Check if any warnings occurred. 
	bool hasWarnings = sg->WarningOccurred();
	if (hasWarnings)
	{
		Simplygon::spStringArray warnings = sg->CreateStringArray();
		sg->GetWarningMessages(warnings);
		auto warningCount = warnings->GetItemCount();
		if (warningCount > 0)
		{
			printf("%s\n", "CheckLog: Warnings:");
			for (auto warningIndex = 0U; warningIndex < warningCount; ++warningIndex)
			{
				Simplygon::spString warningString = warnings->GetItem((int)warningIndex);
				printf("%s\n", warningString.c_str());
			}
			sg->ClearWarningMessages();
		}
	}
	else
	{
		printf("%s\n", "CheckLog: No warnings.");
	}
	
	// Error out if Simplygon has errors. 
	if (hasErrors)
	{
		throw std::exception("Processing failed with an error");
	}
}

void RunBillboardCloudOuterShell(Simplygon::ISimplygon* sg)
{
	// Load scene to process. 	
	printf("%s\n", "Load scene to process.");
	Simplygon::spScene sgScene = LoadScene(sg, "../../../Assets/Cages/Cages.obj");
	
	// For all materials in the scene set the blend mode to blend (instead of opaque) 
	for (int i = 0; i < (int)sgScene->GetMaterialTable()->GetMaterialsCount(); ++i)
	{
		sgScene->GetMaterialTable()->GetMaterial(i)->SetBlendMode(Simplygon::EMaterialBlendMode::Blend);
	}
	
	// Create the Impostor processor. 
	Simplygon::spImpostorProcessor sgImpostorProcessor = sg->CreateImpostorProcessor();
	sgImpostorProcessor->SetScene( sgScene );
	Simplygon::spImpostorSettings sgImpostorSettings = sgImpostorProcessor->GetImpostorSettings();
	
	// Set impostor type to Billboard cloud. 
	sgImpostorSettings->SetImpostorType( Simplygon::EImpostorType::BillboardCloud );
	Simplygon::spBillboardCloudSettings sgBillboardCloudSettings = sgImpostorSettings->GetBillboardCloudSettings();
	
	// Set billboard cloud mode to OuterShell. 
	sgBillboardCloudSettings->SetBillboardMode( Simplygon::EBillboardMode::OuterShell );
	sgBillboardCloudSettings->SetBillboardDensity( 0.5f );
	sgBillboardCloudSettings->SetGeometricComplexity( 0.9f );
	sgBillboardCloudSettings->SetMaxPlaneCount( 20 );
	sgBillboardCloudSettings->SetTwoSided( false );
	Simplygon::spMappingImageSettings sgMappingImageSettings = sgImpostorProcessor->GetMappingImageSettings();
	Simplygon::spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings->GetOutputMaterialSettings(0);
	
	// Setting the size of the output material for the mapping image. This will be the output size of the 
	// textures when we do material casting in a later stage. 
	sgOutputMaterialSettings->SetTextureWidth( 1024 );
	sgOutputMaterialSettings->SetTextureHeight( 1024 );
	sgOutputMaterialSettings->SetMultisamplingLevel( 2 );
	
	// Start the impostor process. 	
	printf("%s\n", "Start the impostor process.");
	sgImpostorProcessor->RunProcessing();
	
	// Setup and run the diffuse material casting. 	
	printf("%s\n", "Setup and run the diffuse material casting.");
	Simplygon::spColorCaster sgDiffuseCaster = sg->CreateColorCaster();
	sgDiffuseCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgDiffuseCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgDiffuseCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgDiffuseCaster->SetOutputFilePath( "DiffuseTexture" );

	Simplygon::spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster->GetColorCasterSettings();
	sgDiffuseCasterSettings->SetMaterialChannel( "Diffuse" );
	sgDiffuseCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgDiffuseCasterSettings->SetBakeOpacityInAlpha( false );
	sgDiffuseCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8G8B8 );
	sgDiffuseCasterSettings->SetDilation( 10 );
	sgDiffuseCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgDiffuseCaster->RunProcessing();
	std::string diffuseTextureFilePath = sgDiffuseCaster->GetOutputFilePath().c_str();
	
	// Setup and run the specular material casting. 	
	printf("%s\n", "Setup and run the specular material casting.");
	Simplygon::spColorCaster sgSpecularCaster = sg->CreateColorCaster();
	sgSpecularCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgSpecularCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgSpecularCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgSpecularCaster->SetOutputFilePath( "SpecularTexture" );

	Simplygon::spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster->GetColorCasterSettings();
	sgSpecularCasterSettings->SetMaterialChannel( "Specular" );
	sgSpecularCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgSpecularCasterSettings->SetDilation( 10 );
	sgSpecularCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgSpecularCaster->RunProcessing();
	std::string specularTextureFilePath = sgSpecularCaster->GetOutputFilePath().c_str();
	
	// Setup and run the normals material casting. 	
	printf("%s\n", "Setup and run the normals material casting.");
	Simplygon::spNormalCaster sgNormalsCaster = sg->CreateNormalCaster();
	sgNormalsCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgNormalsCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgNormalsCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgNormalsCaster->SetOutputFilePath( "NormalsTexture" );

	Simplygon::spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster->GetNormalCasterSettings();
	sgNormalsCasterSettings->SetMaterialChannel( "Normals" );
	sgNormalsCasterSettings->SetGenerateTangentSpaceNormals( true );
	sgNormalsCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgNormalsCasterSettings->SetDilation( 10 );
	sgNormalsCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgNormalsCaster->RunProcessing();
	std::string normalsTextureFilePath = sgNormalsCaster->GetOutputFilePath().c_str();
	
	// Setup and run the opacity material casting. Make sure there is no dilation or fill. 	
	printf("%s\n", "Setup and run the opacity material casting. Make sure there is no dilation or fill.");
	Simplygon::spOpacityCaster sgOpacityCaster = sg->CreateOpacityCaster();
	sgOpacityCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgOpacityCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgOpacityCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgOpacityCaster->SetOutputFilePath( "OpacityTexture" );

	Simplygon::spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster->GetOpacityCasterSettings();
	sgOpacityCasterSettings->SetMaterialChannel( "Opacity" );
	sgOpacityCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgOpacityCasterSettings->SetDilation( 0 );
	sgOpacityCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::NoFill );
	sgOpacityCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8 );

	sgOpacityCaster->RunProcessing();
	std::string opacityTextureFilePath = sgOpacityCaster->GetOutputFilePath().c_str();
	
	// Update scene with new casted textures. 
	Simplygon::spMaterialTable sgMaterialTable = sg->CreateMaterialTable();
	Simplygon::spTextureTable sgTextureTable = sg->CreateTextureTable();
	Simplygon::spMaterial sgMaterial = sg->CreateMaterial();
	sgMaterial->SetName("OutputMaterial");
	Simplygon::spTexture sgDiffuseTexture = sg->CreateTexture();
	sgDiffuseTexture->SetName( "Diffuse" );
	sgDiffuseTexture->SetFilePath( diffuseTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgDiffuseTexture );

	Simplygon::spShadingTextureNode sgDiffuseTextureShadingNode = sg->CreateShadingTextureNode();
	sgDiffuseTextureShadingNode->SetTexCoordLevel( 0 );
	sgDiffuseTextureShadingNode->SetTextureName( "Diffuse" );

	sgMaterial->AddMaterialChannel( "Diffuse" );
	sgMaterial->SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );
	Simplygon::spTexture sgSpecularTexture = sg->CreateTexture();
	sgSpecularTexture->SetName( "Specular" );
	sgSpecularTexture->SetFilePath( specularTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgSpecularTexture );

	Simplygon::spShadingTextureNode sgSpecularTextureShadingNode = sg->CreateShadingTextureNode();
	sgSpecularTextureShadingNode->SetTexCoordLevel( 0 );
	sgSpecularTextureShadingNode->SetTextureName( "Specular" );

	sgMaterial->AddMaterialChannel( "Specular" );
	sgMaterial->SetShadingNetwork( "Specular", sgSpecularTextureShadingNode );
	Simplygon::spTexture sgNormalsTexture = sg->CreateTexture();
	sgNormalsTexture->SetName( "Normals" );
	sgNormalsTexture->SetFilePath( normalsTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgNormalsTexture );

	Simplygon::spShadingTextureNode sgNormalsTextureShadingNode = sg->CreateShadingTextureNode();
	sgNormalsTextureShadingNode->SetTexCoordLevel( 0 );
	sgNormalsTextureShadingNode->SetTextureName( "Normals" );

	sgMaterial->AddMaterialChannel( "Normals" );
	sgMaterial->SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );
	Simplygon::spTexture sgOpacityTexture = sg->CreateTexture();
	sgOpacityTexture->SetName( "Opacity" );
	sgOpacityTexture->SetFilePath( opacityTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgOpacityTexture );

	Simplygon::spShadingTextureNode sgOpacityTextureShadingNode = sg->CreateShadingTextureNode();
	sgOpacityTextureShadingNode->SetTexCoordLevel( 0 );
	sgOpacityTextureShadingNode->SetTextureName( "Opacity" );

	sgMaterial->AddMaterialChannel( "Opacity" );
	sgMaterial->SetShadingNetwork( "Opacity", sgOpacityTextureShadingNode );
	sgMaterial->SetBlendMode(Simplygon::EMaterialBlendMode::Blend);

	sgMaterialTable->AddMaterial( sgMaterial );

	sgScene->GetTextureTable()->Clear();
	sgScene->GetMaterialTable()->Clear();
	sgScene->GetTextureTable()->Copy(sgTextureTable);
	sgScene->GetMaterialTable()->Copy(sgMaterialTable);
	
	// Save processed scene. 	
	printf("%s\n", "Save processed scene.");
	SaveScene(sg, sgScene, "Output.glb");
	
	// Check log for any warnings or errors. 	
	printf("%s\n", "Check log for any warnings or errors.");
	CheckLog(sg);
}

int main()
{
	Simplygon::ISimplygon* sg = NULL;
	Simplygon::EErrorCodes initval = Simplygon::Initialize( &sg );
	if( initval != Simplygon::EErrorCodes::NoError )
	{
		printf( "Failed to initialize Simplygon: ErrorCode(%d)", (int)initval );
		return int(initval);
	}

	RunBillboardCloudOuterShell(sg);

	Simplygon::Deinitialize(sg);

	return 0;
}
csharp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

using System;
using System.IO;
using System.Threading.Tasks;

public class Program
{
    static Simplygon.spScene LoadScene(Simplygon.ISimplygon sg, string path)
    {
        // Create scene importer 
        using Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter();
        sgSceneImporter.SetImportFilePath(path);
        
        // Run scene importer. 
        var importResult = sgSceneImporter.Run();
        if (Simplygon.Simplygon.Failed(importResult))
        {
            throw new System.Exception("Failed to load scene.");
        }
        Simplygon.spScene sgScene = sgSceneImporter.GetScene();
        return sgScene;
    }

    static void SaveScene(Simplygon.ISimplygon sg, Simplygon.spScene sgScene, string path)
    {
        // Create scene exporter. 
        using Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter();
        string outputScenePath = string.Join("", new string[] { "output\\", "ImpostorBillboardCloudOuterShell", "_", path });
        sgSceneExporter.SetExportFilePath(outputScenePath);
        sgSceneExporter.SetScene(sgScene);
        
        // Run scene exporter. 
        var exportResult = sgSceneExporter.Run();
        if (Simplygon.Simplygon.Failed(exportResult))
        {
            throw new System.Exception("Failed to save scene.");
        }
    }

    static void CheckLog(Simplygon.ISimplygon sg)
    {
        // Check if any errors occurred. 
        bool hasErrors = sg.ErrorOccurred();
        if (hasErrors)
        {
            Simplygon.spStringArray errors = sg.CreateStringArray();
            sg.GetErrorMessages(errors);
            var errorCount = errors.GetItemCount();
            if (errorCount > 0)
            {
                Console.WriteLine("CheckLog: Errors:");
                for (uint errorIndex = 0; errorIndex < errorCount; ++errorIndex)
                {
                    string errorString = errors.GetItem((int)errorIndex);
                    Console.WriteLine(errorString);
                }
                sg.ClearErrorMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No errors.");
        }
        
        // Check if any warnings occurred. 
        bool hasWarnings = sg.WarningOccurred();
        if (hasWarnings)
        {
            Simplygon.spStringArray warnings = sg.CreateStringArray();
            sg.GetWarningMessages(warnings);
            var warningCount = warnings.GetItemCount();
            if (warningCount > 0)
            {
                Console.WriteLine("CheckLog: Warnings:");
                for (uint warningIndex = 0; warningIndex < warningCount; ++warningIndex)
                {
                    string warningString = warnings.GetItem((int)warningIndex);
                    Console.WriteLine(warningString);
                }
                sg.ClearWarningMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No warnings.");
        }
        
        // Error out if Simplygon has errors. 
        if (hasErrors)
        {
            throw new System.Exception("Processing failed with an error");
        }
    }

    static void RunBillboardCloudOuterShell(Simplygon.ISimplygon sg)
    {
        // Load scene to process.         
        Console.WriteLine("Load scene to process.");
        Simplygon.spScene sgScene = LoadScene(sg, "../../../Assets/Cages/Cages.obj");
        
        // For all materials in the scene set the blend mode to blend (instead of opaque) 
        for (int i = 0; i < (int)sgScene.GetMaterialTable().GetMaterialsCount(); ++i)
        {
            sgScene.GetMaterialTable().GetMaterial(i).SetBlendMode(Simplygon.EMaterialBlendMode.Blend);
        }
        
        // Create the Impostor processor. 
        using Simplygon.spImpostorProcessor sgImpostorProcessor = sg.CreateImpostorProcessor();
        sgImpostorProcessor.SetScene( sgScene );
        using Simplygon.spImpostorSettings sgImpostorSettings = sgImpostorProcessor.GetImpostorSettings();
        
        // Set impostor type to Billboard cloud. 
        sgImpostorSettings.SetImpostorType( Simplygon.EImpostorType.BillboardCloud );
        using Simplygon.spBillboardCloudSettings sgBillboardCloudSettings = sgImpostorSettings.GetBillboardCloudSettings();
        
        // Set billboard cloud mode to OuterShell. 
        sgBillboardCloudSettings.SetBillboardMode( Simplygon.EBillboardMode.OuterShell );
        sgBillboardCloudSettings.SetBillboardDensity( 0.5f );
        sgBillboardCloudSettings.SetGeometricComplexity( 0.9f );
        sgBillboardCloudSettings.SetMaxPlaneCount( 20 );
        sgBillboardCloudSettings.SetTwoSided( false );
        using Simplygon.spMappingImageSettings sgMappingImageSettings = sgImpostorProcessor.GetMappingImageSettings();
        using Simplygon.spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0);
        
        // Setting the size of the output material for the mapping image. This will be the output size of the 
        // textures when we do material casting in a later stage. 
        sgOutputMaterialSettings.SetTextureWidth( 1024 );
        sgOutputMaterialSettings.SetTextureHeight( 1024 );
        sgOutputMaterialSettings.SetMultisamplingLevel( 2 );
        
        // Start the impostor process.         
        Console.WriteLine("Start the impostor process.");
        sgImpostorProcessor.RunProcessing();
        
        // Setup and run the diffuse material casting.         
        Console.WriteLine("Setup and run the diffuse material casting.");
        string diffuseTextureFilePath;
        using Simplygon.spColorCaster sgDiffuseCaster = sg.CreateColorCaster();
        sgDiffuseCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgDiffuseCaster.SetOutputFilePath( "DiffuseTexture" );

        using Simplygon.spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings();
        sgDiffuseCasterSettings.SetMaterialChannel( "Diffuse" );
        sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgDiffuseCasterSettings.SetBakeOpacityInAlpha( false );
        sgDiffuseCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8G8B8 );
        sgDiffuseCasterSettings.SetDilation( 10 );
        sgDiffuseCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgDiffuseCaster.RunProcessing();
        diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath();
        
        // Setup and run the specular material casting.         
        Console.WriteLine("Setup and run the specular material casting.");
        string specularTextureFilePath;
        using Simplygon.spColorCaster sgSpecularCaster = sg.CreateColorCaster();
        sgSpecularCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgSpecularCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgSpecularCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgSpecularCaster.SetOutputFilePath( "SpecularTexture" );

        using Simplygon.spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster.GetColorCasterSettings();
        sgSpecularCasterSettings.SetMaterialChannel( "Specular" );
        sgSpecularCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgSpecularCasterSettings.SetDilation( 10 );
        sgSpecularCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgSpecularCaster.RunProcessing();
        specularTextureFilePath = sgSpecularCaster.GetOutputFilePath();
        
        // Setup and run the normals material casting.         
        Console.WriteLine("Setup and run the normals material casting.");
        string normalsTextureFilePath;
        using Simplygon.spNormalCaster sgNormalsCaster = sg.CreateNormalCaster();
        sgNormalsCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgNormalsCaster.SetOutputFilePath( "NormalsTexture" );

        using Simplygon.spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings();
        sgNormalsCasterSettings.SetMaterialChannel( "Normals" );
        sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( true );
        sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgNormalsCasterSettings.SetDilation( 10 );
        sgNormalsCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgNormalsCaster.RunProcessing();
        normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath();
        
        // Setup and run the opacity material casting. Make sure there is no dilation or fill.         
        Console.WriteLine("Setup and run the opacity material casting. Make sure there is no dilation or fill.");
        string opacityTextureFilePath;
        using Simplygon.spOpacityCaster sgOpacityCaster = sg.CreateOpacityCaster();
        sgOpacityCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgOpacityCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgOpacityCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgOpacityCaster.SetOutputFilePath( "OpacityTexture" );

        using Simplygon.spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster.GetOpacityCasterSettings();
        sgOpacityCasterSettings.SetMaterialChannel( "Opacity" );
        sgOpacityCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgOpacityCasterSettings.SetDilation( 0 );
        sgOpacityCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.NoFill );
        sgOpacityCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8 );

        sgOpacityCaster.RunProcessing();
        opacityTextureFilePath = sgOpacityCaster.GetOutputFilePath();
        
        // Update scene with new casted textures. 
        using Simplygon.spMaterialTable sgMaterialTable = sg.CreateMaterialTable();
        using Simplygon.spTextureTable sgTextureTable = sg.CreateTextureTable();
        using Simplygon.spMaterial sgMaterial = sg.CreateMaterial();
        sgMaterial.SetName("OutputMaterial");
        using Simplygon.spTexture sgDiffuseTexture = sg.CreateTexture();
        sgDiffuseTexture.SetName( "Diffuse" );
        sgDiffuseTexture.SetFilePath( diffuseTextureFilePath );
        sgTextureTable.AddTexture( sgDiffuseTexture );

        using Simplygon.spShadingTextureNode sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode();
        sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 );
        sgDiffuseTextureShadingNode.SetTextureName( "Diffuse" );

        sgMaterial.AddMaterialChannel( "Diffuse" );
        sgMaterial.SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );
        using Simplygon.spTexture sgSpecularTexture = sg.CreateTexture();
        sgSpecularTexture.SetName( "Specular" );
        sgSpecularTexture.SetFilePath( specularTextureFilePath );
        sgTextureTable.AddTexture( sgSpecularTexture );

        using Simplygon.spShadingTextureNode sgSpecularTextureShadingNode = sg.CreateShadingTextureNode();
        sgSpecularTextureShadingNode.SetTexCoordLevel( 0 );
        sgSpecularTextureShadingNode.SetTextureName( "Specular" );

        sgMaterial.AddMaterialChannel( "Specular" );
        sgMaterial.SetShadingNetwork( "Specular", sgSpecularTextureShadingNode );
        using Simplygon.spTexture sgNormalsTexture = sg.CreateTexture();
        sgNormalsTexture.SetName( "Normals" );
        sgNormalsTexture.SetFilePath( normalsTextureFilePath );
        sgTextureTable.AddTexture( sgNormalsTexture );

        using Simplygon.spShadingTextureNode sgNormalsTextureShadingNode = sg.CreateShadingTextureNode();
        sgNormalsTextureShadingNode.SetTexCoordLevel( 0 );
        sgNormalsTextureShadingNode.SetTextureName( "Normals" );

        sgMaterial.AddMaterialChannel( "Normals" );
        sgMaterial.SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );
        using Simplygon.spTexture sgOpacityTexture = sg.CreateTexture();
        sgOpacityTexture.SetName( "Opacity" );
        sgOpacityTexture.SetFilePath( opacityTextureFilePath );
        sgTextureTable.AddTexture( sgOpacityTexture );

        using Simplygon.spShadingTextureNode sgOpacityTextureShadingNode = sg.CreateShadingTextureNode();
        sgOpacityTextureShadingNode.SetTexCoordLevel( 0 );
        sgOpacityTextureShadingNode.SetTextureName( "Opacity" );

        sgMaterial.AddMaterialChannel( "Opacity" );
        sgMaterial.SetShadingNetwork( "Opacity", sgOpacityTextureShadingNode );
        sgMaterial.SetBlendMode(Simplygon.EMaterialBlendMode.Blend);

        sgMaterialTable.AddMaterial( sgMaterial );

        sgScene.GetTextureTable().Clear();
        sgScene.GetMaterialTable().Clear();
        sgScene.GetTextureTable().Copy(sgTextureTable);
        sgScene.GetMaterialTable().Copy(sgMaterialTable);
        
        // Save processed scene.         
        Console.WriteLine("Save processed scene.");
        SaveScene(sg, sgScene, "Output.glb");
        
        // Check log for any warnings or errors.         
        Console.WriteLine("Check log for any warnings or errors.");
        CheckLog(sg);
    }

    static int Main(string[] args)
    {
        using var sg = Simplygon.Loader.InitSimplygon(out var errorCode, out var errorMessage);
        if (errorCode != Simplygon.EErrorCodes.NoError)
        {
            Console.WriteLine( $"Failed to initialize Simplygon: ErrorCode({(int)errorCode}) {errorMessage}" );
            return (int)errorCode;
        }
        RunBillboardCloudOuterShell(sg);

        return 0;
    }

}
python
# Copyright (c) Microsoft Corporation. 
# Licensed under the MIT License. 

import math
import os
import sys
import glob
import gc
import threading

from pathlib import Path
from simplygon10 import simplygon_loader
from simplygon10 import Simplygon


def LoadScene(sg: Simplygon.ISimplygon, path: str):
    # Create scene importer 
    sgSceneImporter = sg.CreateSceneImporter()
    sgSceneImporter.SetImportFilePath(path)
    
    # Run scene importer. 
    importResult = sgSceneImporter.Run()
    if Simplygon.Failed(importResult):
        raise Exception('Failed to load scene.')
    sgScene = sgSceneImporter.GetScene()
    return sgScene

def SaveScene(sg: Simplygon.ISimplygon, sgScene: Simplygon.spScene, path: str):
    # Create scene exporter. 
    sgSceneExporter = sg.CreateSceneExporter()
    outputScenePath = ''.join(['output\\', 'ImpostorBillboardCloudOuterShell', '_', path])
    sgSceneExporter.SetExportFilePath(outputScenePath)
    sgSceneExporter.SetScene(sgScene)
    
    # Run scene exporter. 
    exportResult = sgSceneExporter.Run()
    if Simplygon.Failed(exportResult):
        raise Exception('Failed to save scene.')

def CheckLog(sg: Simplygon.ISimplygon):
    # Check if any errors occurred. 
    hasErrors = sg.ErrorOccurred()
    if hasErrors:
        errors = sg.CreateStringArray()
        sg.GetErrorMessages(errors)
        errorCount = errors.GetItemCount()
        if errorCount > 0:
            print('CheckLog: Errors:')
            for errorIndex in range(errorCount):
                errorString = errors.GetItem(errorIndex)
                print(errorString)
            sg.ClearErrorMessages()
    else:
        print('CheckLog: No errors.')
    
    # Check if any warnings occurred. 
    hasWarnings = sg.WarningOccurred()
    if hasWarnings:
        warnings = sg.CreateStringArray()
        sg.GetWarningMessages(warnings)
        warningCount = warnings.GetItemCount()
        if warningCount > 0:
            print('CheckLog: Warnings:')
            for warningIndex in range(warningCount):
                warningString = warnings.GetItem(warningIndex)
                print(warningString)
            sg.ClearWarningMessages()
    else:
        print('CheckLog: No warnings.')
    
    # Error out if Simplygon has errors. 
    if hasErrors:
        raise Exception('Processing failed with an error')

def RunBillboardCloudOuterShell(sg: Simplygon.ISimplygon):
    # Load scene to process.     
    print("Load scene to process.")
    sgScene = LoadScene(sg, '../../../Assets/Cages/Cages.obj')
    
    # For all materials in the scene set the blend mode to blend (instead of opaque) 
    materialCount = sgScene.GetMaterialTable().GetMaterialsCount()
    for i in range(0, materialCount):
        sgScene.GetMaterialTable().GetMaterial(i).SetBlendMode(Simplygon.EMaterialBlendMode_Blend)
    
    # Create the Impostor processor. 
    sgImpostorProcessor = sg.CreateImpostorProcessor()
    sgImpostorProcessor.SetScene( sgScene )
    sgImpostorSettings = sgImpostorProcessor.GetImpostorSettings()
    
    # Set impostor type to Billboard cloud. 
    sgImpostorSettings.SetImpostorType( Simplygon.EImpostorType_BillboardCloud )
    sgBillboardCloudSettings = sgImpostorSettings.GetBillboardCloudSettings()
    
    # Set billboard cloud mode to OuterShell. 
    sgBillboardCloudSettings.SetBillboardMode( Simplygon.EBillboardMode_OuterShell )
    sgBillboardCloudSettings.SetBillboardDensity( 0.5 )
    sgBillboardCloudSettings.SetGeometricComplexity( 0.9 )
    sgBillboardCloudSettings.SetMaxPlaneCount( 20 )
    sgBillboardCloudSettings.SetTwoSided( False )
    sgMappingImageSettings = sgImpostorProcessor.GetMappingImageSettings()
    sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0)
    
    # Setting the size of the output material for the mapping image. This will be the output size of the 
    # textures when we do material casting in a later stage. 
    sgOutputMaterialSettings.SetTextureWidth( 1024 )
    sgOutputMaterialSettings.SetTextureHeight( 1024 )
    sgOutputMaterialSettings.SetMultisamplingLevel( 2 )
    
    # Start the impostor process.     
    print("Start the impostor process.")
    sgImpostorProcessor.RunProcessing()
    
    # Setup and run the diffuse material casting.     
    print("Setup and run the diffuse material casting.")
    sgDiffuseCaster = sg.CreateColorCaster()
    sgDiffuseCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgDiffuseCaster.SetOutputFilePath( 'DiffuseTexture' )

    sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings()
    sgDiffuseCasterSettings.SetMaterialChannel( 'Diffuse' )
    sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgDiffuseCasterSettings.SetBakeOpacityInAlpha( False )
    sgDiffuseCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8G8B8 )
    sgDiffuseCasterSettings.SetDilation( 10 )
    sgDiffuseCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgDiffuseCaster.RunProcessing()
    diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath()
    
    # Setup and run the specular material casting.     
    print("Setup and run the specular material casting.")
    sgSpecularCaster = sg.CreateColorCaster()
    sgSpecularCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgSpecularCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgSpecularCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgSpecularCaster.SetOutputFilePath( 'SpecularTexture' )

    sgSpecularCasterSettings = sgSpecularCaster.GetColorCasterSettings()
    sgSpecularCasterSettings.SetMaterialChannel( 'Specular' )
    sgSpecularCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgSpecularCasterSettings.SetDilation( 10 )
    sgSpecularCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgSpecularCaster.RunProcessing()
    specularTextureFilePath = sgSpecularCaster.GetOutputFilePath()
    
    # Setup and run the normals material casting.     
    print("Setup and run the normals material casting.")
    sgNormalsCaster = sg.CreateNormalCaster()
    sgNormalsCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgNormalsCaster.SetOutputFilePath( 'NormalsTexture' )

    sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings()
    sgNormalsCasterSettings.SetMaterialChannel( 'Normals' )
    sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( True )
    sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgNormalsCasterSettings.SetDilation( 10 )
    sgNormalsCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgNormalsCaster.RunProcessing()
    normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath()
    
    # Setup and run the opacity material casting. Make sure there is no dilation or fill.     
    print("Setup and run the opacity material casting. Make sure there is no dilation or fill.")
    sgOpacityCaster = sg.CreateOpacityCaster()
    sgOpacityCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgOpacityCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgOpacityCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgOpacityCaster.SetOutputFilePath( 'OpacityTexture' )

    sgOpacityCasterSettings = sgOpacityCaster.GetOpacityCasterSettings()
    sgOpacityCasterSettings.SetMaterialChannel( 'Opacity' )
    sgOpacityCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgOpacityCasterSettings.SetDilation( 0 )
    sgOpacityCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_NoFill )
    sgOpacityCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8 )

    sgOpacityCaster.RunProcessing()
    opacityTextureFilePath = sgOpacityCaster.GetOutputFilePath()
    
    # Update scene with new casted textures. 
    sgMaterialTable = sg.CreateMaterialTable()
    sgTextureTable = sg.CreateTextureTable()
    sgMaterial = sg.CreateMaterial()
    sgMaterial.SetName("OutputMaterial")
    sgDiffuseTexture = sg.CreateTexture()
    sgDiffuseTexture.SetName( 'Diffuse' )
    sgDiffuseTexture.SetFilePath( diffuseTextureFilePath )
    sgTextureTable.AddTexture( sgDiffuseTexture )

    sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode()
    sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 )
    sgDiffuseTextureShadingNode.SetTextureName( 'Diffuse' )

    sgMaterial.AddMaterialChannel( 'Diffuse' )
    sgMaterial.SetShadingNetwork( 'Diffuse', sgDiffuseTextureShadingNode )
    sgSpecularTexture = sg.CreateTexture()
    sgSpecularTexture.SetName( 'Specular' )
    sgSpecularTexture.SetFilePath( specularTextureFilePath )
    sgTextureTable.AddTexture( sgSpecularTexture )

    sgSpecularTextureShadingNode = sg.CreateShadingTextureNode()
    sgSpecularTextureShadingNode.SetTexCoordLevel( 0 )
    sgSpecularTextureShadingNode.SetTextureName( 'Specular' )

    sgMaterial.AddMaterialChannel( 'Specular' )
    sgMaterial.SetShadingNetwork( 'Specular', sgSpecularTextureShadingNode )
    sgNormalsTexture = sg.CreateTexture()
    sgNormalsTexture.SetName( 'Normals' )
    sgNormalsTexture.SetFilePath( normalsTextureFilePath )
    sgTextureTable.AddTexture( sgNormalsTexture )

    sgNormalsTextureShadingNode = sg.CreateShadingTextureNode()
    sgNormalsTextureShadingNode.SetTexCoordLevel( 0 )
    sgNormalsTextureShadingNode.SetTextureName( 'Normals' )

    sgMaterial.AddMaterialChannel( 'Normals' )
    sgMaterial.SetShadingNetwork( 'Normals', sgNormalsTextureShadingNode )
    sgOpacityTexture = sg.CreateTexture()
    sgOpacityTexture.SetName( 'Opacity' )
    sgOpacityTexture.SetFilePath( opacityTextureFilePath )
    sgTextureTable.AddTexture( sgOpacityTexture )

    sgOpacityTextureShadingNode = sg.CreateShadingTextureNode()
    sgOpacityTextureShadingNode.SetTexCoordLevel( 0 )
    sgOpacityTextureShadingNode.SetTextureName( 'Opacity' )

    sgMaterial.AddMaterialChannel( 'Opacity' )
    sgMaterial.SetShadingNetwork( 'Opacity', sgOpacityTextureShadingNode )
    sgMaterial.SetBlendMode(Simplygon.EMaterialBlendMode_Blend);

    sgMaterialTable.AddMaterial( sgMaterial )

    sgScene.GetTextureTable().Clear()
    sgScene.GetMaterialTable().Clear()
    sgScene.GetTextureTable().Copy(sgTextureTable)
    sgScene.GetMaterialTable().Copy(sgMaterialTable)
    
    # Save processed scene.     
    print("Save processed scene.")
    SaveScene(sg, sgScene, 'Output.glb')
    
    # Check log for any warnings or errors.     
    print("Check log for any warnings or errors.")
    CheckLog(sg)

if __name__ == '__main__':
        sg = simplygon_loader.init_simplygon()
        if sg is None:
            exit(Simplygon.GetLastInitializationError())

        RunBillboardCloudOuterShell(sg)

        sg = None
        gc.collect()

Flipbook

This example shows how to use the Impostor processor type: Flip book.

cpp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

#include <string>
#include <stdlib.h>
#include <filesystem>
#include <future>
#include "SimplygonLoader.h"


Simplygon::spScene LoadScene(Simplygon::ISimplygon* sg, const char* path)
{
	// Create scene importer 
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath(path);
	
	// Run scene importer. 
	auto importResult = sgSceneImporter->Run();
	if (Simplygon::Failed(importResult))
	{
		throw std::exception("Failed to load scene.");
	}
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();
	return sgScene;
}

void SaveScene(Simplygon::ISimplygon* sg, Simplygon::spScene sgScene, const char* path)
{
	// Create scene exporter. 
	Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
	std::string outputScenePath = std::string("output\\") + std::string("ImpostorFlipbook") + std::string("_") + std::string(path);
	sgSceneExporter->SetExportFilePath(outputScenePath.c_str());
	sgSceneExporter->SetScene(sgScene);
	
	// Run scene exporter. 
	auto exportResult = sgSceneExporter->Run();
	if (Simplygon::Failed(exportResult))
	{
		throw std::exception("Failed to save scene.");
	}
}

void CheckLog(Simplygon::ISimplygon* sg)
{
	// Check if any errors occurred. 
	bool hasErrors = sg->ErrorOccurred();
	if (hasErrors)
	{
		Simplygon::spStringArray errors = sg->CreateStringArray();
		sg->GetErrorMessages(errors);
		auto errorCount = errors->GetItemCount();
		if (errorCount > 0)
		{
			printf("%s\n", "CheckLog: Errors:");
			for (auto errorIndex = 0U; errorIndex < errorCount; ++errorIndex)
			{
				Simplygon::spString errorString = errors->GetItem((int)errorIndex);
				printf("%s\n", errorString.c_str());
			}
			sg->ClearErrorMessages();
		}
	}
	else
	{
		printf("%s\n", "CheckLog: No errors.");
	}
	
	// Check if any warnings occurred. 
	bool hasWarnings = sg->WarningOccurred();
	if (hasWarnings)
	{
		Simplygon::spStringArray warnings = sg->CreateStringArray();
		sg->GetWarningMessages(warnings);
		auto warningCount = warnings->GetItemCount();
		if (warningCount > 0)
		{
			printf("%s\n", "CheckLog: Warnings:");
			for (auto warningIndex = 0U; warningIndex < warningCount; ++warningIndex)
			{
				Simplygon::spString warningString = warnings->GetItem((int)warningIndex);
				printf("%s\n", warningString.c_str());
			}
			sg->ClearWarningMessages();
		}
	}
	else
	{
		printf("%s\n", "CheckLog: No warnings.");
	}
	
	// Error out if Simplygon has errors. 
	if (hasErrors)
	{
		throw std::exception("Processing failed with an error");
	}
}

void RunFlipbook(Simplygon::ISimplygon* sg)
{
	// Load scene to process. 	
	printf("%s\n", "Load scene to process.");
	Simplygon::spScene sgScene = LoadScene(sg, "../../../Assets/Bush/Bush.fbx");
	
	// For all materials in the scene set the blend mode to blend (instead of opaque) 
	for (int i = 0; i < (int)sgScene->GetMaterialTable()->GetMaterialsCount(); ++i)
	{
		sgScene->GetMaterialTable()->GetMaterial(i)->SetBlendMode(Simplygon::EMaterialBlendMode::Blend);
	}
	
	// For all materials in the scene set the opacity mode to Opacity. 
	for (int i = 0; i < (int)sgScene->GetMaterialTable()->GetMaterialsCount(); ++i)
	{
		sgScene->GetMaterialTable()->GetMaterial(i)->SetOpacityType(Simplygon::EOpacityType::Opacity);
	}
	
	// Create the Impostor processor. 
	Simplygon::spImpostorProcessor sgImpostorProcessor = sg->CreateImpostorProcessor();
	sgImpostorProcessor->SetScene( sgScene );
	Simplygon::spImpostorSettings sgImpostorSettings = sgImpostorProcessor->GetImpostorSettings();
	
	// Set impostor type to From single view. 
	sgImpostorSettings->SetImpostorType( Simplygon::EImpostorType::Flipbook );
	Simplygon::spFlipbookSettings sgFlipbookSettings = sgImpostorSettings->GetFlipbookSettings();
	sgFlipbookSettings->SetNumberOfViews( 9 );
	sgFlipbookSettings->SetViewDirectionX( 1.0f );
	sgFlipbookSettings->SetViewDirectionY( 0.0f );
	sgFlipbookSettings->SetViewDirectionZ( 0.0f );
	sgFlipbookSettings->SetUpVectorX( 0.0f );
	sgFlipbookSettings->SetUpVectorY( 1.0f );
	sgFlipbookSettings->SetUpVectorZ( 0.0f );
	Simplygon::spMappingImageSettings sgMappingImageSettings = sgImpostorProcessor->GetMappingImageSettings();
	sgMappingImageSettings->SetMaximumLayers( 10 );
	Simplygon::spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings->GetOutputMaterialSettings(0);
	
	// Setting the size of the output material for the mapping image. This will be the output size of the 
	// textures when we do material casting in a later stage. 
	sgOutputMaterialSettings->SetTextureWidth( 256 );
	sgOutputMaterialSettings->SetTextureHeight( 256 );
	sgOutputMaterialSettings->SetMultisamplingLevel( 2 );
	
	// Start the impostor process. 	
	printf("%s\n", "Start the impostor process.");
	sgImpostorProcessor->RunProcessing();
	
	// Setup and run the diffuse material casting. 	
	printf("%s\n", "Setup and run the diffuse material casting.");
	Simplygon::spColorCaster sgDiffuseCaster = sg->CreateColorCaster();
	sgDiffuseCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgDiffuseCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgDiffuseCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgDiffuseCaster->SetOutputFilePath( "DiffuseTexture" );

	Simplygon::spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster->GetColorCasterSettings();
	sgDiffuseCasterSettings->SetMaterialChannel( "Diffuse" );
	sgDiffuseCasterSettings->SetOpacityChannel( "Opacity" );
	sgDiffuseCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgDiffuseCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgDiffuseCasterSettings->SetBakeOpacityInAlpha( false );
	sgDiffuseCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8G8B8 );
	sgDiffuseCasterSettings->SetDilation( 10 );
	sgDiffuseCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgDiffuseCaster->RunProcessing();
	std::string diffuseTextureFilePath = sgDiffuseCaster->GetOutputFilePath().c_str();
	
	// Setup and run the specular material casting. 	
	printf("%s\n", "Setup and run the specular material casting.");
	Simplygon::spColorCaster sgSpecularCaster = sg->CreateColorCaster();
	sgSpecularCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgSpecularCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgSpecularCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgSpecularCaster->SetOutputFilePath( "SpecularTexture" );

	Simplygon::spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster->GetColorCasterSettings();
	sgSpecularCasterSettings->SetMaterialChannel( "Specular" );
	sgSpecularCasterSettings->SetOpacityChannel( "Opacity" );
	sgSpecularCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgSpecularCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgSpecularCasterSettings->SetDilation( 10 );
	sgSpecularCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgSpecularCaster->RunProcessing();
	std::string specularTextureFilePath = sgSpecularCaster->GetOutputFilePath().c_str();
	
	// Setup and run the normals material casting. 	
	printf("%s\n", "Setup and run the normals material casting.");
	Simplygon::spNormalCaster sgNormalsCaster = sg->CreateNormalCaster();
	sgNormalsCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgNormalsCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgNormalsCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgNormalsCaster->SetOutputFilePath( "NormalsTexture" );

	Simplygon::spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster->GetNormalCasterSettings();
	sgNormalsCasterSettings->SetMaterialChannel( "Normals" );
	sgNormalsCasterSettings->SetOpacityChannel( "Opacity" );
	sgNormalsCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgNormalsCasterSettings->SetGenerateTangentSpaceNormals( true );
	sgNormalsCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgNormalsCasterSettings->SetDilation( 10 );
	sgNormalsCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgNormalsCaster->RunProcessing();
	std::string normalsTextureFilePath = sgNormalsCaster->GetOutputFilePath().c_str();
	
	// Setup and run the opacity material casting. Make sure there is no dilation or fill. 	
	printf("%s\n", "Setup and run the opacity material casting. Make sure there is no dilation or fill.");
	Simplygon::spOpacityCaster sgOpacityCaster = sg->CreateOpacityCaster();
	sgOpacityCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgOpacityCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgOpacityCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgOpacityCaster->SetOutputFilePath( "OpacityTexture" );

	Simplygon::spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster->GetOpacityCasterSettings();
	sgOpacityCasterSettings->SetMaterialChannel( "Opacity" );
	sgOpacityCasterSettings->SetOpacityChannel( "Opacity" );
	sgOpacityCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgOpacityCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgOpacityCasterSettings->SetDilation( 0 );
	sgOpacityCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::NoFill );
	sgOpacityCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8 );

	sgOpacityCaster->RunProcessing();
	std::string opacityTextureFilePath = sgOpacityCaster->GetOutputFilePath().c_str();
	
	// Update scene with new casted textures. 
	Simplygon::spMaterialTable sgMaterialTable = sg->CreateMaterialTable();
	Simplygon::spTextureTable sgTextureTable = sg->CreateTextureTable();
	Simplygon::spMaterial sgMaterial = sg->CreateMaterial();
	sgMaterial->SetName("OutputMaterial");
	Simplygon::spTexture sgDiffuseTexture = sg->CreateTexture();
	sgDiffuseTexture->SetName( "Diffuse" );
	sgDiffuseTexture->SetFilePath( diffuseTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgDiffuseTexture );

	Simplygon::spShadingTextureNode sgDiffuseTextureShadingNode = sg->CreateShadingTextureNode();
	sgDiffuseTextureShadingNode->SetTexCoordLevel( 0 );
	sgDiffuseTextureShadingNode->SetTextureName( "Diffuse" );

	sgMaterial->AddMaterialChannel( "Diffuse" );
	sgMaterial->SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );
	Simplygon::spTexture sgSpecularTexture = sg->CreateTexture();
	sgSpecularTexture->SetName( "Specular" );
	sgSpecularTexture->SetFilePath( specularTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgSpecularTexture );

	Simplygon::spShadingTextureNode sgSpecularTextureShadingNode = sg->CreateShadingTextureNode();
	sgSpecularTextureShadingNode->SetTexCoordLevel( 0 );
	sgSpecularTextureShadingNode->SetTextureName( "Specular" );

	sgMaterial->AddMaterialChannel( "Specular" );
	sgMaterial->SetShadingNetwork( "Specular", sgSpecularTextureShadingNode );
	Simplygon::spTexture sgNormalsTexture = sg->CreateTexture();
	sgNormalsTexture->SetName( "Normals" );
	sgNormalsTexture->SetFilePath( normalsTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgNormalsTexture );

	Simplygon::spShadingTextureNode sgNormalsTextureShadingNode = sg->CreateShadingTextureNode();
	sgNormalsTextureShadingNode->SetTexCoordLevel( 0 );
	sgNormalsTextureShadingNode->SetTextureName( "Normals" );

	sgMaterial->AddMaterialChannel( "Normals" );
	sgMaterial->SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );
	Simplygon::spTexture sgOpacityTexture = sg->CreateTexture();
	sgOpacityTexture->SetName( "Opacity" );
	sgOpacityTexture->SetFilePath( opacityTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgOpacityTexture );

	Simplygon::spShadingTextureNode sgOpacityTextureShadingNode = sg->CreateShadingTextureNode();
	sgOpacityTextureShadingNode->SetTexCoordLevel( 0 );
	sgOpacityTextureShadingNode->SetTextureName( "Opacity" );

	sgMaterial->AddMaterialChannel( "Opacity" );
	sgMaterial->SetShadingNetwork( "Opacity", sgOpacityTextureShadingNode );
	sgMaterial->SetBlendMode(Simplygon::EMaterialBlendMode::Blend);

	sgMaterialTable->AddMaterial( sgMaterial );

	sgScene->GetTextureTable()->Clear();
	sgScene->GetMaterialTable()->Clear();
	sgScene->GetTextureTable()->Copy(sgTextureTable);
	sgScene->GetMaterialTable()->Copy(sgMaterialTable);
	
	// Save processed scene. 	
	printf("%s\n", "Save processed scene.");
	SaveScene(sg, sgScene, "Output.glb");
	
	// Check log for any warnings or errors. 	
	printf("%s\n", "Check log for any warnings or errors.");
	CheckLog(sg);
}

int main()
{
	Simplygon::ISimplygon* sg = NULL;
	Simplygon::EErrorCodes initval = Simplygon::Initialize( &sg );
	if( initval != Simplygon::EErrorCodes::NoError )
	{
		printf( "Failed to initialize Simplygon: ErrorCode(%d)", (int)initval );
		return int(initval);
	}

	RunFlipbook(sg);

	Simplygon::Deinitialize(sg);

	return 0;
}
csharp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

using System;
using System.IO;
using System.Threading.Tasks;

public class Program
{
    static Simplygon.spScene LoadScene(Simplygon.ISimplygon sg, string path)
    {
        // Create scene importer 
        using Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter();
        sgSceneImporter.SetImportFilePath(path);
        
        // Run scene importer. 
        var importResult = sgSceneImporter.Run();
        if (Simplygon.Simplygon.Failed(importResult))
        {
            throw new System.Exception("Failed to load scene.");
        }
        Simplygon.spScene sgScene = sgSceneImporter.GetScene();
        return sgScene;
    }

    static void SaveScene(Simplygon.ISimplygon sg, Simplygon.spScene sgScene, string path)
    {
        // Create scene exporter. 
        using Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter();
        string outputScenePath = string.Join("", new string[] { "output\\", "ImpostorFlipbook", "_", path });
        sgSceneExporter.SetExportFilePath(outputScenePath);
        sgSceneExporter.SetScene(sgScene);
        
        // Run scene exporter. 
        var exportResult = sgSceneExporter.Run();
        if (Simplygon.Simplygon.Failed(exportResult))
        {
            throw new System.Exception("Failed to save scene.");
        }
    }

    static void CheckLog(Simplygon.ISimplygon sg)
    {
        // Check if any errors occurred. 
        bool hasErrors = sg.ErrorOccurred();
        if (hasErrors)
        {
            Simplygon.spStringArray errors = sg.CreateStringArray();
            sg.GetErrorMessages(errors);
            var errorCount = errors.GetItemCount();
            if (errorCount > 0)
            {
                Console.WriteLine("CheckLog: Errors:");
                for (uint errorIndex = 0; errorIndex < errorCount; ++errorIndex)
                {
                    string errorString = errors.GetItem((int)errorIndex);
                    Console.WriteLine(errorString);
                }
                sg.ClearErrorMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No errors.");
        }
        
        // Check if any warnings occurred. 
        bool hasWarnings = sg.WarningOccurred();
        if (hasWarnings)
        {
            Simplygon.spStringArray warnings = sg.CreateStringArray();
            sg.GetWarningMessages(warnings);
            var warningCount = warnings.GetItemCount();
            if (warningCount > 0)
            {
                Console.WriteLine("CheckLog: Warnings:");
                for (uint warningIndex = 0; warningIndex < warningCount; ++warningIndex)
                {
                    string warningString = warnings.GetItem((int)warningIndex);
                    Console.WriteLine(warningString);
                }
                sg.ClearWarningMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No warnings.");
        }
        
        // Error out if Simplygon has errors. 
        if (hasErrors)
        {
            throw new System.Exception("Processing failed with an error");
        }
    }

    static void RunFlipbook(Simplygon.ISimplygon sg)
    {
        // Load scene to process.         
        Console.WriteLine("Load scene to process.");
        Simplygon.spScene sgScene = LoadScene(sg, "../../../Assets/Bush/Bush.fbx");
        
        // For all materials in the scene set the blend mode to blend (instead of opaque) 
        for (int i = 0; i < (int)sgScene.GetMaterialTable().GetMaterialsCount(); ++i)
        {
            sgScene.GetMaterialTable().GetMaterial(i).SetBlendMode(Simplygon.EMaterialBlendMode.Blend);
        }
        
        // For all materials in the scene set the opacity mode to Opacity. 
        for (int i = 0; i < (int)sgScene.GetMaterialTable().GetMaterialsCount(); ++i)
        {
            sgScene.GetMaterialTable().GetMaterial(i).SetOpacityType(Simplygon.EOpacityType.Opacity);
        }
        
        // Create the Impostor processor. 
        using Simplygon.spImpostorProcessor sgImpostorProcessor = sg.CreateImpostorProcessor();
        sgImpostorProcessor.SetScene( sgScene );
        using Simplygon.spImpostorSettings sgImpostorSettings = sgImpostorProcessor.GetImpostorSettings();
        
        // Set impostor type to From single view. 
        sgImpostorSettings.SetImpostorType( Simplygon.EImpostorType.Flipbook );
        using Simplygon.spFlipbookSettings sgFlipbookSettings = sgImpostorSettings.GetFlipbookSettings();
        sgFlipbookSettings.SetNumberOfViews( 9 );
        sgFlipbookSettings.SetViewDirectionX( 1.0f );
        sgFlipbookSettings.SetViewDirectionY( 0.0f );
        sgFlipbookSettings.SetViewDirectionZ( 0.0f );
        sgFlipbookSettings.SetUpVectorX( 0.0f );
        sgFlipbookSettings.SetUpVectorY( 1.0f );
        sgFlipbookSettings.SetUpVectorZ( 0.0f );
        using Simplygon.spMappingImageSettings sgMappingImageSettings = sgImpostorProcessor.GetMappingImageSettings();
        sgMappingImageSettings.SetMaximumLayers( 10 );
        using Simplygon.spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0);
        
        // Setting the size of the output material for the mapping image. This will be the output size of the 
        // textures when we do material casting in a later stage. 
        sgOutputMaterialSettings.SetTextureWidth( 256 );
        sgOutputMaterialSettings.SetTextureHeight( 256 );
        sgOutputMaterialSettings.SetMultisamplingLevel( 2 );
        
        // Start the impostor process.         
        Console.WriteLine("Start the impostor process.");
        sgImpostorProcessor.RunProcessing();
        
        // Setup and run the diffuse material casting.         
        Console.WriteLine("Setup and run the diffuse material casting.");
        string diffuseTextureFilePath;
        using Simplygon.spColorCaster sgDiffuseCaster = sg.CreateColorCaster();
        sgDiffuseCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgDiffuseCaster.SetOutputFilePath( "DiffuseTexture" );

        using Simplygon.spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings();
        sgDiffuseCasterSettings.SetMaterialChannel( "Diffuse" );
        sgDiffuseCasterSettings.SetOpacityChannel( "Opacity" );
        sgDiffuseCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgDiffuseCasterSettings.SetBakeOpacityInAlpha( false );
        sgDiffuseCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8G8B8 );
        sgDiffuseCasterSettings.SetDilation( 10 );
        sgDiffuseCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgDiffuseCaster.RunProcessing();
        diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath();
        
        // Setup and run the specular material casting.         
        Console.WriteLine("Setup and run the specular material casting.");
        string specularTextureFilePath;
        using Simplygon.spColorCaster sgSpecularCaster = sg.CreateColorCaster();
        sgSpecularCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgSpecularCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgSpecularCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgSpecularCaster.SetOutputFilePath( "SpecularTexture" );

        using Simplygon.spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster.GetColorCasterSettings();
        sgSpecularCasterSettings.SetMaterialChannel( "Specular" );
        sgSpecularCasterSettings.SetOpacityChannel( "Opacity" );
        sgSpecularCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgSpecularCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgSpecularCasterSettings.SetDilation( 10 );
        sgSpecularCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgSpecularCaster.RunProcessing();
        specularTextureFilePath = sgSpecularCaster.GetOutputFilePath();
        
        // Setup and run the normals material casting.         
        Console.WriteLine("Setup and run the normals material casting.");
        string normalsTextureFilePath;
        using Simplygon.spNormalCaster sgNormalsCaster = sg.CreateNormalCaster();
        sgNormalsCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgNormalsCaster.SetOutputFilePath( "NormalsTexture" );

        using Simplygon.spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings();
        sgNormalsCasterSettings.SetMaterialChannel( "Normals" );
        sgNormalsCasterSettings.SetOpacityChannel( "Opacity" );
        sgNormalsCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( true );
        sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgNormalsCasterSettings.SetDilation( 10 );
        sgNormalsCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgNormalsCaster.RunProcessing();
        normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath();
        
        // Setup and run the opacity material casting. Make sure there is no dilation or fill.         
        Console.WriteLine("Setup and run the opacity material casting. Make sure there is no dilation or fill.");
        string opacityTextureFilePath;
        using Simplygon.spOpacityCaster sgOpacityCaster = sg.CreateOpacityCaster();
        sgOpacityCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgOpacityCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgOpacityCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgOpacityCaster.SetOutputFilePath( "OpacityTexture" );

        using Simplygon.spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster.GetOpacityCasterSettings();
        sgOpacityCasterSettings.SetMaterialChannel( "Opacity" );
        sgOpacityCasterSettings.SetOpacityChannel( "Opacity" );
        sgOpacityCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgOpacityCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgOpacityCasterSettings.SetDilation( 0 );
        sgOpacityCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.NoFill );
        sgOpacityCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8 );

        sgOpacityCaster.RunProcessing();
        opacityTextureFilePath = sgOpacityCaster.GetOutputFilePath();
        
        // Update scene with new casted textures. 
        using Simplygon.spMaterialTable sgMaterialTable = sg.CreateMaterialTable();
        using Simplygon.spTextureTable sgTextureTable = sg.CreateTextureTable();
        using Simplygon.spMaterial sgMaterial = sg.CreateMaterial();
        sgMaterial.SetName("OutputMaterial");
        using Simplygon.spTexture sgDiffuseTexture = sg.CreateTexture();
        sgDiffuseTexture.SetName( "Diffuse" );
        sgDiffuseTexture.SetFilePath( diffuseTextureFilePath );
        sgTextureTable.AddTexture( sgDiffuseTexture );

        using Simplygon.spShadingTextureNode sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode();
        sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 );
        sgDiffuseTextureShadingNode.SetTextureName( "Diffuse" );

        sgMaterial.AddMaterialChannel( "Diffuse" );
        sgMaterial.SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );
        using Simplygon.spTexture sgSpecularTexture = sg.CreateTexture();
        sgSpecularTexture.SetName( "Specular" );
        sgSpecularTexture.SetFilePath( specularTextureFilePath );
        sgTextureTable.AddTexture( sgSpecularTexture );

        using Simplygon.spShadingTextureNode sgSpecularTextureShadingNode = sg.CreateShadingTextureNode();
        sgSpecularTextureShadingNode.SetTexCoordLevel( 0 );
        sgSpecularTextureShadingNode.SetTextureName( "Specular" );

        sgMaterial.AddMaterialChannel( "Specular" );
        sgMaterial.SetShadingNetwork( "Specular", sgSpecularTextureShadingNode );
        using Simplygon.spTexture sgNormalsTexture = sg.CreateTexture();
        sgNormalsTexture.SetName( "Normals" );
        sgNormalsTexture.SetFilePath( normalsTextureFilePath );
        sgTextureTable.AddTexture( sgNormalsTexture );

        using Simplygon.spShadingTextureNode sgNormalsTextureShadingNode = sg.CreateShadingTextureNode();
        sgNormalsTextureShadingNode.SetTexCoordLevel( 0 );
        sgNormalsTextureShadingNode.SetTextureName( "Normals" );

        sgMaterial.AddMaterialChannel( "Normals" );
        sgMaterial.SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );
        using Simplygon.spTexture sgOpacityTexture = sg.CreateTexture();
        sgOpacityTexture.SetName( "Opacity" );
        sgOpacityTexture.SetFilePath( opacityTextureFilePath );
        sgTextureTable.AddTexture( sgOpacityTexture );

        using Simplygon.spShadingTextureNode sgOpacityTextureShadingNode = sg.CreateShadingTextureNode();
        sgOpacityTextureShadingNode.SetTexCoordLevel( 0 );
        sgOpacityTextureShadingNode.SetTextureName( "Opacity" );

        sgMaterial.AddMaterialChannel( "Opacity" );
        sgMaterial.SetShadingNetwork( "Opacity", sgOpacityTextureShadingNode );
        sgMaterial.SetBlendMode(Simplygon.EMaterialBlendMode.Blend);

        sgMaterialTable.AddMaterial( sgMaterial );

        sgScene.GetTextureTable().Clear();
        sgScene.GetMaterialTable().Clear();
        sgScene.GetTextureTable().Copy(sgTextureTable);
        sgScene.GetMaterialTable().Copy(sgMaterialTable);
        
        // Save processed scene.         
        Console.WriteLine("Save processed scene.");
        SaveScene(sg, sgScene, "Output.glb");
        
        // Check log for any warnings or errors.         
        Console.WriteLine("Check log for any warnings or errors.");
        CheckLog(sg);
    }

    static int Main(string[] args)
    {
        using var sg = Simplygon.Loader.InitSimplygon(out var errorCode, out var errorMessage);
        if (errorCode != Simplygon.EErrorCodes.NoError)
        {
            Console.WriteLine( $"Failed to initialize Simplygon: ErrorCode({(int)errorCode}) {errorMessage}" );
            return (int)errorCode;
        }
        RunFlipbook(sg);

        return 0;
    }

}
python
# Copyright (c) Microsoft Corporation. 
# Licensed under the MIT License. 

import math
import os
import sys
import glob
import gc
import threading

from pathlib import Path
from simplygon10 import simplygon_loader
from simplygon10 import Simplygon


def LoadScene(sg: Simplygon.ISimplygon, path: str):
    # Create scene importer 
    sgSceneImporter = sg.CreateSceneImporter()
    sgSceneImporter.SetImportFilePath(path)
    
    # Run scene importer. 
    importResult = sgSceneImporter.Run()
    if Simplygon.Failed(importResult):
        raise Exception('Failed to load scene.')
    sgScene = sgSceneImporter.GetScene()
    return sgScene

def SaveScene(sg: Simplygon.ISimplygon, sgScene: Simplygon.spScene, path: str):
    # Create scene exporter. 
    sgSceneExporter = sg.CreateSceneExporter()
    outputScenePath = ''.join(['output\\', 'ImpostorFlipbook', '_', path])
    sgSceneExporter.SetExportFilePath(outputScenePath)
    sgSceneExporter.SetScene(sgScene)
    
    # Run scene exporter. 
    exportResult = sgSceneExporter.Run()
    if Simplygon.Failed(exportResult):
        raise Exception('Failed to save scene.')

def CheckLog(sg: Simplygon.ISimplygon):
    # Check if any errors occurred. 
    hasErrors = sg.ErrorOccurred()
    if hasErrors:
        errors = sg.CreateStringArray()
        sg.GetErrorMessages(errors)
        errorCount = errors.GetItemCount()
        if errorCount > 0:
            print('CheckLog: Errors:')
            for errorIndex in range(errorCount):
                errorString = errors.GetItem(errorIndex)
                print(errorString)
            sg.ClearErrorMessages()
    else:
        print('CheckLog: No errors.')
    
    # Check if any warnings occurred. 
    hasWarnings = sg.WarningOccurred()
    if hasWarnings:
        warnings = sg.CreateStringArray()
        sg.GetWarningMessages(warnings)
        warningCount = warnings.GetItemCount()
        if warningCount > 0:
            print('CheckLog: Warnings:')
            for warningIndex in range(warningCount):
                warningString = warnings.GetItem(warningIndex)
                print(warningString)
            sg.ClearWarningMessages()
    else:
        print('CheckLog: No warnings.')
    
    # Error out if Simplygon has errors. 
    if hasErrors:
        raise Exception('Processing failed with an error')

def RunFlipbook(sg: Simplygon.ISimplygon):
    # Load scene to process.     
    print("Load scene to process.")
    sgScene = LoadScene(sg, '../../../Assets/Bush/Bush.fbx')
    
    # For all materials in the scene set the blend mode to blend (instead of opaque) 
    materialCount = sgScene.GetMaterialTable().GetMaterialsCount()
    for i in range(0, materialCount):
        sgScene.GetMaterialTable().GetMaterial(i).SetBlendMode(Simplygon.EMaterialBlendMode_Blend)
    
    # For all materials in the scene set the opacity mode to Opacity. 
    materialCount = sgScene.GetMaterialTable().GetMaterialsCount()
    for i in range(0, materialCount):
        sgScene.GetMaterialTable().GetMaterial(i).SetOpacityType(Simplygon.EOpacityType_Opacity)
    
    # Create the Impostor processor. 
    sgImpostorProcessor = sg.CreateImpostorProcessor()
    sgImpostorProcessor.SetScene( sgScene )
    sgImpostorSettings = sgImpostorProcessor.GetImpostorSettings()
    
    # Set impostor type to From single view. 
    sgImpostorSettings.SetImpostorType( Simplygon.EImpostorType_Flipbook )
    sgFlipbookSettings = sgImpostorSettings.GetFlipbookSettings()
    sgFlipbookSettings.SetNumberOfViews( 9 )
    sgFlipbookSettings.SetViewDirectionX( 1.0 )
    sgFlipbookSettings.SetViewDirectionY( 0.0 )
    sgFlipbookSettings.SetViewDirectionZ( 0.0 )
    sgFlipbookSettings.SetUpVectorX( 0.0 )
    sgFlipbookSettings.SetUpVectorY( 1.0 )
    sgFlipbookSettings.SetUpVectorZ( 0.0 )
    sgMappingImageSettings = sgImpostorProcessor.GetMappingImageSettings()
    sgMappingImageSettings.SetMaximumLayers( 10 )
    sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0)
    
    # Setting the size of the output material for the mapping image. This will be the output size of the 
    # textures when we do material casting in a later stage. 
    sgOutputMaterialSettings.SetTextureWidth( 256 )
    sgOutputMaterialSettings.SetTextureHeight( 256 )
    sgOutputMaterialSettings.SetMultisamplingLevel( 2 )
    
    # Start the impostor process.     
    print("Start the impostor process.")
    sgImpostorProcessor.RunProcessing()
    
    # Setup and run the diffuse material casting.     
    print("Setup and run the diffuse material casting.")
    sgDiffuseCaster = sg.CreateColorCaster()
    sgDiffuseCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgDiffuseCaster.SetOutputFilePath( 'DiffuseTexture' )

    sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings()
    sgDiffuseCasterSettings.SetMaterialChannel( 'Diffuse' )
    sgDiffuseCasterSettings.SetOpacityChannel( 'Opacity' )
    sgDiffuseCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgDiffuseCasterSettings.SetBakeOpacityInAlpha( False )
    sgDiffuseCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8G8B8 )
    sgDiffuseCasterSettings.SetDilation( 10 )
    sgDiffuseCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgDiffuseCaster.RunProcessing()
    diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath()
    
    # Setup and run the specular material casting.     
    print("Setup and run the specular material casting.")
    sgSpecularCaster = sg.CreateColorCaster()
    sgSpecularCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgSpecularCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgSpecularCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgSpecularCaster.SetOutputFilePath( 'SpecularTexture' )

    sgSpecularCasterSettings = sgSpecularCaster.GetColorCasterSettings()
    sgSpecularCasterSettings.SetMaterialChannel( 'Specular' )
    sgSpecularCasterSettings.SetOpacityChannel( 'Opacity' )
    sgSpecularCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgSpecularCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgSpecularCasterSettings.SetDilation( 10 )
    sgSpecularCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgSpecularCaster.RunProcessing()
    specularTextureFilePath = sgSpecularCaster.GetOutputFilePath()
    
    # Setup and run the normals material casting.     
    print("Setup and run the normals material casting.")
    sgNormalsCaster = sg.CreateNormalCaster()
    sgNormalsCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgNormalsCaster.SetOutputFilePath( 'NormalsTexture' )

    sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings()
    sgNormalsCasterSettings.SetMaterialChannel( 'Normals' )
    sgNormalsCasterSettings.SetOpacityChannel( 'Opacity' )
    sgNormalsCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( True )
    sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgNormalsCasterSettings.SetDilation( 10 )
    sgNormalsCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgNormalsCaster.RunProcessing()
    normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath()
    
    # Setup and run the opacity material casting. Make sure there is no dilation or fill.     
    print("Setup and run the opacity material casting. Make sure there is no dilation or fill.")
    sgOpacityCaster = sg.CreateOpacityCaster()
    sgOpacityCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgOpacityCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgOpacityCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgOpacityCaster.SetOutputFilePath( 'OpacityTexture' )

    sgOpacityCasterSettings = sgOpacityCaster.GetOpacityCasterSettings()
    sgOpacityCasterSettings.SetMaterialChannel( 'Opacity' )
    sgOpacityCasterSettings.SetOpacityChannel( 'Opacity' )
    sgOpacityCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgOpacityCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgOpacityCasterSettings.SetDilation( 0 )
    sgOpacityCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_NoFill )
    sgOpacityCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8 )

    sgOpacityCaster.RunProcessing()
    opacityTextureFilePath = sgOpacityCaster.GetOutputFilePath()
    
    # Update scene with new casted textures. 
    sgMaterialTable = sg.CreateMaterialTable()
    sgTextureTable = sg.CreateTextureTable()
    sgMaterial = sg.CreateMaterial()
    sgMaterial.SetName("OutputMaterial")
    sgDiffuseTexture = sg.CreateTexture()
    sgDiffuseTexture.SetName( 'Diffuse' )
    sgDiffuseTexture.SetFilePath( diffuseTextureFilePath )
    sgTextureTable.AddTexture( sgDiffuseTexture )

    sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode()
    sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 )
    sgDiffuseTextureShadingNode.SetTextureName( 'Diffuse' )

    sgMaterial.AddMaterialChannel( 'Diffuse' )
    sgMaterial.SetShadingNetwork( 'Diffuse', sgDiffuseTextureShadingNode )
    sgSpecularTexture = sg.CreateTexture()
    sgSpecularTexture.SetName( 'Specular' )
    sgSpecularTexture.SetFilePath( specularTextureFilePath )
    sgTextureTable.AddTexture( sgSpecularTexture )

    sgSpecularTextureShadingNode = sg.CreateShadingTextureNode()
    sgSpecularTextureShadingNode.SetTexCoordLevel( 0 )
    sgSpecularTextureShadingNode.SetTextureName( 'Specular' )

    sgMaterial.AddMaterialChannel( 'Specular' )
    sgMaterial.SetShadingNetwork( 'Specular', sgSpecularTextureShadingNode )
    sgNormalsTexture = sg.CreateTexture()
    sgNormalsTexture.SetName( 'Normals' )
    sgNormalsTexture.SetFilePath( normalsTextureFilePath )
    sgTextureTable.AddTexture( sgNormalsTexture )

    sgNormalsTextureShadingNode = sg.CreateShadingTextureNode()
    sgNormalsTextureShadingNode.SetTexCoordLevel( 0 )
    sgNormalsTextureShadingNode.SetTextureName( 'Normals' )

    sgMaterial.AddMaterialChannel( 'Normals' )
    sgMaterial.SetShadingNetwork( 'Normals', sgNormalsTextureShadingNode )
    sgOpacityTexture = sg.CreateTexture()
    sgOpacityTexture.SetName( 'Opacity' )
    sgOpacityTexture.SetFilePath( opacityTextureFilePath )
    sgTextureTable.AddTexture( sgOpacityTexture )

    sgOpacityTextureShadingNode = sg.CreateShadingTextureNode()
    sgOpacityTextureShadingNode.SetTexCoordLevel( 0 )
    sgOpacityTextureShadingNode.SetTextureName( 'Opacity' )

    sgMaterial.AddMaterialChannel( 'Opacity' )
    sgMaterial.SetShadingNetwork( 'Opacity', sgOpacityTextureShadingNode )
    sgMaterial.SetBlendMode(Simplygon.EMaterialBlendMode_Blend);

    sgMaterialTable.AddMaterial( sgMaterial )

    sgScene.GetTextureTable().Clear()
    sgScene.GetMaterialTable().Clear()
    sgScene.GetTextureTable().Copy(sgTextureTable)
    sgScene.GetMaterialTable().Copy(sgMaterialTable)
    
    # Save processed scene.     
    print("Save processed scene.")
    SaveScene(sg, sgScene, 'Output.glb')
    
    # Check log for any warnings or errors.     
    print("Check log for any warnings or errors.")
    CheckLog(sg)

if __name__ == '__main__':
        sg = simplygon_loader.init_simplygon()
        if sg is None:
            exit(Simplygon.GetLastInitializationError())

        RunFlipbook(sg)

        sg = None
        gc.collect()

From single view

This example shows how to use the Impostor processor type: Impostor from single view.

cpp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

#include <string>
#include <stdlib.h>
#include <filesystem>
#include <future>
#include "SimplygonLoader.h"


Simplygon::spScene LoadScene(Simplygon::ISimplygon* sg, const char* path)
{
	// Create scene importer 
	Simplygon::spSceneImporter sgSceneImporter = sg->CreateSceneImporter();
	sgSceneImporter->SetImportFilePath(path);
	
	// Run scene importer. 
	auto importResult = sgSceneImporter->Run();
	if (Simplygon::Failed(importResult))
	{
		throw std::exception("Failed to load scene.");
	}
	Simplygon::spScene sgScene = sgSceneImporter->GetScene();
	return sgScene;
}

void SaveScene(Simplygon::ISimplygon* sg, Simplygon::spScene sgScene, const char* path)
{
	// Create scene exporter. 
	Simplygon::spSceneExporter sgSceneExporter = sg->CreateSceneExporter();
	std::string outputScenePath = std::string("output\\") + std::string("ImpostorFromSingleView") + std::string("_") + std::string(path);
	sgSceneExporter->SetExportFilePath(outputScenePath.c_str());
	sgSceneExporter->SetScene(sgScene);
	
	// Run scene exporter. 
	auto exportResult = sgSceneExporter->Run();
	if (Simplygon::Failed(exportResult))
	{
		throw std::exception("Failed to save scene.");
	}
}

void CheckLog(Simplygon::ISimplygon* sg)
{
	// Check if any errors occurred. 
	bool hasErrors = sg->ErrorOccurred();
	if (hasErrors)
	{
		Simplygon::spStringArray errors = sg->CreateStringArray();
		sg->GetErrorMessages(errors);
		auto errorCount = errors->GetItemCount();
		if (errorCount > 0)
		{
			printf("%s\n", "CheckLog: Errors:");
			for (auto errorIndex = 0U; errorIndex < errorCount; ++errorIndex)
			{
				Simplygon::spString errorString = errors->GetItem((int)errorIndex);
				printf("%s\n", errorString.c_str());
			}
			sg->ClearErrorMessages();
		}
	}
	else
	{
		printf("%s\n", "CheckLog: No errors.");
	}
	
	// Check if any warnings occurred. 
	bool hasWarnings = sg->WarningOccurred();
	if (hasWarnings)
	{
		Simplygon::spStringArray warnings = sg->CreateStringArray();
		sg->GetWarningMessages(warnings);
		auto warningCount = warnings->GetItemCount();
		if (warningCount > 0)
		{
			printf("%s\n", "CheckLog: Warnings:");
			for (auto warningIndex = 0U; warningIndex < warningCount; ++warningIndex)
			{
				Simplygon::spString warningString = warnings->GetItem((int)warningIndex);
				printf("%s\n", warningString.c_str());
			}
			sg->ClearWarningMessages();
		}
	}
	else
	{
		printf("%s\n", "CheckLog: No warnings.");
	}
	
	// Error out if Simplygon has errors. 
	if (hasErrors)
	{
		throw std::exception("Processing failed with an error");
	}
}

void RunImpostorFromSingleView(Simplygon::ISimplygon* sg)
{
	// Load scene to process. 	
	printf("%s\n", "Load scene to process.");
	Simplygon::spScene sgScene = LoadScene(sg, "../../../Assets/Bush/Bush.fbx");
	
	// For all materials in the scene set the blend mode to blend (instead of opaque) 
	for (int i = 0; i < (int)sgScene->GetMaterialTable()->GetMaterialsCount(); ++i)
	{
		sgScene->GetMaterialTable()->GetMaterial(i)->SetBlendMode(Simplygon::EMaterialBlendMode::Blend);
	}
	
	// For all materials in the scene set the opacity mode to Opacity. 
	for (int i = 0; i < (int)sgScene->GetMaterialTable()->GetMaterialsCount(); ++i)
	{
		sgScene->GetMaterialTable()->GetMaterial(i)->SetOpacityType(Simplygon::EOpacityType::Opacity);
	}
	
	// Create the Impostor processor. 
	Simplygon::spImpostorProcessor sgImpostorProcessor = sg->CreateImpostorProcessor();
	sgImpostorProcessor->SetScene( sgScene );
	Simplygon::spImpostorSettings sgImpostorSettings = sgImpostorProcessor->GetImpostorSettings();
	
	// Set impostor type to From single view. 
	sgImpostorSettings->SetImpostorType( Simplygon::EImpostorType::FromSingleView );
	Simplygon::real viewDir[] = {0.0f, 0.0f, -1.0f};

	Simplygon::spImpostorFromSingleViewSettings sgImpostorFromSingleViewSettings = sgImpostorSettings->GetImpostorFromSingleViewSettings();
	sgImpostorFromSingleViewSettings->SetUseTightFitting( true );
	sgImpostorFromSingleViewSettings->SetTightFittingDepthOffset( 1.0f );
	sgImpostorFromSingleViewSettings->SetTexCoordPadding( 0.01f );
	sgImpostorFromSingleViewSettings->SetViewDirection( viewDir );
	// Once geometry and settings are set, you can calculate the aspect ratio for the textures.
	Simplygon::real aspect = sgImpostorProcessor->GetSingleViewAspectRatio();
	if (aspect < 0.0f)
		throw std::exception("Failed to compute aspect ratio!");
	int xDim = int(aspect * 512);
	int yDim = int(1.f * 512);
	Simplygon::spMappingImageSettings sgMappingImageSettings = sgImpostorProcessor->GetMappingImageSettings();
	sgMappingImageSettings->SetMaximumLayers( 10 );
	Simplygon::spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings->GetOutputMaterialSettings(0);
	
	// Setting the size of the output material for the mapping image. This will be the output size of the 
	// textures when we do material casting in a later stage. 
	sgOutputMaterialSettings->SetTextureWidth( xDim );
	sgOutputMaterialSettings->SetTextureHeight( yDim );
	sgOutputMaterialSettings->SetMultisamplingLevel( 2 );
	
	// Start the impostor process. 	
	printf("%s\n", "Start the impostor process.");
	sgImpostorProcessor->RunProcessing();
	
	// Setup and run the diffuse material casting. 	
	printf("%s\n", "Setup and run the diffuse material casting.");
	Simplygon::spColorCaster sgDiffuseCaster = sg->CreateColorCaster();
	sgDiffuseCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgDiffuseCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgDiffuseCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgDiffuseCaster->SetOutputFilePath( "DiffuseTexture" );

	Simplygon::spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster->GetColorCasterSettings();
	sgDiffuseCasterSettings->SetMaterialChannel( "Diffuse" );
	sgDiffuseCasterSettings->SetOpacityChannel( "Opacity" );
	sgDiffuseCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgDiffuseCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgDiffuseCasterSettings->SetBakeOpacityInAlpha( false );
	sgDiffuseCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8G8B8 );
	sgDiffuseCasterSettings->SetDilation( 10 );
	sgDiffuseCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgDiffuseCaster->RunProcessing();
	std::string diffuseTextureFilePath = sgDiffuseCaster->GetOutputFilePath().c_str();
	
	// Setup and run the specular material casting. 	
	printf("%s\n", "Setup and run the specular material casting.");
	Simplygon::spColorCaster sgSpecularCaster = sg->CreateColorCaster();
	sgSpecularCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgSpecularCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgSpecularCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgSpecularCaster->SetOutputFilePath( "SpecularTexture" );

	Simplygon::spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster->GetColorCasterSettings();
	sgSpecularCasterSettings->SetMaterialChannel( "Specular" );
	sgSpecularCasterSettings->SetOpacityChannel( "Opacity" );
	sgSpecularCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgSpecularCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgSpecularCasterSettings->SetDilation( 10 );
	sgSpecularCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgSpecularCaster->RunProcessing();
	std::string specularTextureFilePath = sgSpecularCaster->GetOutputFilePath().c_str();
	
	// Setup and run the normals material casting. 	
	printf("%s\n", "Setup and run the normals material casting.");
	Simplygon::spNormalCaster sgNormalsCaster = sg->CreateNormalCaster();
	sgNormalsCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgNormalsCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgNormalsCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgNormalsCaster->SetOutputFilePath( "NormalsTexture" );

	Simplygon::spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster->GetNormalCasterSettings();
	sgNormalsCasterSettings->SetMaterialChannel( "Normals" );
	sgNormalsCasterSettings->SetOpacityChannel( "Opacity" );
	sgNormalsCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgNormalsCasterSettings->SetGenerateTangentSpaceNormals( true );
	sgNormalsCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgNormalsCasterSettings->SetDilation( 10 );
	sgNormalsCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::Interpolate );

	sgNormalsCaster->RunProcessing();
	std::string normalsTextureFilePath = sgNormalsCaster->GetOutputFilePath().c_str();
	
	// Setup and run the opacity material casting. Make sure there is no dilation or fill. 	
	printf("%s\n", "Setup and run the opacity material casting. Make sure there is no dilation or fill.");
	Simplygon::spOpacityCaster sgOpacityCaster = sg->CreateOpacityCaster();
	sgOpacityCaster->SetMappingImage( sgImpostorProcessor->GetMappingImage() );
	sgOpacityCaster->SetSourceMaterials( sgScene->GetMaterialTable() );
	sgOpacityCaster->SetSourceTextures( sgScene->GetTextureTable() );
	sgOpacityCaster->SetOutputFilePath( "OpacityTexture" );

	Simplygon::spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster->GetOpacityCasterSettings();
	sgOpacityCasterSettings->SetMaterialChannel( "Opacity" );
	sgOpacityCasterSettings->SetOpacityChannel( "Opacity" );
	sgOpacityCasterSettings->SetOpacityChannelComponent( Simplygon::EColorComponent::Alpha );
	sgOpacityCasterSettings->SetOutputImageFileFormat( Simplygon::EImageOutputFormat::PNG );
	sgOpacityCasterSettings->SetDilation( 0 );
	sgOpacityCasterSettings->SetFillMode( Simplygon::EAtlasFillMode::NoFill );
	sgOpacityCasterSettings->SetOutputPixelFormat( Simplygon::EPixelFormat::R8 );

	sgOpacityCaster->RunProcessing();
	std::string opacityTextureFilePath = sgOpacityCaster->GetOutputFilePath().c_str();
	
	// Update scene with new casted textures. 
	Simplygon::spMaterialTable sgMaterialTable = sg->CreateMaterialTable();
	Simplygon::spTextureTable sgTextureTable = sg->CreateTextureTable();
	Simplygon::spMaterial sgMaterial = sg->CreateMaterial();
	sgMaterial->SetName("OutputMaterial");
	Simplygon::spTexture sgDiffuseTexture = sg->CreateTexture();
	sgDiffuseTexture->SetName( "Diffuse" );
	sgDiffuseTexture->SetFilePath( diffuseTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgDiffuseTexture );

	Simplygon::spShadingTextureNode sgDiffuseTextureShadingNode = sg->CreateShadingTextureNode();
	sgDiffuseTextureShadingNode->SetTexCoordLevel( 0 );
	sgDiffuseTextureShadingNode->SetTextureName( "Diffuse" );

	sgMaterial->AddMaterialChannel( "Diffuse" );
	sgMaterial->SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );
	Simplygon::spTexture sgSpecularTexture = sg->CreateTexture();
	sgSpecularTexture->SetName( "Specular" );
	sgSpecularTexture->SetFilePath( specularTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgSpecularTexture );

	Simplygon::spShadingTextureNode sgSpecularTextureShadingNode = sg->CreateShadingTextureNode();
	sgSpecularTextureShadingNode->SetTexCoordLevel( 0 );
	sgSpecularTextureShadingNode->SetTextureName( "Specular" );

	sgMaterial->AddMaterialChannel( "Specular" );
	sgMaterial->SetShadingNetwork( "Specular", sgSpecularTextureShadingNode );
	Simplygon::spTexture sgNormalsTexture = sg->CreateTexture();
	sgNormalsTexture->SetName( "Normals" );
	sgNormalsTexture->SetFilePath( normalsTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgNormalsTexture );

	Simplygon::spShadingTextureNode sgNormalsTextureShadingNode = sg->CreateShadingTextureNode();
	sgNormalsTextureShadingNode->SetTexCoordLevel( 0 );
	sgNormalsTextureShadingNode->SetTextureName( "Normals" );

	sgMaterial->AddMaterialChannel( "Normals" );
	sgMaterial->SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );
	Simplygon::spTexture sgOpacityTexture = sg->CreateTexture();
	sgOpacityTexture->SetName( "Opacity" );
	sgOpacityTexture->SetFilePath( opacityTextureFilePath.c_str() );
	sgTextureTable->AddTexture( sgOpacityTexture );

	Simplygon::spShadingTextureNode sgOpacityTextureShadingNode = sg->CreateShadingTextureNode();
	sgOpacityTextureShadingNode->SetTexCoordLevel( 0 );
	sgOpacityTextureShadingNode->SetTextureName( "Opacity" );

	sgMaterial->AddMaterialChannel( "Opacity" );
	sgMaterial->SetShadingNetwork( "Opacity", sgOpacityTextureShadingNode );
	sgMaterial->SetBlendMode(Simplygon::EMaterialBlendMode::Blend);

	sgMaterialTable->AddMaterial( sgMaterial );

	sgScene->GetTextureTable()->Clear();
	sgScene->GetMaterialTable()->Clear();
	sgScene->GetTextureTable()->Copy(sgTextureTable);
	sgScene->GetMaterialTable()->Copy(sgMaterialTable);
	Simplygon::spScene sgImpostorScene = sg->CreateScene();
	Simplygon::spGeometryData sgImpostorGeometry = sgImpostorProcessor->GetImpostorGeometryFromSingleView();
	sgImpostorScene->GetRootNode()->CreateChildMesh(sgImpostorGeometry);
	sgImpostorScene->GetMaterialTable()->Copy(sgScene->GetMaterialTable());
	sgImpostorScene->GetTextureTable()->Copy(sgScene->GetTextureTable());
	
	// Save processed scene. 	
	printf("%s\n", "Save processed scene.");
	SaveScene(sg, sgImpostorScene, "Output.glb");
	
	// Check log for any warnings or errors. 	
	printf("%s\n", "Check log for any warnings or errors.");
	CheckLog(sg);
}

int main()
{
	Simplygon::ISimplygon* sg = NULL;
	Simplygon::EErrorCodes initval = Simplygon::Initialize( &sg );
	if( initval != Simplygon::EErrorCodes::NoError )
	{
		printf( "Failed to initialize Simplygon: ErrorCode(%d)", (int)initval );
		return int(initval);
	}

	RunImpostorFromSingleView(sg);

	Simplygon::Deinitialize(sg);

	return 0;
}
csharp
// Copyright (c) Microsoft Corporation. 
// Licensed under the MIT License. 

using System;
using System.IO;
using System.Threading.Tasks;

public class Program
{
    static Simplygon.spScene LoadScene(Simplygon.ISimplygon sg, string path)
    {
        // Create scene importer 
        using Simplygon.spSceneImporter sgSceneImporter = sg.CreateSceneImporter();
        sgSceneImporter.SetImportFilePath(path);
        
        // Run scene importer. 
        var importResult = sgSceneImporter.Run();
        if (Simplygon.Simplygon.Failed(importResult))
        {
            throw new System.Exception("Failed to load scene.");
        }
        Simplygon.spScene sgScene = sgSceneImporter.GetScene();
        return sgScene;
    }

    static void SaveScene(Simplygon.ISimplygon sg, Simplygon.spScene sgScene, string path)
    {
        // Create scene exporter. 
        using Simplygon.spSceneExporter sgSceneExporter = sg.CreateSceneExporter();
        string outputScenePath = string.Join("", new string[] { "output\\", "ImpostorFromSingleView", "_", path });
        sgSceneExporter.SetExportFilePath(outputScenePath);
        sgSceneExporter.SetScene(sgScene);
        
        // Run scene exporter. 
        var exportResult = sgSceneExporter.Run();
        if (Simplygon.Simplygon.Failed(exportResult))
        {
            throw new System.Exception("Failed to save scene.");
        }
    }

    static void CheckLog(Simplygon.ISimplygon sg)
    {
        // Check if any errors occurred. 
        bool hasErrors = sg.ErrorOccurred();
        if (hasErrors)
        {
            Simplygon.spStringArray errors = sg.CreateStringArray();
            sg.GetErrorMessages(errors);
            var errorCount = errors.GetItemCount();
            if (errorCount > 0)
            {
                Console.WriteLine("CheckLog: Errors:");
                for (uint errorIndex = 0; errorIndex < errorCount; ++errorIndex)
                {
                    string errorString = errors.GetItem((int)errorIndex);
                    Console.WriteLine(errorString);
                }
                sg.ClearErrorMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No errors.");
        }
        
        // Check if any warnings occurred. 
        bool hasWarnings = sg.WarningOccurred();
        if (hasWarnings)
        {
            Simplygon.spStringArray warnings = sg.CreateStringArray();
            sg.GetWarningMessages(warnings);
            var warningCount = warnings.GetItemCount();
            if (warningCount > 0)
            {
                Console.WriteLine("CheckLog: Warnings:");
                for (uint warningIndex = 0; warningIndex < warningCount; ++warningIndex)
                {
                    string warningString = warnings.GetItem((int)warningIndex);
                    Console.WriteLine(warningString);
                }
                sg.ClearWarningMessages();
            }
        }
        else
        {
            Console.WriteLine("CheckLog: No warnings.");
        }
        
        // Error out if Simplygon has errors. 
        if (hasErrors)
        {
            throw new System.Exception("Processing failed with an error");
        }
    }

    static void RunImpostorFromSingleView(Simplygon.ISimplygon sg)
    {
        // Load scene to process.         
        Console.WriteLine("Load scene to process.");
        Simplygon.spScene sgScene = LoadScene(sg, "../../../Assets/Bush/Bush.fbx");
        
        // For all materials in the scene set the blend mode to blend (instead of opaque) 
        for (int i = 0; i < (int)sgScene.GetMaterialTable().GetMaterialsCount(); ++i)
        {
            sgScene.GetMaterialTable().GetMaterial(i).SetBlendMode(Simplygon.EMaterialBlendMode.Blend);
        }
        
        // For all materials in the scene set the opacity mode to Opacity. 
        for (int i = 0; i < (int)sgScene.GetMaterialTable().GetMaterialsCount(); ++i)
        {
            sgScene.GetMaterialTable().GetMaterial(i).SetOpacityType(Simplygon.EOpacityType.Opacity);
        }
        
        // Create the Impostor processor. 
        using Simplygon.spImpostorProcessor sgImpostorProcessor = sg.CreateImpostorProcessor();
        sgImpostorProcessor.SetScene( sgScene );
        using Simplygon.spImpostorSettings sgImpostorSettings = sgImpostorProcessor.GetImpostorSettings();
        
        // Set impostor type to From single view. 
        sgImpostorSettings.SetImpostorType( Simplygon.EImpostorType.FromSingleView );
        float[] viewDir = {0.0f, 0.0f, -1.0f};

        using Simplygon.spImpostorFromSingleViewSettings sgImpostorFromSingleViewSettings = sgImpostorSettings.GetImpostorFromSingleViewSettings();
        sgImpostorFromSingleViewSettings.SetUseTightFitting( true );
        sgImpostorFromSingleViewSettings.SetTightFittingDepthOffset( 1.0f );
        sgImpostorFromSingleViewSettings.SetTexCoordPadding( 0.01f );
        sgImpostorFromSingleViewSettings.SetViewDirection( viewDir );
        // Once geometry and settings are set, you can calculate the aspect ratio for the textures.
        float aspect = sgImpostorProcessor.GetSingleViewAspectRatio();
        if (aspect < 0.0f)
            throw new System.Exception("Failed to compute aspect ratio!");
        uint xDim = (uint)(aspect * 512);
        uint yDim = (uint)(1.0f * 512);
        using Simplygon.spMappingImageSettings sgMappingImageSettings = sgImpostorProcessor.GetMappingImageSettings();
        sgMappingImageSettings.SetMaximumLayers( 10 );
        using Simplygon.spMappingImageOutputMaterialSettings sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0);
        
        // Setting the size of the output material for the mapping image. This will be the output size of the 
        // textures when we do material casting in a later stage. 
        sgOutputMaterialSettings.SetTextureWidth( xDim );
        sgOutputMaterialSettings.SetTextureHeight( yDim );
        sgOutputMaterialSettings.SetMultisamplingLevel( 2 );
        
        // Start the impostor process.         
        Console.WriteLine("Start the impostor process.");
        sgImpostorProcessor.RunProcessing();
        
        // Setup and run the diffuse material casting.         
        Console.WriteLine("Setup and run the diffuse material casting.");
        string diffuseTextureFilePath;
        using Simplygon.spColorCaster sgDiffuseCaster = sg.CreateColorCaster();
        sgDiffuseCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgDiffuseCaster.SetOutputFilePath( "DiffuseTexture" );

        using Simplygon.spColorCasterSettings sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings();
        sgDiffuseCasterSettings.SetMaterialChannel( "Diffuse" );
        sgDiffuseCasterSettings.SetOpacityChannel( "Opacity" );
        sgDiffuseCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgDiffuseCasterSettings.SetBakeOpacityInAlpha( false );
        sgDiffuseCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8G8B8 );
        sgDiffuseCasterSettings.SetDilation( 10 );
        sgDiffuseCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgDiffuseCaster.RunProcessing();
        diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath();
        
        // Setup and run the specular material casting.         
        Console.WriteLine("Setup and run the specular material casting.");
        string specularTextureFilePath;
        using Simplygon.spColorCaster sgSpecularCaster = sg.CreateColorCaster();
        sgSpecularCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgSpecularCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgSpecularCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgSpecularCaster.SetOutputFilePath( "SpecularTexture" );

        using Simplygon.spColorCasterSettings sgSpecularCasterSettings = sgSpecularCaster.GetColorCasterSettings();
        sgSpecularCasterSettings.SetMaterialChannel( "Specular" );
        sgSpecularCasterSettings.SetOpacityChannel( "Opacity" );
        sgSpecularCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgSpecularCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgSpecularCasterSettings.SetDilation( 10 );
        sgSpecularCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgSpecularCaster.RunProcessing();
        specularTextureFilePath = sgSpecularCaster.GetOutputFilePath();
        
        // Setup and run the normals material casting.         
        Console.WriteLine("Setup and run the normals material casting.");
        string normalsTextureFilePath;
        using Simplygon.spNormalCaster sgNormalsCaster = sg.CreateNormalCaster();
        sgNormalsCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgNormalsCaster.SetOutputFilePath( "NormalsTexture" );

        using Simplygon.spNormalCasterSettings sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings();
        sgNormalsCasterSettings.SetMaterialChannel( "Normals" );
        sgNormalsCasterSettings.SetOpacityChannel( "Opacity" );
        sgNormalsCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( true );
        sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgNormalsCasterSettings.SetDilation( 10 );
        sgNormalsCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.Interpolate );

        sgNormalsCaster.RunProcessing();
        normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath();
        
        // Setup and run the opacity material casting. Make sure there is no dilation or fill.         
        Console.WriteLine("Setup and run the opacity material casting. Make sure there is no dilation or fill.");
        string opacityTextureFilePath;
        using Simplygon.spOpacityCaster sgOpacityCaster = sg.CreateOpacityCaster();
        sgOpacityCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() );
        sgOpacityCaster.SetSourceMaterials( sgScene.GetMaterialTable() );
        sgOpacityCaster.SetSourceTextures( sgScene.GetTextureTable() );
        sgOpacityCaster.SetOutputFilePath( "OpacityTexture" );

        using Simplygon.spOpacityCasterSettings sgOpacityCasterSettings = sgOpacityCaster.GetOpacityCasterSettings();
        sgOpacityCasterSettings.SetMaterialChannel( "Opacity" );
        sgOpacityCasterSettings.SetOpacityChannel( "Opacity" );
        sgOpacityCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent.Alpha );
        sgOpacityCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat.PNG );
        sgOpacityCasterSettings.SetDilation( 0 );
        sgOpacityCasterSettings.SetFillMode( Simplygon.EAtlasFillMode.NoFill );
        sgOpacityCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat.R8 );

        sgOpacityCaster.RunProcessing();
        opacityTextureFilePath = sgOpacityCaster.GetOutputFilePath();
        
        // Update scene with new casted textures. 
        using Simplygon.spMaterialTable sgMaterialTable = sg.CreateMaterialTable();
        using Simplygon.spTextureTable sgTextureTable = sg.CreateTextureTable();
        using Simplygon.spMaterial sgMaterial = sg.CreateMaterial();
        sgMaterial.SetName("OutputMaterial");
        using Simplygon.spTexture sgDiffuseTexture = sg.CreateTexture();
        sgDiffuseTexture.SetName( "Diffuse" );
        sgDiffuseTexture.SetFilePath( diffuseTextureFilePath );
        sgTextureTable.AddTexture( sgDiffuseTexture );

        using Simplygon.spShadingTextureNode sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode();
        sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 );
        sgDiffuseTextureShadingNode.SetTextureName( "Diffuse" );

        sgMaterial.AddMaterialChannel( "Diffuse" );
        sgMaterial.SetShadingNetwork( "Diffuse", sgDiffuseTextureShadingNode );
        using Simplygon.spTexture sgSpecularTexture = sg.CreateTexture();
        sgSpecularTexture.SetName( "Specular" );
        sgSpecularTexture.SetFilePath( specularTextureFilePath );
        sgTextureTable.AddTexture( sgSpecularTexture );

        using Simplygon.spShadingTextureNode sgSpecularTextureShadingNode = sg.CreateShadingTextureNode();
        sgSpecularTextureShadingNode.SetTexCoordLevel( 0 );
        sgSpecularTextureShadingNode.SetTextureName( "Specular" );

        sgMaterial.AddMaterialChannel( "Specular" );
        sgMaterial.SetShadingNetwork( "Specular", sgSpecularTextureShadingNode );
        using Simplygon.spTexture sgNormalsTexture = sg.CreateTexture();
        sgNormalsTexture.SetName( "Normals" );
        sgNormalsTexture.SetFilePath( normalsTextureFilePath );
        sgTextureTable.AddTexture( sgNormalsTexture );

        using Simplygon.spShadingTextureNode sgNormalsTextureShadingNode = sg.CreateShadingTextureNode();
        sgNormalsTextureShadingNode.SetTexCoordLevel( 0 );
        sgNormalsTextureShadingNode.SetTextureName( "Normals" );

        sgMaterial.AddMaterialChannel( "Normals" );
        sgMaterial.SetShadingNetwork( "Normals", sgNormalsTextureShadingNode );
        using Simplygon.spTexture sgOpacityTexture = sg.CreateTexture();
        sgOpacityTexture.SetName( "Opacity" );
        sgOpacityTexture.SetFilePath( opacityTextureFilePath );
        sgTextureTable.AddTexture( sgOpacityTexture );

        using Simplygon.spShadingTextureNode sgOpacityTextureShadingNode = sg.CreateShadingTextureNode();
        sgOpacityTextureShadingNode.SetTexCoordLevel( 0 );
        sgOpacityTextureShadingNode.SetTextureName( "Opacity" );

        sgMaterial.AddMaterialChannel( "Opacity" );
        sgMaterial.SetShadingNetwork( "Opacity", sgOpacityTextureShadingNode );
        sgMaterial.SetBlendMode(Simplygon.EMaterialBlendMode.Blend);

        sgMaterialTable.AddMaterial( sgMaterial );

        sgScene.GetTextureTable().Clear();
        sgScene.GetMaterialTable().Clear();
        sgScene.GetTextureTable().Copy(sgTextureTable);
        sgScene.GetMaterialTable().Copy(sgMaterialTable);
        using Simplygon.spScene sgImpostorScene = sg.CreateScene();
        using Simplygon.spGeometryData sgImpostorGeometry = sgImpostorProcessor.GetImpostorGeometryFromSingleView();
        sgImpostorScene.GetRootNode().CreateChildMesh(sgImpostorGeometry);
        sgImpostorScene.GetMaterialTable().Copy(sgScene.GetMaterialTable());
        sgImpostorScene.GetTextureTable().Copy(sgScene.GetTextureTable());
        
        // Save processed scene.         
        Console.WriteLine("Save processed scene.");
        SaveScene(sg, sgImpostorScene, "Output.glb");
        
        // Check log for any warnings or errors.         
        Console.WriteLine("Check log for any warnings or errors.");
        CheckLog(sg);
    }

    static int Main(string[] args)
    {
        using var sg = Simplygon.Loader.InitSimplygon(out var errorCode, out var errorMessage);
        if (errorCode != Simplygon.EErrorCodes.NoError)
        {
            Console.WriteLine( $"Failed to initialize Simplygon: ErrorCode({(int)errorCode}) {errorMessage}" );
            return (int)errorCode;
        }
        RunImpostorFromSingleView(sg);

        return 0;
    }

}
python
# Copyright (c) Microsoft Corporation. 
# Licensed under the MIT License. 

import math
import os
import sys
import glob
import gc
import threading

from pathlib import Path
from simplygon10 import simplygon_loader
from simplygon10 import Simplygon


def LoadScene(sg: Simplygon.ISimplygon, path: str):
    # Create scene importer 
    sgSceneImporter = sg.CreateSceneImporter()
    sgSceneImporter.SetImportFilePath(path)
    
    # Run scene importer. 
    importResult = sgSceneImporter.Run()
    if Simplygon.Failed(importResult):
        raise Exception('Failed to load scene.')
    sgScene = sgSceneImporter.GetScene()
    return sgScene

def SaveScene(sg: Simplygon.ISimplygon, sgScene: Simplygon.spScene, path: str):
    # Create scene exporter. 
    sgSceneExporter = sg.CreateSceneExporter()
    outputScenePath = ''.join(['output\\', 'ImpostorFromSingleView', '_', path])
    sgSceneExporter.SetExportFilePath(outputScenePath)
    sgSceneExporter.SetScene(sgScene)
    
    # Run scene exporter. 
    exportResult = sgSceneExporter.Run()
    if Simplygon.Failed(exportResult):
        raise Exception('Failed to save scene.')

def CheckLog(sg: Simplygon.ISimplygon):
    # Check if any errors occurred. 
    hasErrors = sg.ErrorOccurred()
    if hasErrors:
        errors = sg.CreateStringArray()
        sg.GetErrorMessages(errors)
        errorCount = errors.GetItemCount()
        if errorCount > 0:
            print('CheckLog: Errors:')
            for errorIndex in range(errorCount):
                errorString = errors.GetItem(errorIndex)
                print(errorString)
            sg.ClearErrorMessages()
    else:
        print('CheckLog: No errors.')
    
    # Check if any warnings occurred. 
    hasWarnings = sg.WarningOccurred()
    if hasWarnings:
        warnings = sg.CreateStringArray()
        sg.GetWarningMessages(warnings)
        warningCount = warnings.GetItemCount()
        if warningCount > 0:
            print('CheckLog: Warnings:')
            for warningIndex in range(warningCount):
                warningString = warnings.GetItem(warningIndex)
                print(warningString)
            sg.ClearWarningMessages()
    else:
        print('CheckLog: No warnings.')
    
    # Error out if Simplygon has errors. 
    if hasErrors:
        raise Exception('Processing failed with an error')

def RunImpostorFromSingleView(sg: Simplygon.ISimplygon):
    # Load scene to process.     
    print("Load scene to process.")
    sgScene = LoadScene(sg, '../../../Assets/Bush/Bush.fbx')
    
    # For all materials in the scene set the blend mode to blend (instead of opaque) 
    materialCount = sgScene.GetMaterialTable().GetMaterialsCount()
    for i in range(0, materialCount):
        sgScene.GetMaterialTable().GetMaterial(i).SetBlendMode(Simplygon.EMaterialBlendMode_Blend)
    
    # For all materials in the scene set the opacity mode to Opacity. 
    materialCount = sgScene.GetMaterialTable().GetMaterialsCount()
    for i in range(0, materialCount):
        sgScene.GetMaterialTable().GetMaterial(i).SetOpacityType(Simplygon.EOpacityType_Opacity)
    
    # Create the Impostor processor. 
    sgImpostorProcessor = sg.CreateImpostorProcessor()
    sgImpostorProcessor.SetScene( sgScene )
    sgImpostorSettings = sgImpostorProcessor.GetImpostorSettings()
    
    # Set impostor type to From single view. 
    sgImpostorSettings.SetImpostorType( Simplygon.EImpostorType_FromSingleView )
    viewDir = [0.0, 0.0, -1.0]

    sgImpostorFromSingleViewSettings = sgImpostorSettings.GetImpostorFromSingleViewSettings()
    sgImpostorFromSingleViewSettings.SetUseTightFitting( True )
    sgImpostorFromSingleViewSettings.SetTightFittingDepthOffset( 1.0 )
    sgImpostorFromSingleViewSettings.SetTexCoordPadding( 0.01 )
    sgImpostorFromSingleViewSettings.SetViewDirection( viewDir )
    # Once geometry and settings are set, you can calculate the aspect ratio for your textures.
    aspect = sgImpostorProcessor.GetSingleViewAspectRatio()
    if aspect < 0.0:
        raise Exception('Failed to compute aspect ratio!.')
    xDim = int(aspect * 512)
    yDim = int(1.0 * 512)
    sgMappingImageSettings = sgImpostorProcessor.GetMappingImageSettings()
    sgMappingImageSettings.SetMaximumLayers( 10 )
    sgOutputMaterialSettings = sgMappingImageSettings.GetOutputMaterialSettings(0)
    
    # Setting the size of the output material for the mapping image. This will be the output size of the 
    # textures when we do material casting in a later stage. 
    sgOutputMaterialSettings.SetTextureWidth( xDim )
    sgOutputMaterialSettings.SetTextureHeight( yDim )
    sgOutputMaterialSettings.SetMultisamplingLevel( 2 )
    
    # Start the impostor process.     
    print("Start the impostor process.")
    sgImpostorProcessor.RunProcessing()
    
    # Setup and run the diffuse material casting.     
    print("Setup and run the diffuse material casting.")
    sgDiffuseCaster = sg.CreateColorCaster()
    sgDiffuseCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgDiffuseCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgDiffuseCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgDiffuseCaster.SetOutputFilePath( 'DiffuseTexture' )

    sgDiffuseCasterSettings = sgDiffuseCaster.GetColorCasterSettings()
    sgDiffuseCasterSettings.SetMaterialChannel( 'Diffuse' )
    sgDiffuseCasterSettings.SetOpacityChannel( 'Opacity' )
    sgDiffuseCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgDiffuseCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgDiffuseCasterSettings.SetBakeOpacityInAlpha( False )
    sgDiffuseCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8G8B8 )
    sgDiffuseCasterSettings.SetDilation( 10 )
    sgDiffuseCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgDiffuseCaster.RunProcessing()
    diffuseTextureFilePath = sgDiffuseCaster.GetOutputFilePath()
    
    # Setup and run the specular material casting.     
    print("Setup and run the specular material casting.")
    sgSpecularCaster = sg.CreateColorCaster()
    sgSpecularCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgSpecularCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgSpecularCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgSpecularCaster.SetOutputFilePath( 'SpecularTexture' )

    sgSpecularCasterSettings = sgSpecularCaster.GetColorCasterSettings()
    sgSpecularCasterSettings.SetMaterialChannel( 'Specular' )
    sgSpecularCasterSettings.SetOpacityChannel( 'Opacity' )
    sgSpecularCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgSpecularCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgSpecularCasterSettings.SetDilation( 10 )
    sgSpecularCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgSpecularCaster.RunProcessing()
    specularTextureFilePath = sgSpecularCaster.GetOutputFilePath()
    
    # Setup and run the normals material casting.     
    print("Setup and run the normals material casting.")
    sgNormalsCaster = sg.CreateNormalCaster()
    sgNormalsCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgNormalsCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgNormalsCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgNormalsCaster.SetOutputFilePath( 'NormalsTexture' )

    sgNormalsCasterSettings = sgNormalsCaster.GetNormalCasterSettings()
    sgNormalsCasterSettings.SetMaterialChannel( 'Normals' )
    sgNormalsCasterSettings.SetOpacityChannel( 'Opacity' )
    sgNormalsCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgNormalsCasterSettings.SetGenerateTangentSpaceNormals( True )
    sgNormalsCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgNormalsCasterSettings.SetDilation( 10 )
    sgNormalsCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_Interpolate )

    sgNormalsCaster.RunProcessing()
    normalsTextureFilePath = sgNormalsCaster.GetOutputFilePath()
    
    # Setup and run the opacity material casting. Make sure there is no dilation or fill.     
    print("Setup and run the opacity material casting. Make sure there is no dilation or fill.")
    sgOpacityCaster = sg.CreateOpacityCaster()
    sgOpacityCaster.SetMappingImage( sgImpostorProcessor.GetMappingImage() )
    sgOpacityCaster.SetSourceMaterials( sgScene.GetMaterialTable() )
    sgOpacityCaster.SetSourceTextures( sgScene.GetTextureTable() )
    sgOpacityCaster.SetOutputFilePath( 'OpacityTexture' )

    sgOpacityCasterSettings = sgOpacityCaster.GetOpacityCasterSettings()
    sgOpacityCasterSettings.SetMaterialChannel( 'Opacity' )
    sgOpacityCasterSettings.SetOpacityChannel( 'Opacity' )
    sgOpacityCasterSettings.SetOpacityChannelComponent( Simplygon.EColorComponent_Alpha )
    sgOpacityCasterSettings.SetOutputImageFileFormat( Simplygon.EImageOutputFormat_PNG )
    sgOpacityCasterSettings.SetDilation( 0 )
    sgOpacityCasterSettings.SetFillMode( Simplygon.EAtlasFillMode_NoFill )
    sgOpacityCasterSettings.SetOutputPixelFormat( Simplygon.EPixelFormat_R8 )

    sgOpacityCaster.RunProcessing()
    opacityTextureFilePath = sgOpacityCaster.GetOutputFilePath()
    
    # Update scene with new casted textures. 
    sgMaterialTable = sg.CreateMaterialTable()
    sgTextureTable = sg.CreateTextureTable()
    sgMaterial = sg.CreateMaterial()
    sgMaterial.SetName("OutputMaterial")
    sgDiffuseTexture = sg.CreateTexture()
    sgDiffuseTexture.SetName( 'Diffuse' )
    sgDiffuseTexture.SetFilePath( diffuseTextureFilePath )
    sgTextureTable.AddTexture( sgDiffuseTexture )

    sgDiffuseTextureShadingNode = sg.CreateShadingTextureNode()
    sgDiffuseTextureShadingNode.SetTexCoordLevel( 0 )
    sgDiffuseTextureShadingNode.SetTextureName( 'Diffuse' )

    sgMaterial.AddMaterialChannel( 'Diffuse' )
    sgMaterial.SetShadingNetwork( 'Diffuse', sgDiffuseTextureShadingNode )
    sgSpecularTexture = sg.CreateTexture()
    sgSpecularTexture.SetName( 'Specular' )
    sgSpecularTexture.SetFilePath( specularTextureFilePath )
    sgTextureTable.AddTexture( sgSpecularTexture )

    sgSpecularTextureShadingNode = sg.CreateShadingTextureNode()
    sgSpecularTextureShadingNode.SetTexCoordLevel( 0 )
    sgSpecularTextureShadingNode.SetTextureName( 'Specular' )

    sgMaterial.AddMaterialChannel( 'Specular' )
    sgMaterial.SetShadingNetwork( 'Specular', sgSpecularTextureShadingNode )
    sgNormalsTexture = sg.CreateTexture()
    sgNormalsTexture.SetName( 'Normals' )
    sgNormalsTexture.SetFilePath( normalsTextureFilePath )
    sgTextureTable.AddTexture( sgNormalsTexture )

    sgNormalsTextureShadingNode = sg.CreateShadingTextureNode()
    sgNormalsTextureShadingNode.SetTexCoordLevel( 0 )
    sgNormalsTextureShadingNode.SetTextureName( 'Normals' )

    sgMaterial.AddMaterialChannel( 'Normals' )
    sgMaterial.SetShadingNetwork( 'Normals', sgNormalsTextureShadingNode )
    sgOpacityTexture = sg.CreateTexture()
    sgOpacityTexture.SetName( 'Opacity' )
    sgOpacityTexture.SetFilePath( opacityTextureFilePath )
    sgTextureTable.AddTexture( sgOpacityTexture )

    sgOpacityTextureShadingNode = sg.CreateShadingTextureNode()
    sgOpacityTextureShadingNode.SetTexCoordLevel( 0 )
    sgOpacityTextureShadingNode.SetTextureName( 'Opacity' )

    sgMaterial.AddMaterialChannel( 'Opacity' )
    sgMaterial.SetShadingNetwork( 'Opacity', sgOpacityTextureShadingNode )
    sgMaterial.SetBlendMode(Simplygon.EMaterialBlendMode_Blend);

    sgMaterialTable.AddMaterial( sgMaterial )

    sgScene.GetTextureTable().Clear()
    sgScene.GetMaterialTable().Clear()
    sgScene.GetTextureTable().Copy(sgTextureTable)
    sgScene.GetMaterialTable().Copy(sgMaterialTable)
    sgImpostorScene = sg.CreateScene()
    sgImpostorGeometry = sgImpostorProcessor.GetImpostorGeometryFromSingleView()
    sgImpostorScene.GetRootNode().CreateChildMesh(sgImpostorGeometry)
    sgImpostorScene.GetMaterialTable().Copy(sgScene.GetMaterialTable())
    sgImpostorScene.GetTextureTable().Copy(sgScene.GetTextureTable())
    
    # Save processed scene.     
    print("Save processed scene.")
    SaveScene(sg, sgImpostorScene, 'Output.glb')
    
    # Check log for any warnings or errors.     
    print("Check log for any warnings or errors.")
    CheckLog(sg)

if __name__ == '__main__':
        sg = simplygon_loader.init_simplygon()
        if sg is None:
            exit(Simplygon.GetLastInitializationError())

        RunImpostorFromSingleView(sg)

        sg = None
        gc.collect()