Texture compression
In this section you will get to know how to utilize texture compression.
Agenda:
- Texture compression introduction
- FileTextureProvider compression configuration
- HDRTextureProvider compression configuration
- SubstanceTextureProvider compression confguration
- Add textures, substances and background
Scene setup
Let's use custom scene composer to set up the scene.
Scene consists of:
- sphere - location: (0, 0, -1.1)
- cube - location: (0, 0, 1.1)
- green sphere light - location: (6, 4, -5)
- red sphere light - location: (6, 4, -5)
- camera - location: (6, 4, 3))
from skyrenderer.cases.utils import TextureCompressionSceneComposer
scene_composer = TextureCompressionSceneComposer()
scene_composer.setup_scene()
2025-02-14 12:47:01,844 | skyrenderer.scene.renderer_context | INFO: Root paths: - root path: /home/skyengine/anaconda/lib/python3.6/site-packages/skyrenderer - assets path: /dli/mount/assets - config path: /home/skyengine/anaconda/lib/python3.6/site-packages/skyrenderer/config - gpu sources path: /home/skyengine/anaconda/lib/python3.6/site-packages/skyrenderer/optix_sources/sources - cache path: /dli/mount/cache - ptx cache path: compiled_ptx/ptx - ocio path: ocio_configs/aces_1.2/config.ocio
Texture compression introduction
Texture compression is a technique that enables efficient storage and rendering of texture data by reducing VRAM
memory usage without affecting visual quality.
In SkyRenderer compression is generally handled automatically; all we need to do is enable it and configure the
compression settings.
There are three independent switches and configurations for texture compression, each specific to:
- FileTextureProvider: for standard textures loaded from formats like PNG, JPG, HDR, EXR, etc.
- HdrTextureProvider: for HDR environment maps
- SubstanceTextureProvider: for textures rendered through Substance
- SubstanceTextureProvider compression configuration
We use all three providers here and enable compression for each of them.
FileTextureProvider compression configuration
For FileTextureProvider we are using predefined "default" compression configuration.
Should be fine for typical use.
from skyrenderer.basic_types.provider import FileTextureProvider
FileTextureProvider.configure_image_compression("default")
FileTextureProvider.COMPRESSION_ENABLED = True
HDRTextureProvider compression configuration
For both env_map and env_map_light we are using BC6H format.
This is the only format that supports 16-bit floating-point channels.
It supports only RGB (no alpha), but for environment maps this is fine.
There is no higher quality format for environment maps available.
This format has 8 bits per texel.
from skyrenderer.basic_types.provider import HdrTextureProvider
import numpy as np
hdr_compression_config = {
("env_map", np.dtype(np.float32)): "BC6H",
("env_map_light", np.dtype(np.float32)): "BC6H",
}
HdrTextureProvider.configure_image_compression(hdr_compression_config)
HdrTextureProvider.COMPRESSION_ENABLED = True
SubstanceTextureProvider compression confguration
- For base_color_map we are using BC7 format. This is the highest quality format that supports RGB/RGBA
textures with 8-bit channels (uint8).
This format has 8 bits per texel, so for float32 we are compressing by a factor of 16.
Note, that Substance actually produces float32 texture here.
We are loosing bit-depth here by reducing to uint8, but it's fine for this texture. - For roughness_map we are using BC4 format. This is the only single-channel compressed format available.
It supports only 8-bit channels (uint8).
This format has 4 bits per texel, so for float32 we are compressing by a factor of 8.
Note, that Substance actually produces float32 texture here.
We are loosing bit-depth here by reducing to uint8, but it's fine for this texture. - For normal_map we are using BC6H format. This is the only format that supports 16-bit floating-point
channels. It supports only RGB (no alpha), but for normals this is fine.
There is no higher quality format for normals available.
Note, that Substance actually produces float32 texture here, we are reducing it to float16.
from skyrenderer.basic_types.provider import SubstanceTextureProvider
substance_compression_config = {
("base_color_map", np.dtype(np.float32)): "BC7",
("roughness_map", np.dtype(np.float32)): "BC4",
("normal_map", np.dtype(np.float32)): "BC6H",
}
SubstanceTextureProvider.configure_image_compression(substance_compression_config)
SubstanceTextureProvider.COMPRESSION_ENABLED = True
Add textures, substances and background
Create texture providers
Everything is done as usual here, no need to do anything related to compression.
Note, that specific textures might have override compression parameters defined in their JSON's.
texture_provider = FileTextureProvider(scene_composer.renderer_context, "yummy_scones/wood")
substance_provider = SubstanceTextureProvider(scene_composer.renderer_context, "marble_valencia")
background_texture_provider = HdrTextureProvider(
scene_composer.renderer_context,
"spruit_sunrise_4k",
gamma=1.0,
intensity=1.0,
gamma_light=1.0,
intensity_light=1.0,
)
2025-02-14 12:47:02,753 | skyrenderer.basic_types.provider.unit_providers.hdr_texture_provider | WARNING: Parameter light_adapt provided in HDR json is not supported 2025-02-14 12:47:02,754 | skyrenderer.basic_types.provider.unit_providers.hdr_texture_provider | WARNING: Parameter color_adapt provided in HDR json is not supported
Create shader and set materials
Create shader and materials in a regular way, nothing related to compression here.
from skyrenderer.basic_types.procedure import PBRShader
from skyrenderer.scene.scene_layout.layout_elements_definitions import MaterialDefinition
shader_procedure = PBRShader(scene_composer.renderer_context)
shader_parameter_provider = PBRShader.create_parameter_provider(
scene_composer.renderer_context, base_color=(1.0, 1.0, 1.0), roughness=0.02, specular_factor=0.8
)
scene_composer.renderer_context.set_material_definition(
"sphere_GEO", MaterialDefinition(substance_provider, shader_procedure, shader_parameter_provider)
)
scene_composer.renderer_context.set_material_definition(
"cube_001_GEO", MaterialDefinition(texture_provider, shader_procedure, shader_parameter_provider)
)
Add background envmap
Also nothing unusual here, no need to worry about texture compression.
from skyrenderer.basic_types.procedure import EnvMapMiss
from skyrenderer.basic_types.item_component import Background
background_def = Background(
scene_composer.renderer_context,
EnvMapMiss(scene_composer.renderer_context),
background_texture_provider,
EnvMapMiss.create_parameter_provider(scene_composer.renderer_context, max_hdr_value=10),
)
scene_composer.renderer_context.define_env(background_def)
scene_composer.visualize()
2025-02-14 12:47:04,953 | skyrenderer.utils.time_measurement | INFO: Setup time: 2.18 seconds 2025-02-14 12:47:08,718 | skyrenderer.utils.time_measurement | INFO: Context update time: 3.76 seconds 2025-02-14 12:47:13,406 | skyrenderer.utils.time_measurement | INFO: Key points calculation time: 0 ms 2025-02-14 12:47:13,408 | skyrenderer.utils.time_measurement | INFO: Render time: 4.69 seconds
Summary
In this section you have learnt:
- Texture compression can help you reduce VRAM usage.
- SkyRenderer provides texture compression for file, hdr and substance textures.
- To turn texture compression on, we need to set certain global flags to true.