diff --git a/apps/rendering_modes/balanced.kit b/apps/rendering_modes/balanced.kit deleted file mode 100644 index be2b03c0323..00000000000 --- a/apps/rendering_modes/balanced.kit +++ /dev/null @@ -1,49 +0,0 @@ -### THESE ARE RT1 SETTINGS ONLY ### -# rtx.translucency.enabled = false -# rtx.reflections.enabled = false -# rtx.reflections.denoiser.enabled = true -## this will be ignored when RR (dldenoiser) is enabled -## rtx.directLighting.sampledLighting.denoisingTechnique = 0 -# rtx.directLighting.sampledLighting.enabled = true -# rtx.indirectDiffuse.enabled = false -# rtx.indirectDiffuse.denoiser.enabled = true -############################################## - -### THESE ARE RT2 SETTINGS TO MATCH ABOVE PERFORMANCE SETTINGS ### -# these are needed if indirectDiffuse = false (this means GI false) - maxBounces needs to be 2 -rtx.rtpt.cached.enabled = false -rtx.rtpt.lightcache.cached.enabled = false -rtx.rtpt.translucency.virtualMotion.enabled = false -rtx.rtpt.maxBounces = 2 -rtx.rtpt.splitGlass = false -rtx.rtpt.splitClearcoat = false -rtx.rtpt.splitRoughReflection = true -# this gives slightly brighter image -rtx.rtpt.useAmbientOcclusionForAmbientLight = false -############################################## - -rtx.sceneDb.ambientLightIntensity = 1.0 - -rtx.shadows.enabled = true - -# rtx.domeLight.upperLowerStrategy = 3 - -rtx.ambientOcclusion.enabled = false -rtx.ambientOcclusion.denoiserMode = 1 - -rtx.raytracing.subpixel.mode = 0 -rtx.raytracing.cached.enabled = true - -# DLSS frame gen does not yet support tiled camera well -rtx-transient.dlssg.enabled = false - -rtx-transient.dldenoiser.enabled = true - -# Set the DLSS model -rtx.post.dlss.execMode = 1 # can be 0 (Performance), 1 (Balanced), 2 (Quality), or 3 (Auto) - -# Avoids replicator warning -rtx.pathtracing.maxSamplesPerLaunch = 1000000 - -# Avoids silent trimming of tiles -rtx.viewTile.limit = 1000000 diff --git a/apps/rendering_modes/performance.kit b/apps/rendering_modes/performance.kit deleted file mode 100644 index f991bd372bd..00000000000 --- a/apps/rendering_modes/performance.kit +++ /dev/null @@ -1,48 +0,0 @@ -### THESE ARE RT1 SETTINGS ONLY ### -# rtx.translucency.enabled = false -# rtx.reflections.enabled = false -# rtx.reflections.denoiser.enabled = false -# rtx.directLighting.sampledLighting.denoisingTechnique = 0 -# rtx.directLighting.sampledLighting.enabled = false -# rtx.indirectDiffuse.enabled = false -# rtx.indirectDiffuse.denoiser.enabled = false -############################################## - -### THESE ARE RT2 SETTINGS TO MATCH ABOVE PERFORMANCE SETTINGS ### -# these are needed if indirectDiffuse = false (this means GI false) - maxBounces needs to be 2 -rtx.rtpt.cached.enabled = false -rtx.rtpt.lightcache.cached.enabled = false -rtx.rtpt.translucency.virtualMotion.enabled = false -rtx.rtpt.maxBounces = 2 -rtx.rtpt.splitGlass = false -rtx.rtpt.splitClearcoat = false -rtx.rtpt.splitRoughReflection = true -# this gives slightly brighter image -rtx.rtpt.useAmbientOcclusionForAmbientLight = false -############################################## - -rtx.sceneDb.ambientLightIntensity = 1.0 - -rtx.shadows.enabled = true - -rtx.domeLight.upperLowerStrategy = 3 - -rtx.ambientOcclusion.enabled = false -rtx.ambientOcclusion.denoiserMode = 1 - -rtx.raytracing.subpixel.mode = 0 -rtx.raytracing.cached.enabled = false - -# DLSS frame gen does not yet support tiled camera well -rtx-transient.dlssg.enabled = false - -rtx-transient.dldenoiser.enabled = false - -# Set the DLSS model -rtx.post.dlss.execMode = 0 # can be 0 (Performance), 1 (Balanced), 2 (Quality), or 3 (Auto) - -# Avoids replicator warning -rtx.pathtracing.maxSamplesPerLaunch = 1000000 - -# Avoids silent trimming of tiles -rtx.viewTile.limit = 1000000 diff --git a/apps/rendering_modes/quality.kit b/apps/rendering_modes/quality.kit deleted file mode 100644 index 56073b84c67..00000000000 --- a/apps/rendering_modes/quality.kit +++ /dev/null @@ -1,53 +0,0 @@ -### THESE ARE RT1 SETTINGS ONLY ### -# rtx.translucency.enabled = true -# rtx.reflections.enabled = true -# rtx.reflections.denoiser.enabled = true -## this will be ignored when RR (dldenoiser) is enabled -## rtx.directLighting.sampledLighting.denoisingTechnique = 0 -# rtx.directLighting.sampledLighting.enabled = true -# rtx.indirectDiffuse.enabled = true -# rtx.indirectDiffuse.denoiser.enabled = true -############################################## - -### THESE ARE RT2 SETTINGS ### -# maxBounces should be 3 if indirectDiffuse was true -rtx.rtpt.maxBounces = 3 -rtx.rtpt.cached.enabled = false -rtx.rtpt.lightcache.cached.enabled = false -rtx.rtpt.translucency.virtualMotion.enabled = false -rtx.rtpt.splitRoughReflection = true -# these are even more costly, we should only set them to true if noise is observed -# rtx.rtpt.splitGlass = true -# rtx.rtpt.splitClearcoat = true - -# Improved adaptive sampling for disocclusion (reduces ghosting/temporal artifacts) -rtx.rtpt.adaptiveSampling.disocclusion.enabled = true -rtx.rtpt.adaptiveSampling.disocclusion.spp = 4 -############################################## - -rtx.sceneDb.ambientLightIntensity = 1.0 - -rtx.shadows.enabled = true - -# rtx.domeLight.upperLowerStrategy = 4 - -rtx.ambientOcclusion.enabled = true -rtx.ambientOcclusion.denoiserMode = 0 - -rtx.raytracing.subpixel.mode = 1 -rtx.raytracing.cached.enabled = true - -# DLSS frame gen does not yet support tiled camera well -rtx-transient.dlssg.enabled = false - -# RT2 only supports DLSS-RR -# rtx-transient.dldenoiser.enabled = true - -# Set the DLSS model -rtx.post.dlss.execMode = 2 # can be 0 (Performance), 1 (Balanced), 2 (Quality), or 3 (Auto) - -# Avoids replicator warning -rtx.pathtracing.maxSamplesPerLaunch = 1000000 - -# Avoids silent trimming of tiles -rtx.viewTile.limit = 1000000 diff --git a/docs/source/how-to/configure_rendering.rst b/docs/source/how-to/configure_rendering.rst index ee2510fdc44..9f20ae68011 100644 --- a/docs/source/how-to/configure_rendering.rst +++ b/docs/source/how-to/configure_rendering.rst @@ -17,30 +17,52 @@ Adjust and fine-tune rendering to achieve the ideal balance for your workflow. Selecting a Rendering Mode -------------------------- -Rendering modes can be selected in 2 ways. +Note, at present, rendering-mode profiles are supported for Kit Visualizers and RTX based Renderers -1. using the ``rendering_mode`` input class argument in :class:`~sim.RenderCfg` +You can pick ``performance``, ``balanced``, or ``quality`` (or a custom name you added under +:attr:`~sim.SimulationCfg.rendering_mode_cfgs`) in a few places: from the **command line**, through **visualizer configs**, or +through **renderer configs**. - .. code-block:: python +1. **Command Line.** ``--rendering_mode`` sets the mode at launch and overrides visualizer and RTX camera renderer + config settings when you pass it. - # for an example of how this can be used, checkout the tutorial script - # scripts/tutorials/00_sim/set_rendering_mode.py - render_cfg = sim_utils.RenderCfg(rendering_mode="performance") + .. code-block:: bash -2. using the ``--rendering_mode`` CLI argument, which takes precedence over the ``rendering_mode`` argument in :class:`~sim.RenderCfg`. + ./isaaclab.sh -p scripts/tutorials/00_sim/set_rendering_mode.py --rendering_mode {performance/balanced/quality} - .. code-block:: bash +2. **Visualizer Configs.** From a Visualizer Config, set the ``rendering_mode`` field to a profile name defined by the + the RenderingMode Configs. There are 3 presets: ``performance``, ``balanced``, and ``quality``. Users can also define + custom profiles by adding a named entry to :attr:`~sim.SimulationCfg.rendering_mode_cfgs` (see **Overriding Rendering Mode Settings** + below). Rendering Modes of Visualizers are set to performance by default. - ./isaaclab.sh -p scripts/tutorials/00_sim/set_rendering_mode.py --rendering_mode {performance/balanced/quality} + .. code-block:: python + # Set KitVisualizer to balanced rendering mode + sim_cfg = sim_utils.SimulationCfg( + visualizer_cfgs=[ + KitVisualizerCfg( + rendering_mode="balanced", + ), + ], + ) +3. **Renderer Configs.** Similar to Visualizer Configs, from a Renderer Config, set the ``rendering_mode`` field to a profile + name defined by the RenderingMode Configs. Rendering Modes of Renderers are set to None by default, which uses the native rendering settings of the workflow. -Note, the ``rendering_mode`` defaults to ``balanced``. -However, in the case where the launcher argument ``--enable_cameras`` is not set, then -the default ``rendering_mode`` is not applied and, instead, the default kit rendering settings are used. + .. code-block:: python + # Set RTX Renderer to quality rendering mode. + camera_cfg = CameraCfg( + prim_path="/World/envs/env_.*/Camera", + height=480, + width=640, + renderer_cfg=IsaacRtxRendererCfg(rendering_mode="quality"), + ) +.. note:: + If ``rendering_mode=None``, Isaac Lab uses the native rendering settings of the workflow Example renders from the ``set_rendering_mode.py`` script. -To help assess rendering, the example scene includes some reflections, translucency, direct and ambient lighting, and several material types. +To help assess rendering, the example scene includes reflections, translucency, +direct and ambient lighting, and several material types. - Quality Mode @@ -60,95 +82,97 @@ To help assess rendering, the example scene includes some reflections, transluce :width: 100% :alt: Performance Rendering Mode Example -Overwriting Specific Rendering Settings ---------------------------------------- +Overriding Rendering Mode Settings +---------------------------------- -Preset rendering settings can be overwritten via the :class:`~sim.RenderCfg` class. +Preset rendering settings can be overwritten via +:class:`~isaaclab.rendering_mode.RenderingModeCfg`. -There are 2 ways to provide settings that overwrite presets. +The built-in ``rendering_mode_preset`` field only accepts ``performance``, ``balanced``, or ``quality``; those map to +fixed RTX baselines in ``isaaclab_physx.rendering.rtx_rendering_mode_presets`` (also available via :func:`isaaclab.rendering_mode.get_rendering_mode_preset`). -1. :class:`~sim.RenderCfg` supports overwriting specific settings via user-friendly setting names that map to underlying RTX settings. - For example: +Rendering settings can be customized by either overwriting +specific settings of presets via ``kit_*`` fields (option 1) or by defining and adding a new **named profile** to :attr:`~sim.SimulationCfg.rendering_mode_cfgs` (option 2). - .. code-block:: python +1. :class:`~isaaclab.rendering_mode.RenderingModeCfg` supports overwriting specific settings via explicit + ``kit_*`` fields that map to underlying RTX settings. - render_cfg = sim_utils.RenderCfg( - rendering_mode="performance", - # user friendly setting overwrites - enable_translucency=True, # defaults to False in performance mode - enable_reflections=True, # defaults to False in performance mode - dlss_mode="3", # defaults to 1 in performance mode + .. code-block:: python + mode_cfg = RenderingModeCfg( + rendering_mode_preset="performance", + # explicit field overrides + kit_enable_translucency=True, # defaults to False in performance mode + kit_enable_reflections=True, # defaults to False in performance mode + kit_dlss_mode=3, # defaults to 0 in performance mode ) - List of user-friendly settings. + List of Kit settings. .. table:: :widths: 25 75 - +----------------------------+--------------------------------------------------------------------------+ - | enable_translucency | Bool. Enables translucency for specular transmissive surfaces such as | - | | glass at the cost of some performance. | - +----------------------------+--------------------------------------------------------------------------+ - | enable_reflections | Bool. Enables reflections at the cost of some performance. | - +----------------------------+--------------------------------------------------------------------------+ - | enable_global_illumination | Bool. Enables Diffused Global Illumination at the cost of some | - | | performance. | - +----------------------------+--------------------------------------------------------------------------+ - | antialiasing_mode | Literal["Off", "FXAA", "DLSS", "TAA", "DLAA"]. | - | | | - | | DLSS: Boosts performance by using AI to output higher resolution frames | - | | from a lower resolution input. DLSS samples multiple lower resolution | - | | images and uses motion data and feedback from prior frames to reconstruct| - | | native quality images. | - | | DLAA: Provides higher image quality with an AI-based anti-aliasing | - | | technique. DLAA uses the same Super Resolution technology developed for | - | | DLSS, reconstructing a native resolution image to maximize image quality.| - +----------------------------+--------------------------------------------------------------------------+ - | enable_dlssg | Bool. Enables the use of DLSS-G. DLSS Frame Generation boosts performance| - | | by using AI to generate more frames. This feature requires an Ada | - | | Lovelace architecture GPU and can hurt performance due to additional | - | | thread-related activities. | - +----------------------------+--------------------------------------------------------------------------+ - | enable_dl_denoiser | Bool. Enables the use of a DL denoiser, which improves the quality of | - | | renders at the cost of performance. | - +----------------------------+--------------------------------------------------------------------------+ - | dlss_mode | Literal[0, 1, 2, 3]. For DLSS anti-aliasing, selects the performance/ | - | | quality tradeoff mode. Valid values are 0 (Performance), 1 (Balanced), | - | | 2 (Quality), or 3 (Auto). | - +----------------------------+--------------------------------------------------------------------------+ - | enable_direct_lighting | Bool. Enable direct light contributions from lights. | - +----------------------------+--------------------------------------------------------------------------+ - | samples_per_pixel | Int. Defines the Direct Lighting samples per pixel. Higher values | - | | increase the direct lighting quality at the cost of performance. | - +----------------------------+--------------------------------------------------------------------------+ - | enable_shadows | Bool. Enables shadows at the cost of performance. When disabled, lights | - | | will not cast shadows. | - +----------------------------+--------------------------------------------------------------------------+ - | enable_ambient_occlusion | Bool. Enables ambient occlusion at the cost of some performance. | - +----------------------------+--------------------------------------------------------------------------+ - - -2. For more control, :class:`~sim.RenderCfg` allows you to overwrite any RTX setting by using the ``carb_settings`` argument. - - Examples of RTX settings can be found from within the repo, in the render mode preset files located in ``apps/rendering_modes``. - - In addition, the full NVIDIA RTX renderer documentation can be found at - https://docs.omniverse.nvidia.com/materials-and-rendering/latest/rtx-renderer.html. - - An example usage of ``carb_settings``. + +------------------------------------+-------------------------------------------------------------------------+ + | kit_enable_translucency | Bool. Enables translucency for specular transmissive surfaces such as | + | | glass at the cost of some performance. | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_enable_reflections | Bool. Enables reflections at the cost of some performance. | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_enable_global_illumination | Bool. Enables Diffuse Global Illumination at the cost of some | + | | performance. | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_antialiasing_mode | Literal["Off", "FXAA", "DLSS", "TAA", "DLAA"]. | + | | DLSS boosts performance by reconstructing higher-resolution frames. | + | | DLAA prioritizes image quality using the same SR technology as DLSS. | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_enable_dlssg | Bool. Enables DLSS-G frame generation (Ada Lovelace GPU required). | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_enable_dl_denoiser | Bool. Enables DL denoiser (quality up, performance down). | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_dlss_mode | Literal[0, 1, 2, 3] = Performance, Balanced, Quality, Auto. | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_enable_direct_lighting | Bool. Enables direct light contributions from lights. | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_samples_per_pixel | Int. Direct lighting samples-per-pixel (higher = better, slower). | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_enable_shadows | Bool. Enables shadows at performance cost. | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_enable_ambient_occlusion | Bool. Enables ambient occlusion at performance cost. | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_dome_light_upper_lower_strategy | Literal[0, 3, 4]. Maps to ``/rtx/domeLight/upperLowerStrategy`` (dome | + | | light upper/lower hemisphere handling; see Omniverse RTX docs for | + | | semantics of each value). | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_disocclusion_scale | Float. Aggressiveness of disocclusion handling for tiled rendering | + | | (maps to ``/rtx/aovConverter/disocclusionScale``). | + +------------------------------------+-------------------------------------------------------------------------+ + | kit_nre_compositing_renderer_hints | Int. NRE compositing hint (Isaac Lab apps use ``3``). Maps to | + | | ``/omni/rtx/nre/compositing/rendererHints``. | + +------------------------------------+-------------------------------------------------------------------------+ + + +2. If you need a custom profile, define your own named entry in + :attr:`~sim.SimulationCfg.rendering_mode_cfgs` and reference that name from ``KitVisualizerCfg.rendering_mode`` + (:mod:`isaaclab_physx.visualizers`) and/or ``camera_cfg.renderer_cfg.rendering_mode`` (RTX renderers under + :mod:`isaaclab_physx.renderers`). .. code-block:: python - - render_cfg = sim_utils.RenderCfg( - rendering_mode="quality", - # carb setting overwrites - carb_settings={ - "rtx.translucency.enabled": False, - "rtx.reflections.enabled": False, - "rtx.domeLight.upperLowerStrategy": 3, - } + sim_cfg = sim_utils.SimulationCfg( + rendering_mode_cfgs={ + "my_profile": RenderingModeCfg( + rendering_mode_preset="balanced", + kit_enable_reflections=True, + kit_dlss_mode=2, + ), + }, + visualizer_cfgs=[KitVisualizerCfg(rendering_mode="my_profile")], ) + camera_cfg = CameraCfg( + prim_path="/World/envs/env_.*/Camera", + height=480, + width=640, + renderer_cfg=IsaacRtxRendererCfg(rendering_mode="my_profile"), + ) Current Limitations ------------------- diff --git a/scripts/tutorials/00_sim/set_rendering_mode.py b/scripts/tutorials/00_sim/set_rendering_mode.py index 38a1d5b2ba8..e820e3ce1d5 100644 --- a/scripts/tutorials/00_sim/set_rendering_mode.py +++ b/scripts/tutorials/00_sim/set_rendering_mode.py @@ -33,7 +33,10 @@ """Rest everything follows.""" +from isaaclab_physx.visualizers import KitVisualizerCfg + import isaaclab.sim as sim_utils +from isaaclab.rendering_mode import RenderingModeCfg from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR @@ -41,21 +44,32 @@ def main(): """Main function.""" # rendering modes include performance, balanced, and quality - # note, the rendering_mode specified in the CLI argument (--rendering_mode) takes precedence over - # this Render Config setting + # note: the CLI argument (--rendering_mode) takes precedence over this visualizer setting rendering_mode = "performance" - # carb setting dictionary can include any rtx carb setting which will overwrite the native preset setting - carb_settings = {"rtx.reflections.enabled": True} - - # Initialize render config - render_cfg = sim_utils.RenderCfg( - rendering_mode=rendering_mode, - carb_settings=carb_settings, + # RTX tuning uses :class:`RenderingModeCfg` profiles on ``SimulationCfg.rendering_mode_cfgs`` + # (not raw carb paths). Each built-in name starts from its preset, then applies optional ``kit_*`` overrides. + sim_cfg = sim_utils.SimulationCfg( + rendering_mode_cfgs={ + "performance": RenderingModeCfg( + rendering_mode_preset="performance", + kit_enable_reflections=True, + ), + "balanced": RenderingModeCfg( + rendering_mode_preset="balanced", + kit_enable_reflections=True, + kit_dlss_mode=1, + ), + "quality": RenderingModeCfg( + rendering_mode_preset="quality", + kit_antialiasing_mode="DLAA", + kit_disocclusion_scale=10_000.0, + ), + }, + visualizer_cfgs=[ + KitVisualizerCfg(rendering_mode=rendering_mode), + ], ) - - # Initialize the simulation context with render coofig - sim_cfg = sim_utils.SimulationCfg(render=render_cfg) sim = sim_utils.SimulationContext(sim_cfg) # Pose camera in the hospital lobby area diff --git a/source/isaaclab/isaaclab/app/app_launcher.py b/source/isaaclab/isaaclab/app/app_launcher.py index df6f7cb79e1..8ad6886931a 100644 --- a/source/isaaclab/isaaclab/app/app_launcher.py +++ b/source/isaaclab/isaaclab/app/app_launcher.py @@ -29,6 +29,10 @@ from isaacsim import SimulationApp from isaaclab.app.settings_manager import get_settings_manager, initialize_carb_settings +from isaaclab.rendering_mode.rendering_mode_utils import ( + CLI_RENDERING_MODE_PROFILE_PATH, + apply_rendering_mode_preset, +) # import logger logger = logging.getLogger(__name__) @@ -446,9 +450,8 @@ def add_app_launcher_args(parser: argparse.ArgumentParser) -> None: action=ExplicitAction, choices={"performance", "balanced", "quality"}, help=( - "Sets the rendering mode. Preset settings files can be found in apps/rendering_modes." - ' Can be "performance", "balanced", or "quality".' - " Individual settings can be overwritten by using the RenderCfg class." + "When passed, selects RenderingModeCfg presets for overwriting rendering settings of all Renderers" + "When passed, selects RenderingModeCfg presets for overwriting rendering settings of all Renderers " ), ) arg_group.add_argument( @@ -701,7 +704,7 @@ def _resolve_headless_settings(self, launcher_args: dict, livestream_arg: int, l # the bool of headless_arg to avoid messy string processing, headless_env = int(os.environ.get("HEADLESS", 0)) headless_arg = launcher_args.pop("headless", AppLauncher._APPLAUNCHER_CFG_INFO["headless"][1]) - headless_arg_explicit = launcher_args.pop("headless_explicit", False) + headless_arg_explicit = bool(launcher_args.pop("headless_explicit", False)) headless_valid_vals = {0, 1} # Value checking on HEADLESS if headless_env not in headless_valid_vals: @@ -1116,6 +1119,7 @@ def _hide_stop_button(self): def _set_rendering_mode_settings(self, launcher_args: dict) -> None: """Store RTX rendering mode in settings.""" + rendering_mode_explicit = launcher_args.pop("rendering_mode_explicit", False) rendering_mode = launcher_args.get("rendering_mode") if rendering_mode is None: @@ -1124,7 +1128,24 @@ def _set_rendering_mode_settings(self, launcher_args: dict) -> None: return rendering_mode = "" - get_settings_manager().set_string("/isaaclab/rendering/rendering_mode", rendering_mode) + settings = get_settings_manager() + settings.set_string(CLI_RENDERING_MODE_PROFILE_PATH, rendering_mode) + settings.set_bool("/isaaclab/rendering/rendering_mode/explicit", bool(rendering_mode_explicit)) + + # Apply built-in Kit presets at launch so RTX matches the CLI before SimulationContext runs. + if ( + rendering_mode_explicit + and rendering_mode in {"performance", "balanced", "quality"} + and settings.is_omniverse_mode + ): + try: + apply_rendering_mode_preset(settings.set, rendering_mode) + except Exception as e: + logger.warning( + "Could not apply Kit rendering preset %r to carb settings at launch: %s", + rendering_mode, + e, + ) def _set_animation_recording_settings(self, launcher_args: dict) -> None: """Store animation recording settings in settings.""" diff --git a/source/isaaclab/isaaclab/app/settings_manager.py b/source/isaaclab/isaaclab/app/settings_manager.py index 8281c627a91..5abbe9b392d 100644 --- a/source/isaaclab/isaaclab/app/settings_manager.py +++ b/source/isaaclab/isaaclab/app/settings_manager.py @@ -125,7 +125,6 @@ def get(self, path: str, default: Any = None) -> Any: The value at the path, or default if not found """ if self._use_carb and self._carb_settings is not None: - # Delegate to carb.settings value = self._carb_settings.get(path) return value if value is not None else default else: diff --git a/source/isaaclab/isaaclab/renderers/renderer_cfg.py b/source/isaaclab/isaaclab/renderers/renderer_cfg.py index 334fa3f070a..e646caf161f 100644 --- a/source/isaaclab/isaaclab/renderers/renderer_cfg.py +++ b/source/isaaclab/isaaclab/renderers/renderer_cfg.py @@ -12,4 +12,11 @@ class RendererCfg: """Configuration for a renderer.""" - renderer_type: str = "default" + renderer_type: str | None = None + """Type identifier for selecting a renderer backend implementation.""" + + rendering_mode: str | None = None + """Name of the rendering mode profile for selecting rendering settings. + + Set to None by default, which uses the native rendering settings of the workflow. + """ diff --git a/source/isaaclab/isaaclab/rendering_mode/__init__.py b/source/isaaclab/isaaclab/rendering_mode/__init__.py new file mode 100644 index 00000000000..1087be0475a --- /dev/null +++ b/source/isaaclab/isaaclab/rendering_mode/__init__.py @@ -0,0 +1,17 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Rendering mode config, presets, and application helpers.""" + +from .rendering_mode_cfg import RenderingModeCfg +from .rendering_mode_presets import get_rendering_mode_preset +from .rendering_mode_utils import CLI_RENDERING_MODE_PROFILE_PATH, resolve_effective_rendering_mode_name + +__all__ = [ + "CLI_RENDERING_MODE_PROFILE_PATH", + "RenderingModeCfg", + "get_rendering_mode_preset", + "resolve_effective_rendering_mode_name", +] diff --git a/source/isaaclab/isaaclab/rendering_mode/rendering_mode_cfg.py b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_cfg.py new file mode 100644 index 00000000000..0621e17dbea --- /dev/null +++ b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_cfg.py @@ -0,0 +1,158 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +from __future__ import annotations + +from typing import Literal + +from isaaclab.utils import configclass + + +@configclass +class RenderingModeCfg: + """RTX/carb settings for `Omniverse RTX`_ (viewport + RTX camera renderers: + ``default`` / ``isaac_rtx`` / ``rtx``). + + Put named profiles in :attr:`~isaaclab.sim.SimulationCfg.rendering_mode_cfgs`, then set the same name on + ``KitVisualizerCfg.rendering_mode`` or ``CameraCfg.renderer_cfg.rendering_mode`` (non-Kit renderers ignore it). + + **Order:** optional :attr:`rendering_mode_preset` (``performance`` / ``balanced`` / ``quality``) loads the + matching baseline from :mod:`isaaclab_physx.rendering.rtx_rendering_mode_presets` (via + :func:`isaaclab.rendering_mode.get_rendering_mode_preset`)—the same three choices as CLI + ``--rendering_mode``. Each non-``None`` ``kit_*`` field then overrides specific carb paths on top of that + baseline. + + Baselines before this config are defined by the app experience (e.g. ``apps/isaaclab.python.rendering.kit``, + ``apps/isaaclab.python.headless.rendering.kit``). Newton / non-Kit viewer options belong on ``NewtonVisualizerCfg``, + not here. + + .. _Omniverse RTX: https://docs.omniverse.nvidia.com/materials-and-rendering/latest/rtx-renderer.html + """ + + rendering_mode_preset: Literal["performance", "balanced", "quality"] | None = None + """Optional built-in RTX baseline (performance, balanced, or quality). + + Values are defined in :mod:`isaaclab_physx.rendering.rtx_rendering_mode_presets`. This is the same + conceptual knob as passing ``--rendering_mode`` to a script: it selects one of the three + packaged profiles before any per-field ``kit_*`` overrides below are applied. + """ + + kit_enable_translucency: bool | None = None + """Enables translucency for specular transmissive surfaces such as glass. + + This comes at the cost of some performance. Default in experience files is typically ``False``. + Carb path: ``/rtx/translucency/enabled``. + """ + + kit_enable_reflections: bool | None = None + """Enables reflections at the cost of some performance. Default is often ``False`` in presets. + + Carb path: ``/rtx/reflections/enabled``. + """ + + kit_enable_global_illumination: bool | None = None + """Enables diffuse global illumination at the cost of some performance. Default is often ``False``. + + Carb path: ``/rtx/indirectDiffuse/enabled``. + """ + + kit_antialiasing_mode: Literal["Off", "FXAA", "DLSS", "TAA", "DLAA"] | None = None + """Anti-aliasing mode (defaults in experience files often favor DLSS where available). + + - **DLSS**: Uses AI to reconstruct higher-resolution frames from a lower-resolution input, using + motion data and prior-frame feedback. + - **DLAA**: Uses the same super-resolution stack as DLSS to anti-alias at native resolution for + maximum image quality. + + Applied through ``omni.replicator.core`` (``set_render_rtx_realtime``) so it stays consistent + with Replicator; other ``kit_*`` paths are set directly on carb after this call. + """ + + kit_enable_dlssg: bool | None = None + """Enables DLSS Frame Generation. Default is typically ``False``. + + DLSS-G boosts performance by synthesizing additional frames from sequential frames and motion + data. + + .. note:: + + Requires an Ada Lovelace GPU. Can add thread-related overhead. + + Carb path: ``/rtx-transient/dlssg/enabled``. + """ + + kit_enable_dl_denoiser: bool | None = None + """Enables the DL denoiser (quality up, performance down). + + Carb path: ``/rtx-transient/dldenoiser/enabled``. + """ + + kit_dlss_mode: Literal[0, 1, 2, 3] | None = None + """When using DLSS anti-aliasing, selects the performance/quality tradeoff. Default is often ``0``. + + * ``0`` — Performance + * ``1`` — Balanced + * ``2`` — Quality + * ``3`` — Auto + + Carb path: ``/rtx/post/dlss/execMode``. + """ + + kit_enable_direct_lighting: bool | None = None + """Enables direct light contributions from lights. Default is often ``False`` in tight presets. + + Carb path: ``/rtx/directLighting/enabled``. + """ + + kit_samples_per_pixel: int | None = None + """Direct lighting samples per pixel (higher improves quality, costs performance). Default is often ``1``. + + Carb path: ``/rtx/directLighting/sampledLighting/samplesPerPixel``. + """ + + kit_enable_shadows: bool | None = None + """Enables shadows (performance cost). Defaults are often ``True`` when lighting is on. + + Carb path: ``/rtx/shadows/enabled``. + """ + + kit_enable_ambient_occlusion: bool | None = None + """Enables ambient occlusion at a performance cost. Default is often ``False`` in performance presets. + + Carb path: ``/rtx/ambientOcclusion/enabled``. + """ + + kit_dome_light_upper_lower_strategy: Literal[0, 3, 4] | None = None + """How the dome light is sampled. Default is often ``0``. + + See `dome light sampling`_ in the Omniverse RTX docs for semantics. + + * ``0`` — **Image-based lighting (IBL)** — Most accurate for high-frequency dome textures; can show + sampling artifacts in real time. + * ``3`` — **Limited IBL** — Fastest, least accurate; good when the dome is a minor contributor. + * ``4`` — **Approximated IBL** — Fast, artifact-free in real time for low-frequency domes; pairs + with the direct-lighting denoiser. + + Carb path: ``/rtx/domeLight/upperLowerStrategy``. + + .. _dome light sampling: https://docs.omniverse.nvidia.com/materials-and-rendering/latest/rtx-renderer_common.html#dome-light + """ + + kit_disocclusion_scale: float | None = None + """Scales disocclusion handling for tiled / per-camera rendering (ghosting, newly exposed regions). + + Higher values can reduce disocclusion artifacts at the cost of stability or side effects in some scenes. + Carb path: ``/rtx/aovConverter/disocclusionScale``. + """ + + kit_nre_compositing_renderer_hints: int | None = None + """NRE compositing renderer hints (Isaac Lab rendering experiences use ``3``). + + Required for correct compositing when using UsdVol 3D Gaussian content across multiple environments. + Carb path: ``/omni/rtx/nre/compositing/rendererHints`` (see also + ``omni.rtx.nre.compositing.rendererHints`` in application ``.kit`` files). + """ + + # TODO: Optional passthrough dict for arbitrary carb keys (cf. legacy RenderCfg.carb_settings). diff --git a/source/isaaclab/isaaclab/rendering_mode/rendering_mode_presets.py b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_presets.py new file mode 100644 index 00000000000..8b6d87f53d0 --- /dev/null +++ b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_presets.py @@ -0,0 +1,30 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Stable entry point for built-in RTX presets. + +Preset tables are defined in :mod:`isaaclab_physx.rendering.rtx_rendering_mode_presets` and loaded here +so ``isaaclab.rendering_mode`` keeps a single public API. +""" + +from __future__ import annotations + +from typing import Any + + +def get_rendering_mode_preset(preset_name: str) -> dict[str, Any]: + """Return a deep copy of the requested built-in rendering mode preset. + + Raises: + ImportError: If ``isaaclab_physx`` is not installed (RTX presets live in that package). + """ + try: + from isaaclab_physx.rendering.rtx_rendering_mode_presets import get_builtin_rtx_rendering_mode_preset + except ImportError as e: + raise ImportError( + "RTX rendering mode presets are provided by isaaclab_physx. " + "Install with: pip install 'isaaclab[physx]' or install the isaaclab_physx package." + ) from e + return get_builtin_rtx_rendering_mode_preset(preset_name) diff --git a/source/isaaclab/isaaclab/rendering_mode/rendering_mode_utils.py b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_utils.py new file mode 100644 index 00000000000..a74708c4f6d --- /dev/null +++ b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_utils.py @@ -0,0 +1,164 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Utility helpers for applying rendering mode profiles.""" + +from __future__ import annotations + +import contextlib +import logging +from typing import Any + +from .rendering_mode_cfg import RenderingModeCfg +from .rendering_mode_presets import get_rendering_mode_preset + +_logger = logging.getLogger(__name__) + +# Log at most once if carb cannot read the CLI profile leaf. +_cli_rendering_mode_resolution_warned = False + +# CLI profile name string; AppLauncher uses this leaf path (``set_string``). +CLI_RENDERING_MODE_PROFILE_PATH = "/isaaclab/rendering/rendering_mode/profile" + +_RENDERING_MODE_FIELD_TO_CARB: dict[str, str] = { + "kit_enable_translucency": "/rtx/translucency/enabled", + "kit_enable_reflections": "/rtx/reflections/enabled", + "kit_enable_global_illumination": "/rtx/indirectDiffuse/enabled", + "kit_enable_dlssg": "/rtx-transient/dlssg/enabled", + "kit_enable_dl_denoiser": "/rtx-transient/dldenoiser/enabled", + "kit_dlss_mode": "/rtx/post/dlss/execMode", + "kit_enable_direct_lighting": "/rtx/directLighting/enabled", + "kit_samples_per_pixel": "/rtx/directLighting/sampledLighting/samplesPerPixel", + "kit_enable_shadows": "/rtx/shadows/enabled", + "kit_enable_ambient_occlusion": "/rtx/ambientOcclusion/enabled", + "kit_dome_light_upper_lower_strategy": "/rtx/domeLight/upperLowerStrategy", + "kit_disocclusion_scale": "/rtx/aovConverter/disocclusionScale", + "kit_nre_compositing_renderer_hints": "/omni/rtx/nre/compositing/rendererHints", +} + + +def _read_cli_rendering_mode_profile_name(get_setting: Any) -> str | None: + """Read CLI rendering mode profile name (``performance`` / ``balanced`` / ``quality``). + + Reads :data:`CLI_RENDERING_MODE_PROFILE_PATH` (a string leaf written by :class:`~isaaclab.app.AppLauncher`). + """ + global _cli_rendering_mode_resolution_warned + + with contextlib.suppress(Exception): + import carb + + gs = carb.settings.get_settings() + if gs is not None and hasattr(gs, "get_string"): + with contextlib.suppress(Exception): + s = gs.get_string(CLI_RENDERING_MODE_PROFILE_PATH) + if s is not None: + out = str(s).strip() + if out: + return out + + raw = get_setting(CLI_RENDERING_MODE_PROFILE_PATH) + if isinstance(raw, str): + out = raw.strip() + return out if out else None + + if raw is not None: + if not _cli_rendering_mode_resolution_warned: + _cli_rendering_mode_resolution_warned = True + _logger.warning( + "Could not read %s as a string profile name (got %s). CLI rendering mode override may be ignored.", + CLI_RENDERING_MODE_PROFILE_PATH, + type(raw).__name__, + ) + return None + + +def resolve_effective_rendering_mode_name(get_setting: Any, cfg: Any) -> str | None: + """CLI explicit flag wins; otherwise use ``cfg.rendering_mode``.""" + if bool(get_setting("/isaaclab/rendering/rendering_mode/explicit")): + return _read_cli_rendering_mode_profile_name(get_setting) + return getattr(cfg, "rendering_mode", None) + + +def apply_rendering_mode_preset(set_setting: Any, preset_name: str) -> None: + """Apply a named built-in preset (performance / balanced / quality) via the provided setter.""" + preset = get_rendering_mode_preset(preset_name) + for key, value in preset.items(): + set_setting(key, value) + + +def apply_rendering_mode_cfg(set_setting: Any, mode_cfg: RenderingModeCfg) -> None: + """Apply :class:`RenderingModeCfg` fields to carb (preset baseline + per-field overrides).""" + if mode_cfg.rendering_mode_preset: + apply_rendering_mode_preset(set_setting, mode_cfg.rendering_mode_preset) + + # Replicator's set_render_rtx_realtime() can reset other RTX carb flags. Run it before applying + # explicit per-field carb overrides so user settings remain authoritative. + if mode_cfg.kit_antialiasing_mode is not None: + with contextlib.suppress(Exception): + import omni.replicator.core as rep + + rep.settings.set_render_rtx_realtime(antialiasing=mode_cfg.kit_antialiasing_mode) + + for field_name, carb_key in _RENDERING_MODE_FIELD_TO_CARB.items(): + value = getattr(mode_cfg, field_name, None) + if value is not None: + set_setting(carb_key, value) + + +def apply_mode_profile_to_renderer_cfg( + get_setting: Any, + set_setting: Any, + renderer_cfg: Any, + mode_cfgs: dict[str, RenderingModeCfg], + logger: Any, +) -> None: + """Resolve and apply a rendering mode profile to an RTX :class:`~isaaclab.renderers.RendererCfg` (in place).""" + rtype = getattr(renderer_cfg, "renderer_type", None) + if rtype not in ("default", "isaac_rtx", "rtx"): + return + mode_name = resolve_effective_rendering_mode_name(get_setting, renderer_cfg) + mode_cfg = resolve_rendering_mode_cfg(mode_name, mode_cfgs, logger) + if mode_cfg is None: + return + apply_rendering_mode_cfg(set_setting, mode_cfg) + + +def resolve_rendering_mode_cfg( + mode_name: str | None, mode_cfgs: dict[str, RenderingModeCfg], logger: Any +) -> RenderingModeCfg | None: + """Fetch rendering mode cfg by name and log if missing.""" + if not mode_name: + return None + if not isinstance(mode_name, str): + logger.warning( + "[SimulationContext] Rendering mode name must be str, got %s; skipping profile lookup.", + type(mode_name).__name__, + ) + return None + mode_cfg = mode_cfgs.get(mode_name) + if mode_cfg is None: + logger.warning( + "[SimulationContext] Rendering mode '%s' not found in SimulationCfg.rendering_mode_cfgs.", + mode_name, + ) + return None + return mode_cfg + + +def apply_mode_profile_to_visualizer_cfg( + get_setting: Any, + set_setting: Any, + visualizer_cfg: Any, + mode_cfgs: dict[str, RenderingModeCfg], + logger: Any, +) -> None: + """Resolve and apply rendering mode profile for a viewport visualizer (RTX / carb settings).""" + if getattr(visualizer_cfg, "visualizer_type", None) != "kit": + return + mode_name = resolve_effective_rendering_mode_name(get_setting, visualizer_cfg) + mode_cfg = resolve_rendering_mode_cfg(mode_name, mode_cfgs, logger) + if mode_cfg is None: + return + apply_rendering_mode_cfg(set_setting, mode_cfg) diff --git a/source/isaaclab/isaaclab/sensors/camera/camera.py b/source/isaaclab/isaaclab/sensors/camera/camera.py index 70ccc6c14dd..a3dbe1e6fc9 100644 --- a/source/isaaclab/isaaclab/sensors/camera/camera.py +++ b/source/isaaclab/isaaclab/sensors/camera/camera.py @@ -20,6 +20,8 @@ import isaaclab.sim as sim_utils import isaaclab.utils.sensors as sensor_utils from isaaclab.app.settings_manager import get_settings_manager +from isaaclab.rendering_mode.rendering_mode_utils import apply_mode_profile_to_renderer_cfg +from isaaclab.sim import SimulationContext from isaaclab.sim.views import XformPrimView from isaaclab.utils import has_kit, to_camel_case from isaaclab.utils.array import convert_to_torch @@ -443,6 +445,17 @@ def _initialize_impl(self): " rendering." ) + sim = SimulationContext.instance() + if sim is not None: + mode_cfgs = sim.cfg.rendering_mode_cfgs + apply_mode_profile_to_renderer_cfg( + sim.get_setting, + sim.set_setting, + self.cfg.renderer_cfg, + mode_cfgs, + logger, + ) + import omni.replicator.core as rep from omni.syntheticdata.scripts.SyntheticData import SyntheticData diff --git a/source/isaaclab/isaaclab/sensors/camera/tiled_camera.py b/source/isaaclab/isaaclab/sensors/camera/tiled_camera.py index e6ae56adaa5..aedd7af0e33 100644 --- a/source/isaaclab/isaaclab/sensors/camera/tiled_camera.py +++ b/source/isaaclab/isaaclab/sensors/camera/tiled_camera.py @@ -17,6 +17,8 @@ from isaaclab.app.settings_manager import get_settings_manager from isaaclab.renderers import Renderer +from isaaclab.rendering_mode.rendering_mode_utils import apply_mode_profile_to_renderer_cfg +from isaaclab.sim import SimulationContext from isaaclab.sim.views import XformPrimView from ..sensor_base import SensorBase @@ -163,6 +165,17 @@ def _initialize_impl(self): # Initialize parent class SensorBase._initialize_impl(self) + sim = SimulationContext.instance() + if sim is not None: + mode_cfgs = sim.cfg.rendering_mode_cfgs + apply_mode_profile_to_renderer_cfg( + sim.get_setting, + sim.set_setting, + self.cfg.renderer_cfg, + mode_cfgs, + logger, + ) + self.renderer = Renderer(self.cfg.renderer_cfg) logger.info("Using renderer: %s", type(self.renderer).__name__) diff --git a/source/isaaclab/isaaclab/sim/simulation_cfg.py b/source/isaaclab/isaaclab/sim/simulation_cfg.py index 6c2e97bb7e8..82c762372ee 100644 --- a/source/isaaclab/isaaclab/sim/simulation_cfg.py +++ b/source/isaaclab/isaaclab/sim/simulation_cfg.py @@ -11,161 +11,15 @@ from __future__ import annotations -from typing import Any, Literal # Literal used by RenderCfg +from typing import Literal from isaaclab.physics import PhysicsCfg +from isaaclab.rendering_mode.rendering_mode_cfg import RenderingModeCfg from isaaclab.sim.spawners.materials.physics_materials_cfg import RigidBodyMaterialCfg from isaaclab.utils import configclass from isaaclab.visualizers import VisualizerCfg -@configclass -class RenderCfg: - """Configuration for Omniverse RTX Renderer. - - These parameters are used to configure the Omniverse RTX Renderer. - - The defaults for IsaacLab are set in the experience files: - - * ``apps/isaaclab.python.rendering.kit``: Setting used when running the simulation with the GUI enabled. - * ``apps/isaaclab.python.headless.rendering.kit``: Setting used when running the simulation in headless mode. - - Setting any value here will override the defaults of the experience files. - - For more information, see the `Omniverse RTX Renderer documentation`_. - - .. _Omniverse RTX Renderer documentation: https://docs.omniverse.nvidia.com/materials-and-rendering/latest/rtx-renderer.html - """ - - enable_translucency: bool | None = None - """Enables translucency for specular transmissive surfaces such as glass. - - This comes at the cost of some performance. Default is False. - This is set by the variable: ``/rtx/translucency/enabled``. - """ - - enable_reflections: bool | None = None - """Enables reflections at the cost of some performance. Default is False. - - This is set by the variable: ``/rtx/reflections/enabled``. - """ - - enable_global_illumination: bool | None = None - """Enables Diffused Global Illumination at the cost of some performance. Default is False. - - This is set by the variable: ``/rtx/indirectDiffuse/enabled``. - """ - - antialiasing_mode: Literal["Off", "FXAA", "DLSS", "TAA", "DLAA"] | None = None - """Selects the anti-aliasing mode to use. Defaults to DLSS. - - - **DLSS**: Boosts performance by using AI to output higher resolution frames from a lower resolution input. - DLSS samples multiple lower resolution images and uses motion data and feedback from prior frames to reconstruct - native quality images. - - **DLAA**: Provides higher image quality with an AI-based anti-aliasing technique. DLAA uses the same - Super Resolution technology developed for DLSS, reconstructing a native resolution image to maximize - image quality. - - This is set by the variable: ``/rtx/post/dlss/execMode``. - """ - - enable_dlssg: bool | None = None - """"Enables the use of DLSS-G. Default is False. - - DLSS Frame Generation boosts performance by using AI to generate more frames. DLSS analyzes sequential frames - and motion data to create additional high quality frames. - - .. note:: - - This feature requires an Ada Lovelace architecture GPU. Enabling this feature also enables additional - thread-related activities, which can hurt performance. - - This is set by the variable: ``/rtx-transient/dlssg/enabled``. - """ - - enable_dl_denoiser: bool | None = None - """Enables the use of a DL denoiser. - - The DL denoiser can help improve the quality of renders, but comes at a cost of performance. - - This is set by the variable: ``/rtx-transient/dldenoiser/enabled``. - """ - - dlss_mode: Literal[0, 1, 2, 3] | None = None - """For DLSS anti-aliasing, selects the performance/quality tradeoff mode. Default is 0. - - Valid values are: - - * 0 (Performance) - * 1 (Balanced) - * 2 (Quality) - * 3 (Auto) - - This is set by the variable: ``/rtx/post/dlss/execMode``. - """ - - enable_direct_lighting: bool | None = None - """Enable direct light contributions from lights. Default is False. - - This is set by the variable: ``/rtx/directLighting/enabled``. - """ - - samples_per_pixel: int | None = None - """Defines the Direct Lighting samples per pixel. Default is 1. - - A higher value increases the direct lighting quality at the cost of performance. - - This is set by the variable: ``/rtx/directLighting/sampledLighting/samplesPerPixel``. - """ - - enable_shadows: bool | None = None - """Enables shadows at the cost of performance. Defaults to True. - - When disabled, lights will not cast shadows. - - This is set by the variable: ``/rtx/shadows/enabled``. - """ - - enable_ambient_occlusion: bool | None = None - """Enables ambient occlusion at the cost of some performance. Default is False. - - This is set by the variable: ``/rtx/ambientOcclusion/enabled``. - """ - - dome_light_upper_lower_strategy: Literal[0, 3, 4] | None = None - """Selects how to sample the Dome Light. Default is 0. - For more information, refer to the `documentation`_. - - .. _documentation: https://docs.omniverse.nvidia.com/materials-and-rendering/latest/rtx-renderer_common.html#dome-light - - Valid values are: - - * 0: **Image-Based Lighting (IBL)** - Most accurate even for high-frequency Dome Light textures. - Can introduce sampling artifacts in real-time mode. - * 3: **Limited Image-Based Lighting** - Only sampled for reflection and refraction. Fastest, but least - accurate. Good for cases where the Dome Light contributes less than other light sources. - * 4: **Approximated Image-Based Lighting** - Fast and artifacts-free sampling in real-time mode but only - works well with a low-frequency texture (e.g., a sky with no sun disc where the sun is instead a separate - Distant Light). Requires enabling Direct Lighting denoiser. - - This is set by the variable: ``/rtx/domeLight/upperLowerStrategy``. - """ - - carb_settings: dict[str, Any] | None = None - """A general dictionary for users to supply all carb rendering settings with native names. - - The keys of the dictionary can be formatted like a carb setting, .kit file setting, or python variable. - For instance, a key value pair can be ``/rtx/translucency/enabled: False`` (carb), - ``rtx.translucency.enabled: False`` (.kit), or ``rtx_translucency_enabled: False`` (python). - """ - - rendering_mode: Literal["performance", "balanced", "quality"] | None = None - """The rendering mode. - - This behaves the same as the passing the CLI arg ``--rendering_mode`` to an executable script. - """ - - @configclass class SimulationCfg: """Configuration for simulation physics. @@ -238,8 +92,12 @@ class SimulationCfg: a different config (e.g., NewtonManagerCfg) to use a different physics backend. """ - render: RenderCfg = RenderCfg() - """Render settings. Default is RenderCfg().""" + rendering_mode_cfgs: dict[str, RenderingModeCfg] = { + "performance": RenderingModeCfg(rendering_mode_preset="performance"), + "balanced": RenderingModeCfg(rendering_mode_preset="balanced"), + "quality": RenderingModeCfg(rendering_mode_preset="quality"), + } + """Named rendering mode profiles available to visualizers and renderers.""" create_stage_in_memory: bool = False """If stage is first created in memory. Default is False. diff --git a/source/isaaclab/isaaclab/sim/simulation_context.py b/source/isaaclab/isaaclab/sim/simulation_context.py index 91cee7d0be4..902bb185a0d 100644 --- a/source/isaaclab/isaaclab/sim/simulation_context.py +++ b/source/isaaclab/isaaclab/sim/simulation_context.py @@ -7,13 +7,11 @@ import gc import logging -import os import traceback from collections.abc import Iterator from contextlib import contextmanager from typing import Any -import toml import torch from pxr import Gf, Usd, UsdGeom, UsdPhysics, UsdUtils @@ -27,6 +25,7 @@ VisualizerPrebuiltArtifacts, resolve_scene_data_requirements, ) +from isaaclab.rendering_mode.rendering_mode_utils import apply_mode_profile_to_visualizer_cfg from isaaclab.sim.utils import create_new_stage from isaaclab.utils.version import has_kit from isaaclab.visualizers.base_visualizer import BaseVisualizer @@ -164,7 +163,6 @@ def __init__(self, cfg: SimulationCfg | None = None): self.cfg.physics = self._physics self.physics_manager: type[PhysicsManager] = self._physics.class_type self.physics_manager.initialize(self) - self._apply_render_cfg_settings() # Initialize visualizer state (provider/visualizers are created lazily during initialize_visualizers()). self._scene_data_provider: BaseSceneDataProvider | None = None @@ -191,94 +189,16 @@ def __init__(self, cfg: SimulationCfg | None = None): type(self)._instance = self # Mark as valid singleton only after successful init - def _apply_render_cfg_settings(self) -> None: - """Apply render preset and overrides from SimulationCfg.render.""" - # TODO: Refactor render preset + override handling to a dedicated RenderingQualityCfg - # (name subject to change) to keep quality profiles and carb mappings centralized. - render_cfg = getattr(self.cfg, "render", None) - if render_cfg is None: - return - - # Priority: - # 1) CLI/AppLauncher setting if present, 2) SimulationCfg.render.rendering_mode. - rendering_mode = self.get_setting("/isaaclab/rendering/rendering_mode") - if not rendering_mode: - rendering_mode = getattr(render_cfg, "rendering_mode", None) - - if rendering_mode: - supported_rendering_modes = {"performance", "balanced", "quality"} - if rendering_mode not in supported_rendering_modes: - raise ValueError( - f"RenderCfg rendering mode '{rendering_mode}' not in supported modes " - f"{sorted(supported_rendering_modes)}." - ) - - isaaclab_app_exp_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), *[".."] * 4, "apps") - from isaaclab.utils.version import get_isaac_sim_version - - if get_isaac_sim_version().major < 6: - isaaclab_app_exp_path = os.path.join(isaaclab_app_exp_path, "isaacsim_5") - - preset_filename = os.path.join(isaaclab_app_exp_path, f"rendering_modes/{rendering_mode}.kit") - if os.path.exists(preset_filename): - with open(preset_filename) as file: - preset_dict = toml.load(file) - - def _apply_nested(data: dict[str, Any], path: str = "") -> None: - for key, value in data.items(): - key_path = f"{path}/{key}" if path else f"/{key}" - if isinstance(value, dict): - _apply_nested(value, key_path) - else: - self.set_setting(key_path.replace(".", "/"), value) - - _apply_nested(preset_dict) - else: - logger.warning("[SimulationContext] Render preset file not found: %s", preset_filename) - - # RenderCfg fields mapped to setting paths (stored via SettingsManager) - field_to_setting = { - "enable_translucency": "/rtx/translucency/enabled", - "enable_reflections": "/rtx/reflections/enabled", - "enable_global_illumination": "/rtx/indirectDiffuse/enabled", - "enable_dlssg": "/rtx-transient/dlssg/enabled", - "enable_dl_denoiser": "/rtx-transient/dldenoiser/enabled", - "dlss_mode": "/rtx/post/dlss/execMode", - "enable_direct_lighting": "/rtx/directLighting/enabled", - "samples_per_pixel": "/rtx/directLighting/sampledLighting/samplesPerPixel", - "enable_shadows": "/rtx/shadows/enabled", - "enable_ambient_occlusion": "/rtx/ambientOcclusion/enabled", - "dome_light_upper_lower_strategy": "/rtx/domeLight/upperLowerStrategy", - } - - for key, value in vars(render_cfg).items(): - if value is None or key in {"rendering_mode", "carb_settings", "antialiasing_mode"}: - continue - setting_path = field_to_setting.get(key) - if setting_path is not None: - self.set_setting(setting_path, value) - - # Raw overrides from render_cfg (stored via SettingsManager) - extra_settings = getattr(render_cfg, "carb_settings", None) - if extra_settings: - for key, value in extra_settings.items(): - if "_" in key: - path = "/" + key.replace("_", "/") - elif "." in key: - path = "/" + key.replace(".", "/") - else: - path = key - self.set_setting(path, value) - - # Optional anti-aliasing mode via Replicator (best-effort, may use Omniverse APIs) - antialiasing_mode = getattr(render_cfg, "antialiasing_mode", None) - if antialiasing_mode is not None: - try: - import omni.replicator.core as rep - - rep.settings.set_render_rtx_realtime(antialiasing=antialiasing_mode) - except Exception: - pass + def _apply_mode_profile_to_visualizer_cfg(self, visualizer_cfg: Any) -> None: + """Apply resolved rendering-mode profile to a visualizer config.""" + mode_cfgs = self.cfg.rendering_mode_cfgs + apply_mode_profile_to_visualizer_cfg( + self.get_setting, + self.set_setting, + visualizer_cfg, + mode_cfgs, + logger, + ) def _init_usd_physics_scene(self) -> None: """Create and configure the USD physics scene.""" @@ -561,6 +481,7 @@ def initialize_visualizers(self) -> None: for cfg in visualizer_cfgs: try: + self._apply_mode_profile_to_visualizer_cfg(cfg) visualizer = cfg.create_visualizer() visualizer.initialize(self._scene_data_provider) self._visualizers.append(visualizer) diff --git a/source/isaaclab/isaaclab/visualizers/visualizer_cfg.py b/source/isaaclab/isaaclab/visualizers/visualizer_cfg.py index a96e3c04d2b..d344f325ebc 100644 --- a/source/isaaclab/isaaclab/visualizers/visualizer_cfg.py +++ b/source/isaaclab/isaaclab/visualizers/visualizer_cfg.py @@ -59,7 +59,13 @@ class VisualizerCfg: """If env_filter_mode='env_ids', only these env indices are shown. This improves performance, particularly for large-scale training, by reducing scene updates sent to visualizers. - Note, OV visualizer only applies a cosmetic visibility toggle (no performance gain). + Note, the Kit visualizer only applies a cosmetic visibility toggle (no performance gain). + """ + + rendering_mode: str | None = None + """Name of the rendering mode profile for selecting rendering settings. + + Set to None by default, which uses the native rendering settings of the workflow. """ def get_visualizer_type(self) -> str | None: diff --git a/source/isaaclab/test/rendering/test_rendering_mode.py b/source/isaaclab/test/rendering/test_rendering_mode.py new file mode 100644 index 00000000000..ef595ce0e8f --- /dev/null +++ b/source/isaaclab/test/rendering/test_rendering_mode.py @@ -0,0 +1,219 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import logging + +import pytest + +from isaaclab.renderers.renderer_cfg import RendererCfg +from isaaclab.rendering_mode import RenderingModeCfg +from isaaclab.rendering_mode.rendering_mode_utils import ( + apply_mode_profile_to_renderer_cfg, + resolve_effective_rendering_mode_name, +) + + +@pytest.fixture(scope="module") +def simulation_app(): + """Launch Kit once for Isaac Sim tests in this module (must run before any ``pxr`` import).""" + from isaaclab.app import AppLauncher + + return AppLauncher(headless=True, enable_cameras=True).app + + +# --------------------------------------------------------------------------- +# Offline: resolution / gating (no live Kit session) +# --------------------------------------------------------------------------- + + +class _FakeSettings: + """Minimal carb settings view for CLI explicit + rendering_mode paths.""" + + def __init__(self, explicit: bool, mode): + self._data: dict[str, object] = { + "/isaaclab/rendering/rendering_mode/explicit": explicit, + "/isaaclab/rendering/rendering_mode/profile": mode, + } + + def get(self, key: str): + return self._data.get(key) + + +def test_cli_explicit_rendering_mode_overrides_renderer_cfg(): + """CLI explicit flag should win over ``RendererCfg.rendering_mode`` (Kit RTX path).""" + r_cfg = RendererCfg(renderer_type="isaac_rtx", rendering_mode="quality") + settings = _FakeSettings(explicit=True, mode="performance") + assert resolve_effective_rendering_mode_name(settings.get, r_cfg) == "performance" + + +def test_apply_rtx_profile_skips_non_rtx_renderer_backend(): + """Only default / isaac_rtx / rtx renderers receive ``SimulationCfg.rendering_mode_cfgs`` RTX applies.""" + recorded: list[tuple[str, object]] = [] + + def get_setting(key: str): + return _FakeSettings(explicit=False, mode="").get(key) + + def set_setting(name: str, value: object) -> None: + recorded.append((name, value)) + + r_cfg = RendererCfg(renderer_type="newton_warp", rendering_mode="performance") + apply_mode_profile_to_renderer_cfg( + get_setting, + set_setting, + r_cfg, + {"performance": RenderingModeCfg(rendering_mode_preset="performance")}, + logger=logging.getLogger(__name__), + ) + assert recorded == [] + + +# --------------------------------------------------------------------------- +# Isaac Sim: presets and overrides via visualizer and via RTX camera renderer +# --------------------------------------------------------------------------- + + +@pytest.mark.isaacsim_ci +@pytest.mark.usefixtures("simulation_app") +def test_rendering_mode_presets_apply_via_visualizer(): + """Built-in presets + ``kit_*`` overrides should propagate to carb via Kit visualizer init.""" + from isaaclab_visualizers.kit import KitVisualizerCfg + + from isaaclab.app.settings_manager import get_settings_manager + from isaaclab.rendering_mode import get_rendering_mode_preset + from isaaclab.sim.simulation_cfg import SimulationCfg + from isaaclab.sim.simulation_context import SimulationContext + + dlss_override = 3 + + for mode_name in ["performance", "balanced", "quality"]: + SimulationContext.clear_instance() + preset_dict = get_rendering_mode_preset(mode_name) + profile_name = f"profile_{mode_name}" + + cfg = SimulationCfg( + rendering_mode_cfgs={ + profile_name: RenderingModeCfg( + rendering_mode_preset=mode_name, + kit_dlss_mode=dlss_override, + ) + }, + visualizer_cfgs=KitVisualizerCfg(rendering_mode=profile_name), + ) + sim = SimulationContext(cfg) + sim.reset() + + settings = get_settings_manager() + for key, val in preset_dict.items(): + setting_name = key if key.startswith("/") else "/" + key.replace(".", "/") + expected = dlss_override if setting_name == "/rtx/post/dlss/execMode" else val + assert settings.get(setting_name) == expected, ( + f"Mismatch for '{setting_name}' in mode '{mode_name}': " + f"expected {expected!r}, got {settings.get(setting_name)!r}" + ) + + SimulationContext.clear_instance() + + +@pytest.mark.isaacsim_ci +@pytest.mark.usefixtures("simulation_app") +def test_rendering_mode_kit_field_overrides_via_visualizer(): + """Explicit ``RenderingModeCfg`` fields should map to carb when the Kit visualizer applies the profile.""" + from isaaclab_visualizers.kit import KitVisualizerCfg + + from isaaclab.sim.simulation_cfg import SimulationCfg + from isaaclab.sim.simulation_context import SimulationContext + + mode_cfg = RenderingModeCfg( + kit_enable_translucency=True, + kit_enable_reflections=True, + kit_enable_global_illumination=True, + kit_antialiasing_mode="DLAA", + kit_enable_dlssg=True, + kit_enable_dl_denoiser=True, + kit_dlss_mode=0, + kit_enable_direct_lighting=True, + kit_samples_per_pixel=4, + kit_enable_shadows=True, + kit_enable_ambient_occlusion=True, + ) + cfg = SimulationCfg( + rendering_mode_cfgs={"custom": mode_cfg}, + visualizer_cfgs=KitVisualizerCfg(rendering_mode="custom"), + ) + sim = SimulationContext(cfg) + sim.reset() + + assert sim.get_setting("/rtx/translucency/enabled") is True + assert sim.get_setting("/rtx/reflections/enabled") is True + assert sim.get_setting("/rtx/indirectDiffuse/enabled") is True + assert sim.get_setting("/rtx-transient/dlssg/enabled") is True + assert sim.get_setting("/rtx-transient/dldenoiser/enabled") is True + assert sim.get_setting("/rtx/post/dlss/execMode") == 0 + assert sim.get_setting("/rtx/directLighting/enabled") is True + assert sim.get_setting("/rtx/directLighting/sampledLighting/samplesPerPixel") == 4 + assert sim.get_setting("/rtx/shadows/enabled") is True + assert sim.get_setting("/rtx/ambientOcclusion/enabled") is True + + SimulationContext.clear_instance() + + +@pytest.mark.isaacsim_ci +@pytest.mark.usefixtures("simulation_app") +def test_rendering_mode_kit_field_overrides_via_camera_renderer(): + """Same ``RenderingModeCfg`` profile should apply when a Kit RTX camera initializes (renderer path).""" + from isaaclab_physx.renderers import IsaacRtxRendererCfg + + import isaaclab.sim as sim_utils + from isaaclab.sensors.camera import Camera, CameraCfg + from isaaclab.sim.simulation_cfg import SimulationCfg + from isaaclab.sim.simulation_context import SimulationContext + + SimulationContext.clear_instance() + sim_utils.create_new_stage() + cfg_ground = sim_utils.GroundPlaneCfg() + cfg_ground.func("/World/defaultGroundPlane", cfg_ground) + + mode_cfg = RenderingModeCfg( + kit_enable_translucency=True, + kit_enable_reflections=True, + kit_enable_global_illumination=True, + kit_dlss_mode=0, + kit_enable_direct_lighting=True, + kit_samples_per_pixel=4, + kit_enable_shadows=True, + kit_enable_ambient_occlusion=True, + ) + sim_cfg = SimulationCfg( + dt=0.01, + rendering_mode_cfgs={"cam_profile": mode_cfg}, + ) + sim = SimulationContext(sim_cfg) + sim_utils.update_stage() + + camera_cfg = CameraCfg( + height=64, + width=64, + prim_path="/World/Camera", + update_period=0, + data_types=["distance_to_image_plane"], + spawn=sim_utils.PinholeCameraCfg( + focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 1.0e5) + ), + renderer_cfg=IsaacRtxRendererCfg(rendering_mode="cam_profile"), + ) + camera = Camera(camera_cfg) + sim.reset() + assert camera.is_initialized + + assert sim.get_setting("/rtx/translucency/enabled") is True + assert sim.get_setting("/rtx/reflections/enabled") is True + assert sim.get_setting("/rtx/indirectDiffuse/enabled") is True + assert sim.get_setting("/rtx/post/dlss/execMode") == 0 + assert sim.get_setting("/rtx/directLighting/enabled") is True + assert sim.get_setting("/rtx/directLighting/sampledLighting/samplesPerPixel") == 4 + assert sim.get_setting("/rtx/shadows/enabled") is True + assert sim.get_setting("/rtx/ambientOcclusion/enabled") is True + + SimulationContext.clear_instance() diff --git a/source/isaaclab/test/sim/test_simulation_render_config.py b/source/isaaclab/test/sim/test_simulation_render_config.py deleted file mode 100644 index e5ad4274d18..00000000000 --- a/source/isaaclab/test/sim/test_simulation_render_config.py +++ /dev/null @@ -1,206 +0,0 @@ -# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). -# All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause - - -"""Launch Isaac Sim Simulator first.""" - -from isaaclab.app import AppLauncher - -# launch omniverse app -simulation_app = AppLauncher(headless=True, enable_cameras=True).app - - -"""Rest everything follows.""" - -import os - -import flatdict -import pytest -import toml - -from isaaclab.app.settings_manager import get_settings_manager -from isaaclab.sim.simulation_cfg import RenderCfg, SimulationCfg -from isaaclab.sim.simulation_context import SimulationContext -from isaaclab.utils.version import get_isaac_sim_version - - -@pytest.mark.skip(reason="Timeline not stopped") -@pytest.mark.isaacsim_ci -def test_render_cfg(): - """Test that the simulation context is created with the correct render cfg.""" - enable_translucency = True - enable_reflections = True - enable_global_illumination = True - antialiasing_mode = "DLAA" - enable_dlssg = True - enable_dl_denoiser = True - dlss_mode = 0 - enable_direct_lighting = True - samples_per_pixel = 4 - enable_shadows = True - enable_ambient_occlusion = True - - render_cfg = RenderCfg( - enable_translucency=enable_translucency, - enable_reflections=enable_reflections, - enable_global_illumination=enable_global_illumination, - antialiasing_mode=antialiasing_mode, - enable_dlssg=enable_dlssg, - dlss_mode=dlss_mode, - enable_dl_denoiser=enable_dl_denoiser, - enable_direct_lighting=enable_direct_lighting, - samples_per_pixel=samples_per_pixel, - enable_shadows=enable_shadows, - enable_ambient_occlusion=enable_ambient_occlusion, - ) - - cfg = SimulationCfg(render=render_cfg) - - # FIXME: when running all tests, the timeline is not stopped, force stop it here but also that does not the timeline - # omni.timeline.get_timeline_interface().stop() - - sim = SimulationContext(cfg) - - assert sim.cfg.render.enable_translucency == enable_translucency - assert sim.cfg.render.enable_reflections == enable_reflections - assert sim.cfg.render.enable_global_illumination == enable_global_illumination - assert sim.cfg.render.antialiasing_mode == antialiasing_mode - assert sim.cfg.render.enable_dlssg == enable_dlssg - assert sim.cfg.render.dlss_mode == dlss_mode - assert sim.cfg.render.enable_dl_denoiser == enable_dl_denoiser - assert sim.cfg.render.enable_direct_lighting == enable_direct_lighting - assert sim.cfg.render.samples_per_pixel == samples_per_pixel - assert sim.cfg.render.enable_shadows == enable_shadows - assert sim.cfg.render.enable_ambient_occlusion == enable_ambient_occlusion - - assert sim.get_setting("/rtx/translucency/enabled") == sim.cfg.render.enable_translucency - assert sim.get_setting("/rtx/reflections/enabled") == sim.cfg.render.enable_reflections - assert sim.get_setting("/rtx/indirectDiffuse/enabled") == sim.cfg.render.enable_global_illumination - assert sim.get_setting("/rtx-transient/dlssg/enabled") == sim.cfg.render.enable_dlssg - assert sim.get_setting("/rtx-transient/dldenoiser/enabled") == sim.cfg.render.enable_dl_denoiser - assert sim.get_setting("/rtx/post/dlss/execMode") == sim.cfg.render.dlss_mode - assert sim.get_setting("/rtx/directLighting/enabled") == sim.cfg.render.enable_direct_lighting - assert sim.get_setting("/rtx/directLighting/sampledLighting/samplesPerPixel") == sim.cfg.render.samples_per_pixel - assert sim.get_setting("/rtx/shadows/enabled") == sim.cfg.render.enable_shadows - assert sim.get_setting("/rtx/ambientOcclusion/enabled") == sim.cfg.render.enable_ambient_occlusion - assert sim.get_setting("/rtx/post/aa/op") == 4 # dlss = 3, dlaa=4 - - -@pytest.mark.isaacsim_ci -def test_render_cfg_presets(): - """Test that the simulation context is created with the correct render cfg preset with overrides.""" - - # carb setting dictionary overrides - carb_settings = {"/rtx/raytracing/subpixel/mode": 3, "/rtx/pathtracing/maxSamplesPerLaunch": 999999} - # user-friendly setting overrides - dlss_mode = ("/rtx/post/dlss/execMode", 5) - - rendering_modes = ["performance", "balanced", "quality"] - - for rendering_mode in rendering_modes: - # Clear any existing simulation context before creating a new one - SimulationContext.clear_instance() - - # grab isaac lab apps path - isaaclab_app_exp_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), *[".."] * 4, "apps") - # for Isaac Sim 5 compatibility, we use the 5 rendering mode app files in a different folder - if get_isaac_sim_version().major < 6: - isaaclab_app_exp_path = os.path.join(isaaclab_app_exp_path, "isaacsim_5") - - # grab preset settings - preset_filename = os.path.join(isaaclab_app_exp_path, f"rendering_modes/{rendering_mode}.kit") - with open(preset_filename) as file: - preset_dict = toml.load(file) - preset_dict = dict(flatdict.FlatDict(preset_dict, delimiter=".")) - - render_cfg = RenderCfg( - rendering_mode=rendering_mode, - dlss_mode=dlss_mode[1], - carb_settings=carb_settings, - ) - - cfg = SimulationCfg(render=render_cfg) - - SimulationContext(cfg) - - settings = get_settings_manager() - for key, val in preset_dict.items(): - setting_name = "/" + key.replace(".", "/") # convert to setting path format - - if setting_name in carb_settings: - setting_gt = carb_settings[setting_name] - elif setting_name == dlss_mode[0]: - setting_gt = dlss_mode[1] - else: - setting_gt = val - - setting_val = settings.get(setting_name) - - assert setting_gt == setting_val, ( - f"Mismatch for '{setting_name}' in mode '{rendering_mode}': " - f"expected {setting_gt!r}, got {setting_val!r}" - ) - - # Clean up after the test - SimulationContext.clear_instance() - - -@pytest.mark.skip(reason="Timeline not stopped") -@pytest.mark.isaacsim_ci -def test_render_cfg_defaults(): - """Test that the simulation context is created with the correct render cfg.""" - enable_translucency = False - enable_reflections = False - enable_global_illumination = False - antialiasing_mode = "DLSS" - enable_dlssg = False - enable_dl_denoiser = False - dlss_mode = 2 - enable_direct_lighting = False - samples_per_pixel = 1 - enable_shadows = False - enable_ambient_occlusion = False - - render_cfg = RenderCfg( - enable_translucency=enable_translucency, - enable_reflections=enable_reflections, - enable_global_illumination=enable_global_illumination, - antialiasing_mode=antialiasing_mode, - enable_dlssg=enable_dlssg, - enable_dl_denoiser=enable_dl_denoiser, - dlss_mode=dlss_mode, - enable_direct_lighting=enable_direct_lighting, - samples_per_pixel=samples_per_pixel, - enable_shadows=enable_shadows, - enable_ambient_occlusion=enable_ambient_occlusion, - ) - - cfg = SimulationCfg(render=render_cfg) - - sim = SimulationContext(cfg) - - assert sim.cfg.render.enable_translucency == enable_translucency - assert sim.cfg.render.enable_reflections == enable_reflections - assert sim.cfg.render.enable_global_illumination == enable_global_illumination - assert sim.cfg.render.antialiasing_mode == antialiasing_mode - assert sim.cfg.render.enable_dlssg == enable_dlssg - assert sim.cfg.render.enable_dl_denoiser == enable_dl_denoiser - assert sim.cfg.render.dlss_mode == dlss_mode - assert sim.cfg.render.enable_direct_lighting == enable_direct_lighting - assert sim.cfg.render.samples_per_pixel == samples_per_pixel - assert sim.cfg.render.enable_shadows == enable_shadows - assert sim.cfg.render.enable_ambient_occlusion == enable_ambient_occlusion - - assert sim.get_setting("/rtx/translucency/enabled") == sim.cfg.render.enable_translucency - assert sim.get_setting("/rtx/reflections/enabled") == sim.cfg.render.enable_reflections - assert sim.get_setting("/rtx/indirectDiffuse/enabled") == sim.cfg.render.enable_global_illumination - assert sim.get_setting("/rtx-transient/dlssg/enabled") == sim.cfg.render.enable_dlssg - assert sim.get_setting("/rtx-transient/dldenoiser/enabled") == sim.cfg.render.enable_dl_denoiser - assert sim.get_setting("/rtx/post/dlss/execMode") == sim.cfg.render.dlss_mode - assert sim.get_setting("/rtx/directLighting/enabled") == sim.cfg.render.enable_direct_lighting - assert sim.get_setting("/rtx/directLighting/sampledLighting/samplesPerPixel") == sim.cfg.render.samples_per_pixel - assert sim.get_setting("/rtx/shadows/enabled") == sim.cfg.render.enable_shadows - assert sim.get_setting("/rtx/ambientOcclusion/enabled") == sim.cfg.render.enable_ambient_occlusion - assert sim.get_setting("/rtx/post/aa/op") == 3 # dlss = 3, dlaa=4 diff --git a/source/isaaclab_physx/docs/CHANGELOG.rst b/source/isaaclab_physx/docs/CHANGELOG.rst index 6ea71fa755c..65d5047c98d 100644 --- a/source/isaaclab_physx/docs/CHANGELOG.rst +++ b/source/isaaclab_physx/docs/CHANGELOG.rst @@ -1,6 +1,18 @@ Changelog --------- +0.5.14 (2026-04-08) +~~~~~~~~~~~~~~~~~~~ + +Changed +^^^^^^^ + +* Moved built-in RTX rendering mode preset tables (``performance`` / ``balanced`` / ``quality``) from the core + ``isaaclab`` package into :mod:`isaaclab_physx.rendering.rtx_rendering_mode_presets`. The public + :func:`isaaclab.rendering_mode.get_rendering_mode_preset` API still resolves these values when ``isaaclab_physx`` + is installed. + + 0.5.13 (2026-03-25) ~~~~~~~~~~~~~~~~~~~ diff --git a/source/isaaclab_physx/isaaclab_physx/rendering/__init__.py b/source/isaaclab_physx/isaaclab_physx/rendering/__init__.py new file mode 100644 index 00000000000..bd8e7df0725 --- /dev/null +++ b/source/isaaclab_physx/isaaclab_physx/rendering/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""RTX rendering resources for the PhysX / Isaac Sim stack.""" + +from .rtx_rendering_mode_presets import get_builtin_rtx_rendering_mode_preset + +__all__ = ["get_builtin_rtx_rendering_mode_preset"] diff --git a/source/isaaclab_physx/isaaclab_physx/rendering/rtx_rendering_mode_presets.py b/source/isaaclab_physx/isaaclab_physx/rendering/rtx_rendering_mode_presets.py new file mode 100644 index 00000000000..bed756586e9 --- /dev/null +++ b/source/isaaclab_physx/isaaclab_physx/rendering/rtx_rendering_mode_presets.py @@ -0,0 +1,88 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Built-in RTX rendering mode presets (performance, balanced, quality). + +Carb path values align with Isaac Lab application rendering profiles (e.g. under ``apps/``) where applicable. +These baselines are used by :class:`~isaaclab.rendering_mode.RenderingModeCfg` and +``isaaclab.rendering_mode`` helpers for Kit viewport and Isaac RTX camera renderers. +""" + +from __future__ import annotations + +from copy import deepcopy +from typing import Any + +_BUILTIN_RTX_RENDERING_MODE_PRESETS: dict[str, dict[str, Any]] = { + "performance": { + "/rtx/rtpt/cached/enabled": False, + "/rtx/rtpt/lightcache/cached/enabled": False, + "/rtx/rtpt/translucency/virtualMotion/enabled": False, + "/rtx/rtpt/maxBounces": 2, + "/rtx/rtpt/splitGlass": False, + "/rtx/rtpt/splitClearcoat": False, + "/rtx/rtpt/splitRoughReflection": True, + "/rtx/rtpt/useAmbientOcclusionForAmbientLight": False, + "/rtx/sceneDb/ambientLightIntensity": 1.0, + "/rtx/shadows/enabled": True, + "/rtx/domeLight/upperLowerStrategy": 3, + "/rtx/ambientOcclusion/enabled": False, + "/rtx/ambientOcclusion/denoiserMode": 1, + "/rtx/raytracing/subpixel/mode": 0, + "/rtx/raytracing/cached/enabled": False, + "/rtx-transient/dlssg/enabled": False, + "/rtx-transient/dldenoiser/enabled": False, + "/rtx/post/dlss/execMode": 1, + "/rtx/pathtracing/maxSamplesPerLaunch": 1_000_000, + "/rtx/viewTile/limit": 1_000_000, + }, + "balanced": { + "/rtx/rtpt/cached/enabled": False, + "/rtx/rtpt/lightcache/cached/enabled": False, + "/rtx/rtpt/translucency/virtualMotion/enabled": False, + "/rtx/rtpt/maxBounces": 2, + "/rtx/rtpt/splitGlass": False, + "/rtx/rtpt/splitClearcoat": False, + "/rtx/rtpt/splitRoughReflection": True, + "/rtx/rtpt/useAmbientOcclusionForAmbientLight": False, + "/rtx/sceneDb/ambientLightIntensity": 1.0, + "/rtx/shadows/enabled": True, + "/rtx/ambientOcclusion/enabled": False, + "/rtx/ambientOcclusion/denoiserMode": 1, + "/rtx/raytracing/subpixel/mode": 0, + "/rtx/raytracing/cached/enabled": True, + "/rtx-transient/dlssg/enabled": False, + "/rtx-transient/dldenoiser/enabled": True, + "/rtx/post/dlss/execMode": 1, + "/rtx/pathtracing/maxSamplesPerLaunch": 1_000_000, + "/rtx/viewTile/limit": 1_000_000, + }, + "quality": { + "/rtx/rtpt/maxBounces": 3, + "/rtx/rtpt/cached/enabled": False, + "/rtx/rtpt/lightcache/cached/enabled": False, + "/rtx/rtpt/translucency/virtualMotion/enabled": False, + "/rtx/rtpt/splitRoughReflection": True, + "/rtx/rtpt/adaptiveSampling/disocclusion/enabled": True, + "/rtx/rtpt/adaptiveSampling/disocclusion/spp": 4, + "/rtx/sceneDb/ambientLightIntensity": 1.0, + "/rtx/shadows/enabled": True, + "/rtx/ambientOcclusion/enabled": True, + "/rtx/ambientOcclusion/denoiserMode": 0, + "/rtx/raytracing/subpixel/mode": 1, + "/rtx/raytracing/cached/enabled": True, + "/rtx-transient/dlssg/enabled": False, + "/rtx/post/dlss/execMode": 2, + "/rtx/pathtracing/maxSamplesPerLaunch": 1_000_000, + "/rtx/viewTile/limit": 1_000_000, + }, +} + + +def get_builtin_rtx_rendering_mode_preset(preset_name: str) -> dict[str, Any]: + """Return a deep copy of the requested built-in RTX rendering mode preset.""" + if preset_name not in {"performance", "balanced", "quality"}: + raise ValueError(f"Unknown preset '{preset_name}'.") + return deepcopy(_BUILTIN_RTX_RENDERING_MODE_PRESETS[preset_name]) diff --git a/source/isaaclab_physx/setup.py b/source/isaaclab_physx/setup.py index d8e1b731b4b..3b3d434f3eb 100644 --- a/source/isaaclab_physx/setup.py +++ b/source/isaaclab_physx/setup.py @@ -47,6 +47,7 @@ "isaaclab_physx.cloner", "isaaclab_physx.physics", "isaaclab_physx.renderers", + "isaaclab_physx.rendering", "isaaclab_physx.scene_data_providers", "isaaclab_physx.sensors", "isaaclab_physx.sensors.contact_sensor", diff --git a/source/isaaclab_physx/test/rendering/test_rtx_rendering_mode_presets.py b/source/isaaclab_physx/test/rendering/test_rtx_rendering_mode_presets.py new file mode 100644 index 00000000000..9bdb4e27b0f --- /dev/null +++ b/source/isaaclab_physx/test/rendering/test_rtx_rendering_mode_presets.py @@ -0,0 +1,24 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +"""Tests for built-in RTX rendering mode preset data.""" + +from __future__ import annotations + +import pytest + +from isaaclab_physx.rendering.rtx_rendering_mode_presets import get_builtin_rtx_rendering_mode_preset + + +def test_builtin_rtx_presets_cover_three_modes(): + for name in ("performance", "balanced", "quality"): + d = get_builtin_rtx_rendering_mode_preset(name) + assert isinstance(d, dict) + assert "/rtx/shadows/enabled" in d + + +def test_unknown_preset_raises(): + with pytest.raises(ValueError, match="Unknown preset"): + get_builtin_rtx_rendering_mode_preset("not_a_mode") diff --git a/source/isaaclab_visualizers/isaaclab_visualizers/kit/kit_visualizer_cfg.py b/source/isaaclab_visualizers/isaaclab_visualizers/kit/kit_visualizer_cfg.py index 88112a6f20b..cd1d042b58b 100644 --- a/source/isaaclab_visualizers/isaaclab_visualizers/kit/kit_visualizer_cfg.py +++ b/source/isaaclab_visualizers/isaaclab_visualizers/kit/kit_visualizer_cfg.py @@ -33,3 +33,13 @@ class KitVisualizerCfg(VisualizerCfg): window_height: int = 720 """Viewport height in pixels.""" + + rendering_mode: str | None = "performance" + """Kit/RTX profile name from :attr:`~isaaclab.sim.SimulationCfg.rendering_mode_cfgs` (default ``performance``). + + Built-in ``performance`` / ``balanced`` / ``quality`` baselines are defined in + :mod:`isaaclab_physx.rendering.rtx_rendering_mode_presets` and applied through the same mechanism as RTX camera + renderers; no separate copy lives under ``isaaclab_visualizers``. + + Set to ``None`` to skip applying a named profile (USD / Kit defaults). + """ diff --git a/source/isaaclab_visualizers/isaaclab_visualizers/newton/newton_visualizer_cfg.py b/source/isaaclab_visualizers/isaaclab_visualizers/newton/newton_visualizer_cfg.py index b89e0a2d547..cfe0973dc2a 100644 --- a/source/isaaclab_visualizers/isaaclab_visualizers/newton/newton_visualizer_cfg.py +++ b/source/isaaclab_visualizers/isaaclab_visualizers/newton/newton_visualizer_cfg.py @@ -53,19 +53,19 @@ class NewtonVisualizerCfg(VisualizerCfg): """Show center of mass visualization.""" enable_shadows: bool = True - """Enable shadow rendering.""" + """Enable shadow rendering in the Newton GL viewer.""" enable_sky: bool = True - """Enable sky rendering.""" + """Enable sky gradient rendering.""" enable_wireframe: bool = False - """Enable wireframe rendering.""" + """Enable wireframe overlay.""" sky_upper_color: tuple[float, float, float] = (0.2, 0.4, 0.6) - """Sky upper color RGB [0,1].""" + """Upper sky gradient color (RGB).""" sky_lower_color: tuple[float, float, float] = (0.5, 0.6, 0.7) - """Sky lower color RGB [0,1].""" + """Lower sky gradient color (RGB).""" light_color: tuple[float, float, float] = (1.0, 1.0, 1.0) - """Light color RGB [0,1].""" + """Directional light color (RGB).""" diff --git a/source/isaaclab_visualizers/setup.py b/source/isaaclab_visualizers/setup.py index 5b0c24cffa6..729b9a9e8cc 100644 --- a/source/isaaclab_visualizers/setup.py +++ b/source/isaaclab_visualizers/setup.py @@ -28,6 +28,8 @@ "viser": [ "newton @ git+https://github.com/newton-physics/newton.git@2684d75bfa4bb8b058a93b81c458a74b7701c997", "viser>=1.0.16", + # Viser requires a current websockets API; Isaac Sim's pip_prebundle may ship an older copy. + "websockets>=13.0", ], } diff --git a/tools/test_settings.py b/tools/test_settings.py index 12d4bf5bcf9..65e1e574b29 100644 --- a/tools/test_settings.py +++ b/tools/test_settings.py @@ -39,7 +39,7 @@ "test_teleop_environments_with_stage_in_memory.py": 5000, "test_cartpole_showcase_environments.py": 5000, "test_cartpole_showcase_environments_with_stage_in_memory.py": 5000, - "test_simulation_render_config.py": 1000, + "test_rendering_mode.py": 1000, "test_operational_space.py": 1000, "test_non_headless_launch.py": 1000, # This test launches the app in non-headless mode and starts simulation "test_rl_games_wrapper.py": 1000,