Material Slots
In this case you will get familiar with material slots concept and how to manually assign materials to them.
Agenda:
- Material slots basics
- Manual setup of materials
Material slots basics
The Alembic format used extensively in Sky Engine as described in ASSETS_Alembics case
has one more capability that we can take the advantage of: face sets.
Face sets are slots for materials assigned to the parts of (or the whole) mesh - therefore they are also
called just "material slots".
In SkyRenderer one node can have only one material, so we process meshes with assigned material slots and cut them
into separate nodes, using the material slot name as a suffix.
For better understanding, let’s go over an example: the CG artists prepared a node called tree_GEO. They have
separate textures for leaves and bark, so they assign the leave faces to the "leaves" material slot and
the bark faces - to the "bark" material slot. Each slot has a separate UV layout, but they are both
contained in the tree_GEO node. This is then exported to Alembic file. This node will be visible in SkyRenderer
as 2 separate nodes:
- tree_GEO_leaves,
- tree_GEO_bark.
But that's not the end of the story. The information about the material slot name is still contained in this node
(not only in suffix) and can still be used as a material slot. This can be done manually, or - for many
predefined material slot names - automatically via MaterialSlotFiller (check SYSTEM_MaterialSlotFiller
tutorial).
Scene setup
Let's use custom scene composer to set up the scene.
Scene consists of:
- Room (MocapRoomAll_GEO) node in the scene split using nine material slots
- Bottle (Bottle_GEO) node with one material slot "Glass" covering the whole node, instanced three times
from skyrenderer.cases.utils import MaterialSlotFillerSceneComposer
scene_composer = MaterialSlotFillerSceneComposer(antialiasing_level=2048)
scene_composer.setup_scene()
scene_composer.visualize()
2025-01-29 14:03:44,502 | skyrenderer.scene.renderer_context | INFO: Root paths:
- root path: /dli/skyenvironment/skyrenderer/skyrenderer
- assets path: /dli/mount/assets
- config path: /dli/skyenvironment/skyrenderer/skyrenderer/config
- gpu sources path: /dli/skyenvironment/skyrenderer/skyrenderer/optix_sources/sources
- cache path: /dli/mount/cache
- ptx cache path: compiled_ptx/ptx
- ocio path: ocio_configs/aces_1.2/config.ocio
2025-01-29 14:03:44,868 | skyrenderer.scene.renderer_context | WARNING: Light with light_id=light_LIGHT_NUL already exists in the scene and will be replace with a new one.There can only be a single light for a single node.
2025-01-29 14:03:44,970 | skyrenderer.utils.time_measurement | INFO: Setup time: 101 ms
/dli/skyenvironment/skyrenderer/skyrenderer/basic_types/provider/unit_providers/geometry.py:25: RuntimeWarning: invalid value encountered in true_divide
n0 = n0 / np.linalg.norm(n0, axis=1, keepdims=True)
/dli/skyenvironment/skyrenderer/skyrenderer/basic_types/provider/unit_providers/geometry.py:26: RuntimeWarning: invalid value encountered in true_divide
n1 = n1 / np.linalg.norm(n1, axis=1, keepdims=True)
/dli/skyenvironment/skyrenderer/skyrenderer/basic_types/provider/unit_providers/geometry.py:27: RuntimeWarning: invalid value encountered in true_divide
n2 = n2 / np.linalg.norm(n2, axis=1, keepdims=True)
/dli/skyenvironment/skyrenderer/skyrenderer/basic_types/provider/unit_providers/geometry.py:36: RuntimeWarning: invalid value encountered in true_divide
dpdu = dpdu / np.linalg.norm(dpdu, axis=1, keepdims=True)
2025-01-29 14:03:45,759 | skyrenderer.utils.time_measurement | INFO: Context update time: 788 ms
2025-01-29 14:03:49,349 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms
2025-01-29 14:03:49,350 | skyrenderer.utils.time_measurement | INFO: Render time: 3.59 seconds
Manual setup of materials
To manually assign a material to the material slot, you can just create a texture provider, shader or parameter
provider with the name matching to the material slot's name.
We create a shader and a parameter provider for the "Glass" material slot and a texture provider for "WhiteWalls"
material slot. Note that we don't have to assign these elements to nodes, the names matching with the material
slots are enough.
from skyrenderer.basic_types.procedure.shader.basic_shaders.glass_shader import GlassShader
from skyrenderer.basic_types.provider import FileTextureProvider
GlassShader(scene_composer.renderer_context, name="Glass")
GlassShader.create_parameter_provider(
scene_composer.renderer_context,
name="Glass",
base_color=(1, 1, 1),
)
FileTextureProvider(scene_composer.renderer_context, name="WhiteWalls", asset_def="bricks")
scene_composer.visualize()
2025-01-29 14:03:49,923 | skyrenderer.utils.time_measurement | INFO: Setup time: 261 ms
2025-01-29 14:03:50,871 | skyrenderer.utils.time_measurement | INFO: Context update time: 947 ms
2025-01-29 14:03:55,226 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms
2025-01-29 14:03:55,228 | skyrenderer.utils.time_measurement | INFO: Render time: 4.36 seconds
Summary
In this section you have learnt:
- Face Sets and Material Slots are exchangeable names, and they can be used to assign materials.
- Each Material Slot is represented by the separate node.
- We can assign materials manually and automatically (via Material Slot Filler).