// Initializes CCopyEntity::m_pMeshRenderMethod
// - Initialize the mesh render method
// - Initialize shader parameter loaders
// - Create alpha entities
// - Creates a shader
void BaseEntity::InitEntityGraphics( CCopyEntity &entity,
                                      ShaderHandle& shader,
                                      ShaderTechniqueHandle& tech )
{
	if( shader.IsLoaded()
	 && tech.GetTechniqueName()
	 && 0 < strlen(tech.GetTechniqueName()) )
	{
		CreateMeshRenderMethod( EntityHandle<>( entity.Self() ), shader, tech );
	}
	else
	{
		InitMeshRenderMethod( entity );
	}

	// create transparent parts of the model as separate entities
	if( m_EntityFlag & BETYPE_SUPPORT_TRANSPARENT_PARTS )
	{
		// Remove any previous alpha entities
		int next_child_index = 0;
		while( next_child_index < entity.GetNumChildren() )
//		for( int i=0; i<entity.GetNumChildren(); i++ )
		{
			shared_ptr<CCopyEntity> pChild = entity.m_aChild[next_child_index].Get();
			if( IsValidEntity(pChild.get())
			 && pChild->GetEntityTypeID() == CCopyEntityTypeID::ALPHA_ENTITY )
			{
				CCopyEntity *pChildRawPtr = pChild.get();
				m_pStage->TerminateEntity( pChildRawPtr );
			}
			else
				next_child_index += 1;
		}

		CreateAlphaEntities( &entity );
	}

	shared_ptr<BasicMesh> pMesh = entity.m_MeshHandle.GetMesh();
	if( !pMesh )
		return;

	BasicMesh& mesh = *pMesh;
	const int num_mesh_materials = mesh.GetNumMaterials();

	std::vector<GenericShaderDesc> shader_descs;
	shader_descs.resize( num_mesh_materials );

	std::vector<int> mirror_subsets_indices;
//	std::vector<int> non_mirror_subsets_indices;

	if( m_MeshProperty.m_MeshDesc.IsValid() )
//	if( true )
	{
		// The mesh is specified in the base entity
	}
	else
	{
		// base entity has no mesh
		// - entity's mesh is individual
		shader_descs.resize( num_mesh_materials );
		for( int i=0; i<num_mesh_materials; i++ )
		{
			// Fill out the shader desc based on the parameter values of the material

			// reflection
			bool registered_as_mirror = RegisterAsMirrorIfReflective( entity, mesh, i, shader_descs[i] );
			if( registered_as_mirror )
				mirror_subsets_indices.push_back( i );

			// specularity
			if( 0.001f < mesh.GetMaterial(i).m_Mat.fSpecularity )
				shader_descs[i].Specular = SpecularSource::UNIFORM;
			else
				shader_descs[i].Specular = SpecularSource::NONE;
		}

		vector< pair< GenericShaderDesc, vector<unsigned int> > > grouped_descs;
		group_elements( shader_descs, grouped_descs );

		// Do a NULL check just in case
		// The mesh render method is initialized by InitMeshRenderMethod() above.
		if( !entity.m_pMeshRenderMethod )
			entity.m_pMeshRenderMethod.reset( new MeshContainerRenderMethod );

		bool shader_loaded = false;
		if( grouped_descs.size() == 1 )
		{
			SubsetRenderMethod& render_method = entity.m_pMeshRenderMethod->PrimaryMeshRenderMethod();

			render_method.m_Technique.SetTechniqueName( "Default" );
			render_method.m_ShaderDesc.pShaderGenerator.reset( new GenericShaderGenerator( grouped_descs[0].first ) );

//			shader_loaded = render_method.Load();
			shader_loaded = render_method.m_Shader.Load( render_method.m_ShaderDesc );
		}
		else
		{
			LOG_PRINT_WARNING( "Mesh materials need different shaders. This situation is not supported yet (the total number of materials: " + to_string(num_mesh_materials) + ")." );
		}
	}
}