This page has been translated automatically.
Unigine Basics
1. Introduction
2. Managing Virtual Worlds
3. Preparing 3D Models
4. Materials
5. Cameras and Lighting
7. Making Cutscenes and Recording Videos
8. Preparing Your Project for Release
9. Physics
10. Optimization Basics
11. PROJECT2: First-Person Shooter
12. PROJECT3: Third-Person Cross-Country Arcade Racing Game
13. PROJECT4: VR Application With Simple Interaction

Managing Materials

Changing parameters of the material assigned to the object surface via code, and replacing one assigned material with another.

Materials can be operated not only in the Editor — sometimes it is required to assign materials via code (in case of procedural content generation, for example) or configure some of their parameters. To control materials via API, we use the following two classes:

  • Materials class that represents an interface for managing loaded materials (this is a manager class that can help you find a required material, for example).
  • Material class that is used to manage each individual material.

The following example demonstrates how to inherit a new material from the base one, which is called mesh_base.

Source code (C++)
#include <UnigineMaterials.h>
#include <UnigineObjects.h>
#include<UniginePrimitives.h>
using namespace Unigine;

/* .. */

int AppWorldLogic::init() 
{

	// creating a box (ObjectMeshDynamic node)
	ObjectMeshDynamicPtr my_mesh = Primitives::createBox(vec3(1.5f, 1.5f, 1.5f));

	// getting the base mesh_base material to inherit from
	MaterialPtr mesh_base = Materials::findManualMaterial("Unigine::mesh_base");

	// inherit a new child material from it
	MaterialPtr my_mesh_base = mesh_base->inherit();
	
	// save it to  "materials/my_mesh_base0.mat"
	my_mesh_base->createMaterialFile("materials/my_mesh_base0.mat");

	// setting the albedo color of the material to red
	my_mesh_base->setParameterFloat4("albedo_color", Math::vec4(255, 0, 0, 255));

	// assigning a "my_mesh_base0.mat" material to the surface 0 of the my_mesh ObjectMeshDynamic node
	my_mesh->setMaterialPath("materials/my_mesh_base0.mat", 0);
	
	// assigning a "my_mesh_base0.mat" material to all surfaces of the my_mesh ObjectMeshDynamic node
	my_mesh->setMaterialPath("materials/my_mesh_base0.mat", "*");
}

int AppWorldLogic::shutdown() 
{
	// deleting the material "materials/my_mesh_base0.mat"
	Materials::removeMaterial(Materials::findMaterialByPath("materials/my_mesh_base0.mat")->getGUID());

	return 1;
}

Practice#

Now let's create an interactive poster in our interior with an ability to change its albedo texture and apply a light filter to the picture (add a tone).

First, we're gonna need a Static Mesh plane.

  1. Go to the archviz/textures folder and find the plane.mesh asset.
  2. Drag it to the scene (a new Static Mesh object will be created) and change its name to "poster".
  3. Set poster's transformation as shown on the image below:

  4. In the Surface Material section create a child material for the surface (click create a child material) to be able to change its parameters and drag the tex01.jpg asset to the Albedo field in the Textures tab.

Let's create the Customizable component (inherited from Interactable) that switches textures from the list (the array parameter) on the object — Action(0), and changes the albedo color multiplier by overrriding the method — Action(1). The code of the component looks like this:

Customizable.h
#pragma once
#include <UnigineComponentSystem.h>
#include "Interactable.h"
class Customizable :
    public Interactable
{
public:
	// declare constructor and destructor for our class and define the name of the property to be associated with the component.
	// The Customizable.prop file containing all parameters listed below will be generated in your project's data folder after running the app for the first time
	COMPONENT_DEFINE(Customizable, Interactable);

	// declaration and initialization of component parameters
	PROP_ARRAY(File, textures);

	// registering methods to be called at the corresponding stages of the world logic (methods are declared in the protected-section below)
	COMPONENT_INIT(init);

	// Action method override for the child-component
	void action(int num = 0);

protected:
	// declaration of methods to be called at the corresponding stages of the world logic
	void init();

private:
	int current_texture = 0;	// current texture
};
Customizable.cpp
#include "Customizable.h"
// registering the Customizable component
REGISTER_COMPONENT(Customizable);
using namespace Unigine;
using namespace Math;

void Customizable::init()
{
	// setting the tooltip text that will be displayed when hovering over the object
	tooltip = "Right-click on the object switches the listed object materials in a cyclic order. Pressing the 'TAB' button randomly changes the color tone.";
}

// overriding the action for the child component
void Customizable::action(int num)
{
	Unigine::ObjectPtr object = checked_ptr_cast<Unigine::Object>(node);
	// selecting the action
	switch (num)
	{
		// switching between the listed albedo textures of the object material in a cyclic order
	case 0:
		// if the texture list is not set or empty, we do nothing
		if (textures.nullCheck() || textures.size() < 0)
			return;

		current_texture++;
		if (current_texture >= textures.size())
			current_texture = 0;

		object->setMaterialTexture("albedo", Unigine::FileSystem::guidToPath(FileSystem::getGUID(textures[current_texture].getRaw())), 0);
		break;
		// randomly changing the albedo color multiplier for the current material on the object
	case 1:
		object->getMaterial(0)->setParameterFloat4("albedo_color", Math::randColor());
		break;
	}
}

Let's save our files and then build and run our application by hitting Ctrl + F5 to make the Component System generate a property to be used to assign our component to nodes. Close the application after running it and switch to UnigineEditor.

Then let's assign our component to the poster node and fill the texture array (tex01, tex02, tex03).

Now the image on the poster can be changed in one click.

Last update: 2024-12-13
Build: ()