#include "../Common/Example.h"
void RunExample( const std::string& readFrom );
std::string assetPath = GetAssetPath() + "MaterialNodeExampleAssets/";
int main( int argc, char* argv[] )
{
try
{
InitExample();
sg->SetGlobalSetting("DefaultTBNType", SG_TANGENTSPACEMETHOD_ORTHONORMAL);
RunExample(assetPath + "island.obj");
DeinitExample();
}
catch (const std::exception& ex)
{
std::cerr << ex.what() << std::endl;
return -1;
}
return 0;
}
void SetupTexcoordLevels( spGeometryData newGeom )
{
spRealArray tex_coords_0 = newGeom->GetTexCoords( 0 );
tex_coords_0->SetAlternativeName( "UVzero" );
if( !newGeom->GetTexCoords( 1 ) )
{
newGeom->AddTexCoords( 1 );
spRealArray tex_coords_1 = newGeom->GetTexCoords( 1 );
for( uint i = 0; i < tex_coords_0->GetItemCount(); ++i )
{
tex_coords_1->SetItem( i, tex_coords_0->GetItem( i ) * 4.0f );
}
tex_coords_1->SetAlternativeName( "UVone" );
}
}
void ComputeVertexColors( spGeometryData newGeom )
{
float threshold_water = 0.01f;
float threshold_grass = 0.3f;
float threshold_dirt = 0.5f;
spRealArray coords = newGeom->GetCoords();
spRidArray vertex_ids = newGeom->GetVertexIds();
real max_height = -REAL_MAX;
real min_height = REAL_MAX;
for( uint i = 0; i < coords->GetTupleCount(); ++i )
{
real current_height = coords->GetItem( i * 3 + 1 );
if( current_height > max_height )
max_height = current_height;
if( current_height < min_height )
min_height = current_height;
}
if( !newGeom->GetColors( 0 ) )
{
newGeom->AddColors( 0 );
}
spRealArray relative_height_vertex_color = newGeom->GetColors( 0 );
relative_height_vertex_color->SetAlternativeName( "colorA" );
if( !newGeom->GetColors( 1 ) )
{
newGeom->AddColors( 1 );
}
spRealArray weight_water_vertex_color = newGeom->GetColors( 1 );
weight_water_vertex_color->SetAlternativeName( "colorB" );
if( !newGeom->GetColors( 2 ) )
{
newGeom->AddColors( 2 );
}
spRealArray weight_grass_vertex_color = newGeom->GetColors( 2 );
weight_grass_vertex_color->SetAlternativeName( "colorC" );
if( !newGeom->GetColors( 3 ) )
{
newGeom->AddColors( 3 );
}
spRealArray weight_dirt_vertex_color = newGeom->GetColors( 3 );
weight_dirt_vertex_color->SetAlternativeName( "colorD" );
for( uint corner_id = 0; corner_id < newGeom->GetTriangleCount() * 3; ++corner_id )
{
rid v_id = vertex_ids->GetItem( corner_id );
real absolute_height = coords->GetItem( v_id * 3 + 1 );
real relative_height = (absolute_height - min_height) / (max_height - min_height);
real interpolate_water_grass = clamp( relative_height / threshold_water, 0.0f, 1.0f );
real interpolate_grass_dirt = clamp( (relative_height - threshold_water) / (threshold_grass - threshold_water), 0.0f, 1.0f );
real interpolate_dirt_rock = clamp( (relative_height - threshold_grass) / (threshold_dirt - threshold_grass), 0.0f, 1.0f );
real relative_height_color[4] = { relative_height, relative_height, relative_height, 1.0 };
real blend_water_color[4] = { interpolate_water_grass, interpolate_water_grass, interpolate_water_grass, 1.0 };
real blend_grass_color[4] = { interpolate_grass_dirt, interpolate_grass_dirt, interpolate_grass_dirt, 1.0 };
real blend_dirt_color[4] = { interpolate_dirt_rock, interpolate_dirt_rock, interpolate_dirt_rock, 1.0 };
relative_height_vertex_color->SetTuple( corner_id, relative_height_color );
weight_water_vertex_color->SetTuple( corner_id, blend_water_color );
weight_grass_vertex_color->SetTuple( corner_id, blend_grass_color );
weight_dirt_vertex_color->SetTuple( corner_id, blend_dirt_color );
}
}
spShadingNode CreateMountainNode()
{
spShadingTextureNode node_texture_icemask = sg->CreateShadingTextureNode();
spShadingTextureNode node_texture_ice = sg->CreateShadingTextureNode();
spShadingTextureNode node_texture_rock = sg->CreateShadingTextureNode();
const char *level_0 = "UVzero";
const char *level_1 = "UVone";
node_texture_icemask->SetTextureLevelName( level_0 );
node_texture_ice->SetTextureLevelName( level_1 );
node_texture_rock->SetTextureLevelName( level_1 );
node_texture_icemask->SetTextureName( (assetPath + "icemask.png").c_str() );
node_texture_ice->SetTextureName( (assetPath + "ice.png").c_str() );
node_texture_rock->SetTextureName( (assetPath + "rock.jpg").c_str() );
spShadingVertexColorNode node_weights_relative_height = sg->CreateShadingVertexColorNode();
node_weights_relative_height->SetVertexColorSet( "colorA" );
spShadingInterpolateNode node_masked_ice = sg->CreateShadingInterpolateNode();
node_masked_ice->SetInput( 0, node_texture_rock );
node_masked_ice->SetInput( 1, node_texture_ice );
node_masked_ice->SetInput( 2, node_texture_icemask );
spShadingSubtractNode node_icyness = sg->CreateShadingSubtractNode();
node_icyness->SetInput( 0, node_weights_relative_height );
node_icyness->SetDefaultParameter( 1, 0.1f, 0.1f, 0.1f, 0.0f );
spShadingClampNode node_icyness_clamp = sg->CreateShadingClampNode();
node_icyness_clamp->SetInput( 0, node_icyness );
node_icyness_clamp->SetDefaultParameter( 1, 0.0f, 0.0f, 0.0f, 1.0f );
node_icyness_clamp->SetDefaultParameter( 2, 1.0f, 1.0f, 1.0f, 1.0f );
spShadingInterpolateNode node_interpolate_mountain = sg->CreateShadingInterpolateNode();
node_interpolate_mountain->SetInput( 0, node_texture_rock );
node_interpolate_mountain->SetInput( 1, node_masked_ice );
node_interpolate_mountain->SetInput( 2, node_icyness_clamp );
return spShadingNode( node_interpolate_mountain );
}
spShadingNode CreateWaterNode()
{
spShadingTextureNode node_texture_water = sg->CreateShadingTextureNode();
spShadingTextureNode node_texture_noise = sg->CreateShadingTextureNode();
const char *level_0 = "UVzero";
const char *level_1 = "UVone";
node_texture_water->SetTextureLevelName( level_1 );
node_texture_noise->SetTextureLevelName( level_1 );
node_texture_water->SetTextureName( (assetPath + "water.png").c_str() );
node_texture_noise->SetTextureName( (assetPath + "noise.png").c_str() );
spShadingColorNode node_color_water = sg->CreateShadingColorNode();
node_color_water->SetColor( 0.075f, 0.368f, 0.347f, 1.0f );
spShadingInterpolateNode node_interpolate_water_color = sg->CreateShadingInterpolateNode();
node_interpolate_water_color->SetInput( 0, node_texture_water );
node_interpolate_water_color->SetInput( 1, node_color_water );
node_interpolate_water_color->SetInput( 2, node_texture_noise );
return spShadingNode( node_interpolate_water_color );
}
spShadingNode CreateIslandMaterialNodeNetwork()
{
spShadingNode node_mountain = CreateMountainNode();
spShadingNode node_water = CreateWaterNode();
spShadingTextureNode node_texture_grass = sg->CreateShadingTextureNode();
spShadingTextureNode node_texture_dirt = sg->CreateShadingTextureNode();
const char *level_0 = "UVzero";
const char *level_1 = "UVone";
node_texture_dirt->SetTextureLevelName( level_1 );
node_texture_grass->SetTextureLevelName( level_1 );
node_texture_dirt->SetTextureName( (assetPath + "stonedirt.jpg").c_str() );
node_texture_grass->SetTextureName( (assetPath + "greengrass.jpg").c_str() );
spShadingInterpolateNode node_interpolate_water_land = sg->CreateShadingInterpolateNode();
spShadingInterpolateNode node_interpolate_land_0 = sg->CreateShadingInterpolateNode();
spShadingInterpolateNode node_interpolate_land_1 = sg->CreateShadingInterpolateNode();
spShadingVertexColorNode node_weights_water_land = sg->CreateShadingVertexColorNode();
node_weights_water_land->SetVertexColorSet( "colorB" );
spShadingVertexColorNode node_weights_interpolate_land_0 = sg->CreateShadingVertexColorNode();
node_weights_interpolate_land_0->SetVertexColorSet( "colorC" );
spShadingVertexColorNode node_weights_interpolate_land_1 = sg->CreateShadingVertexColorNode();
node_weights_interpolate_land_1->SetVertexColorSet( "colorD" );
node_interpolate_land_1->SetInput( 0, node_texture_dirt );
node_interpolate_land_1->SetInput( 1, node_mountain );
node_interpolate_land_1->SetInput( 2, node_weights_interpolate_land_1 );
node_interpolate_land_0->SetInput( 0, node_texture_grass );
node_interpolate_land_0->SetInput( 1, node_interpolate_land_1 );
node_interpolate_land_0->SetInput( 2, node_weights_interpolate_land_0 );
node_interpolate_water_land->SetInput( 0, node_water );
node_interpolate_water_land->SetInput( 1, node_interpolate_land_0 );
node_interpolate_water_land->SetInput( 2, node_weights_water_land );
return spShadingNode( node_interpolate_water_land );
}
void RunExample( const std::string& readFrom )
{
const std::string writeTo = "output";
std::string output_geometry_filename = GetExecutablePath() + writeTo + ".obj";
std::string output_diffuse_filename = GetExecutablePath() + writeTo + "_diffuse.png";
spWavefrontImporter objReader = sg->CreateWavefrontImporter();
objReader->SetImportFilePath( readFrom.c_str() );
if( !objReader->RunImport() )
throw std::exception("Failed to load input file!");
spScene scene = objReader->GetScene();
int selectionSetAllSceneMeshesID = scene->SelectNodes( "ISceneMesh" );
spSelectionSet selectionSetAllSceneMeshes = scene->GetSelectionSetTable()->GetSelectionSet( selectionSetAllSceneMeshesID );
for( uint i = 0; i < selectionSetAllSceneMeshes->GetItemCount(); ++i )
{
spSceneMesh sceneMesh = Cast<ISceneMesh>( scene->GetNodeByGUID( selectionSetAllSceneMeshes->GetItem( i ) ) );
spGeometryData geom = sceneMesh->GetGeometry();
ComputeVertexColors( geom );
SetupTexcoordLevels( geom );
}
spMaterialTable material_table = scene->GetMaterialTable();
material_table->Clear();
spMaterial island_material = sg->CreateMaterial();
material_table->AddMaterial( island_material );
spTextureTable texture_table = scene->GetTextureTable();
std::string Texs[7];
Texs[0] = assetPath + "stonedirt.jpg";
Texs[1] = assetPath + "greengrass.jpg";
Texs[2] = assetPath + "water.png";
Texs[3] = assetPath + "noise.png";
Texs[4] = assetPath + "icemask.png";
Texs[5] = assetPath + "ice.png";
Texs[6] = assetPath + "rock.jpg";
for( uint i = 0; i < 7; ++i )
{
spTexture texture = sg->CreateTexture();
texture->SetName( Texs[i].c_str() );
texture->SetFilePath( Texs[i].c_str() );
texture_table->AddTexture( texture );
}
spShadingNode exit_node = CreateIslandMaterialNodeNetwork();
island_material->SetShadingNetwork( SG_MATERIAL_CHANNEL_DIFFUSE, exit_node );
spShaderGenerator island_shader = sg->CreateShaderGenerator();
island_shader->SetMaterial( island_material );
island_shader->GenerateShaderData();
std::cout << "Shader Input Texture Paths:" << std::endl;
for (uint index = 0; index < island_shader->GetShaderInputTexturePathsCount(); index++)
{
rstring str = island_shader->GetShaderInputTexturePath(index);
std::cout << "\t" << str.GetText() << std::endl;
}
std::cout << "Shader Input UV Sets:" << std::endl;
for (uint index = 0; index < island_shader->GetShaderInputUVSetsCount(); index++)
{
rstring str = island_shader->GetShaderInputUVSet(index);
std::cout << "\t" << str.GetText() << std::endl;
}
std::cout << "Shader Input Vertex Color Sets:" << std::endl;
for (uint index = 0; index < island_shader->GetShaderInputVertexColorsCount(); index++)
{
rstring str = island_shader->GetShaderInputVertexColor(index);
std::cout << "\t" << str.GetText() << std::endl;
}
rstring hlsl_code = island_shader->GetHLSLCode();
rstring glsl_vertex_code = island_shader->GetGLSLVertexCode();
rstring glsl_fragment_code = island_shader->GetGLSLFragmentCode();
FILE * file_hlsl = fopen( "shader_hlsl.txt", "wt" );
fprintf( file_hlsl, "%s", hlsl_code.GetText() );
fclose( file_hlsl );
FILE * file_glsl_vertex = fopen( "shader_glsl_vertex.txt", "wt" );
fprintf( file_glsl_vertex, "%s", glsl_vertex_code.GetText() );
fclose( file_glsl_vertex );
FILE * file_glsl_fragment = fopen( "shader_glsl_fragment.txt", "wt" );
fprintf( file_glsl_fragment, "%s", glsl_fragment_code.GetText() );
fclose( file_glsl_fragment );
#ifdef _WIN32
#ifndef _HEADLESS
spDirectXRenderer renderer = sg->CreateDirectXRenderer();
renderer->CreatePreviewer( 2048, 2048 );
renderer->LoadGeometryDataWithMaterialShadingNetwork( scene );
spSceneCamera sceneCamera = sg->CreateSceneCamera();
sceneCamera->SetCustomSphereCameraPath(
1,
0.0f,
0.0f,
100.0f
);
scene->GetRootNode()->AddChild( sceneCamera );
spSelectionSet cameraSelectionSet = sg->CreateSelectionSet();
cameraSelectionSet->AddItem( sceneCamera->GetNodeGUID() );
rid cameraSelectionSetID = scene->GetSelectionSetTable()->AddSelectionSet( cameraSelectionSet );
renderer->RenderAlongCameraPathAndStorePics( cameraSelectionSetID, "screenshot", "png" );
#endif
#endif
spReductionProcessor red = sg->CreateReductionProcessor();
red->SetScene( scene );
spRepairSettings repair_settings = red->GetRepairSettings();
repair_settings->SetWeldDist( 0.2f );
repair_settings->SetTjuncDist( 0.2f );
spReductionSettings reduction_settings = red->GetReductionSettings();
reduction_settings->SetTriangleRatio( 0.9f );
spMappingImageSettings mapping_settings = red->GetMappingImageSettings();
mapping_settings->SetGenerateMappingImage( true );
mapping_settings->SetGenerateTexCoords( true );
mapping_settings->SetParameterizerMaxStretch( 0.5f );
mapping_settings->SetGutterSpace( 4 );
mapping_settings->SetUseAutomaticTextureSize( false );
mapping_settings->SetWidth( 2048 );
mapping_settings->SetHeight( 2048 );
mapping_settings->SetMultisamplingLevel( 2 );
red->RunProcessing();
spMappingImage mapping_image = red->GetMappingImage();
spMaterialTable output_materials = sg->CreateMaterialTable();
spTextureTable output_textures = sg->CreateTextureTable();
spMaterial output_material = sg->CreateMaterial();
output_material->SetName( "output_material" );
output_materials->AddMaterial( output_material );
spColorCaster cast = sg->CreateColorCaster();
cast->SetColorType( SG_MATERIAL_CHANNEL_DIFFUSE );
cast->SetSourceMaterials( scene->GetMaterialTable() );
cast->SetSourceTextures( scene->GetTextureTable() );
cast->SetMappingImage( mapping_image );
cast->SetOutputChannels( 3 );
cast->SetOutputChannelBitDepth( 8 );
cast->SetDilation( 10 );
cast->SetOutputFilePath( output_diffuse_filename.c_str() );
cast->RunProcessing();
AddSimplygonTexture( output_material, output_textures, SG_MATERIAL_CHANNEL_DIFFUSE, output_diffuse_filename.c_str() );
spWavefrontExporter objexp = sg->CreateWavefrontExporter();
material_table->Clear();
material_table->Copy( output_materials );
texture_table->Clear();
texture_table->Copy( output_textures );
objexp->SetExportFilePath( output_geometry_filename.c_str() );
objexp->SetScene( scene );
objexp->RunExport();
}