diff --git a/apps/isaacsim_5/rendering_modes/balanced.kit b/apps/isaacsim_5/rendering_modes/balanced.kit deleted file mode 100644 index ee92625fd7e..00000000000 --- a/apps/isaacsim_5/rendering_modes/balanced.kit +++ /dev/null @@ -1,36 +0,0 @@ -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.sceneDb.ambientLightIntensity = 1.0 - -rtx.shadows.enabled = true - -rtx.indirectDiffuse.enabled = false -rtx.indirectDiffuse.denoiser.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/isaacsim_5/rendering_modes/performance.kit b/apps/isaacsim_5/rendering_modes/performance.kit deleted file mode 100644 index 3cfe6e8c0e2..00000000000 --- a/apps/isaacsim_5/rendering_modes/performance.kit +++ /dev/null @@ -1,35 +0,0 @@ -rtx.translucency.enabled = false - -rtx.reflections.enabled = false -rtx.reflections.denoiser.enabled = false - -rtx.directLighting.sampledLighting.denoisingTechnique = 0 -rtx.directLighting.sampledLighting.enabled = false - -rtx.sceneDb.ambientLightIntensity = 1.0 - -rtx.shadows.enabled = true - -rtx.indirectDiffuse.enabled = false -rtx.indirectDiffuse.denoiser.enabled = false - -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/isaacsim_5/rendering_modes/quality.kit b/apps/isaacsim_5/rendering_modes/quality.kit deleted file mode 100644 index 8e966ddfd3b..00000000000 --- a/apps/isaacsim_5/rendering_modes/quality.kit +++ /dev/null @@ -1,36 +0,0 @@ -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.sceneDb.ambientLightIntensity = 1.0 - -rtx.shadows.enabled = true - -rtx.indirectDiffuse.enabled = true -rtx.indirectDiffuse.denoiser.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 -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/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 423d3df4ef2..670784d1c96 100644 --- a/docs/source/how-to/configure_rendering.rst +++ b/docs/source/how-to/configure_rendering.rst @@ -1,37 +1,45 @@ Configuring Rendering Settings ============================== -Isaac Lab offers 3 preset rendering modes: performance, balanced, and quality. -You can select a mode via a command line argument or from within a script, and customize settings as needed. -Adjust and fine-tune rendering to achieve the ideal balance for your workflow. +Isaac Lab offers three preset rendering mode profiles: ``performance``, ``balanced``, and ``quality``. +You can select a profile via CLI or from script config, then override specific Kit/Newton settings as needed. -Selecting a Rendering Mode --------------------------- +Selecting a Rendering Mode Profile +---------------------------------- -Rendering modes can be selected in 2 ways. +Rendering mode can be selected in two ways: -1. using the ``rendering_mode`` input class argument in :class:`~sim.RenderCfg` +1. Set the visualizer profile selector field ``rendering_mode``, which selects an entry from + :attr:`~sim.SimulationCfg.rendering_mode_cfgs`. .. code-block:: python - # 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") + import isaaclab.sim as sim_utils + from isaaclab_physx.visualizers import KitVisualizerCfg -2. using the ``--rendering_mode`` CLI argument, which takes precedence over the ``rendering_mode`` argument in :class:`~sim.RenderCfg`. + sim_cfg = sim_utils.SimulationCfg( + visualizer_cfgs=[ + KitVisualizerCfg( + rendering_mode="performance", + ), + ], + ) - .. code-block:: bash +2. Use the ``--rendering_mode`` CLI argument, which takes precedence over + ``visualizer_cfg.rendering_mode``. - ./isaaclab.sh -p scripts/tutorials/00_sim/set_rendering_mode.py --rendering_mode {performance/balanced/quality} + .. code-block:: bash + ./isaaclab.sh -p scripts/tutorials/00_sim/set_rendering_mode.py --rendering_mode {performance/balanced/quality} -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. +Notes: +* If ``rendering_mode=None`` for a visualizer, Isaac Lab does not apply rendering overrides + for that visualizer, and backend/native defaults (for Kit, USD-authored settings) are used. +* ``--rendering_mode`` is the supported CLI entry point. 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 @@ -54,117 +62,74 @@ To help assess rendering, the example scene includes some reflections, transluce Overwriting Specific Rendering Settings --------------------------------------- -Preset rendering settings can be overwritten via the :class:`~sim.RenderCfg` class. +Preset rendering settings can be overwritten via :class:`~sim.RenderingModeCfg`. -There are 2 ways to provide settings that overwrite presets. +There are two ways to provide settings that overwrite presets: -1. :class:`~sim.RenderCfg` supports overwriting specific settings via user-friendly setting names that map to underlying RTX settings. - For example: +1. :class:`~sim.RenderingModeCfg` supports overwriting specific settings via explicit + ``kit_*`` fields that map to underlying RTX settings. .. code-block:: python - 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 + import isaaclab.sim as sim_utils + + mode_cfg = sim_utils.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 RTX documentation can be found here - https://docs.omniverse.nvidia.com/materials-and-rendering/latest/rtx-renderer.html. - - An example usage of ``carb_settings``. - - .. 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, - } - ) - + +------------------------------------+-------------------------------------------------------------------------+ + | 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. | + +------------------------------------+-------------------------------------------------------------------------+ + +2. Customize or add named profiles in :attr:`~sim.SimulationCfg.rendering_mode_cfgs`, + then select them from per-visualizer profile selector fields (``rendering_mode``). Current Limitations ------------------- -For performance reasons, we default to using DLSS for denoising, which generally provides better performance. -This may result in renders of lower quality, which may be especially evident at lower resolutions. -Due to this, we recommend using per-tile or per-camera resolution of at least 100 x 100. -For renders at lower resolutions, we advice setting the ``antialiasing_mode`` attribute in :class:`~sim.RenderCfg` to -``DLAA``, and also potentially enabling ``enable_dl_denoiser``. Both of these settings should help improve render -quality, but also comes at a cost of performance. Additional rendering parameters can also be specified in :class:`~sim.RenderCfg`. - - -If you observe visual artifacts such as ghosting or disocclusion issues when using tiled rendering, you can try -adjusting the ``disocclusionScale`` parameter. This setting controls how aggressively the renderer handles -areas that become newly visible between frames: - -.. code-block:: python - - render_cfg = sim_utils.RenderCfg( - carb_settings={ - "/rtx/aovConverter/disocclusionScale": 10000, - } - ) +For performance reasons, DLSS-centric settings are commonly used by default. +At lower resolutions, quality artifacts may be more visible. +For low-resolution renders, consider: -.. note:: +* ``kit_antialiasing_mode="DLAA"`` +* ``kit_enable_dl_denoiser=True`` +<<<<<<< mtrepte/add_rendering_quality_cfg +in :class:`~sim.RenderingModeCfg`. These can improve quality at a performance cost. +======= This parameter is not commonly exposed as it may have side effects in certain scenarios. Only use it as a last resort if other quality settings do not resolve the visual artifacts. The value can be adjusted to a very high value to reduce disocclusion artifacts. @@ -189,3 +154,4 @@ in **multiple environments**, you must set the following so the renderer uses th With multiple environments, each environment holds its own copy of the scene, increasing device memory use, and environments are rendered one after another, which can substantially slow down rendering. +>>>>>>> develop diff --git a/source/isaaclab/isaaclab/app/app_launcher.py b/source/isaaclab/isaaclab/app/app_launcher.py index e789b629580..9ccc13e5227 100644 --- a/source/isaaclab/isaaclab/app/app_launcher.py +++ b/source/isaaclab/isaaclab/app/app_launcher.py @@ -907,6 +907,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: @@ -915,7 +916,9 @@ 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("/isaaclab/rendering/rendering_mode", rendering_mode) + settings.set_bool("/isaaclab/rendering/rendering_mode/explicit", bool(rendering_mode_explicit)) def _set_animation_recording_settings(self, launcher_args: dict) -> None: """Store animation recording settings in settings.""" diff --git a/source/isaaclab/isaaclab/renderers/__init__.py b/source/isaaclab/isaaclab/renderers/__init__.py index fde1f967fcd..dcda7b01baf 100644 --- a/source/isaaclab/isaaclab/renderers/__init__.py +++ b/source/isaaclab/isaaclab/renderers/__init__.py @@ -3,6 +3,12 @@ # # SPDX-License-Identifier: BSD-3-Clause +<<<<<<< mtrepte/add_rendering_quality_cfg +"""Renderer interfaces and configuration types.""" + +from __future__ import annotations + +======= """Sub-package for renderer configurations and implementations. This sub-package contains configuration classes and implementations for @@ -12,11 +18,15 @@ from __future__ import annotations from .base_renderer import BaseRenderer +>>>>>>> develop from .renderer import Renderer from .renderer_cfg import RendererCfg __all__ = [ +<<<<<<< mtrepte/add_rendering_quality_cfg +======= "BaseRenderer", +>>>>>>> develop "Renderer", "RendererCfg", ] diff --git a/source/isaaclab/isaaclab/renderers/renderer_cfg.py b/source/isaaclab/isaaclab/renderers/renderer_cfg.py index 334fa3f070a..68ca7cbe00d 100644 --- a/source/isaaclab/isaaclab/renderers/renderer_cfg.py +++ b/source/isaaclab/isaaclab/renderers/renderer_cfg.py @@ -3,13 +3,33 @@ # # SPDX-License-Identifier: BSD-3-Clause +<<<<<<< mtrepte/add_rendering_quality_cfg +"""Stub renderer config classes. + +These are intentionally lightweight placeholders so the rendering domain can +stabilize around explicit renderer config names before full implementation. +""" + +from __future__ import annotations +======= """Base configuration for renderers.""" +>>>>>>> develop from isaaclab.utils import configclass @configclass class RendererCfg: +<<<<<<< mtrepte/add_rendering_quality_cfg + """Base configuration for all renderer backends.""" + + renderer_type: str | None = None + """Type identifier (e.g., 'rtx', 'warp'). Must be overridden by subclasses.""" + + rendering_mode: str | None = None + """Name of the rendering mode profile to use with this renderer.""" +======= """Configuration for a renderer.""" renderer_type: str = "default" +>>>>>>> develop diff --git a/source/isaaclab/isaaclab/rendering_mode/__init__.py b/source/isaaclab/isaaclab/rendering_mode/__init__.py new file mode 100644 index 00000000000..da49b16f62a --- /dev/null +++ b/source/isaaclab/isaaclab/rendering_mode/__init__.py @@ -0,0 +1,11 @@ +# 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_kit_rendering_preset + +__all__ = ["RenderingModeCfg", "get_kit_rendering_preset"] 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..717f2129809 --- /dev/null +++ b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_cfg.py @@ -0,0 +1,82 @@ +# 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: + """Shared rendering mode profile for visualizers and renderers. + + This profile keeps backend-specific fields in one place using explicit prefixes: + - 'kit_*' for Omniverse/RTX quality controls + - 'newton_*' for Newton visual quality controls + """ + + rendering_mode_preset: Literal["performance", "balanced", "quality"] | None = None + """Optional built-in preset profile. + + Preset values are defined in 'isaaclab.rendering_mode.rendering_mode_presets'. + """ + + kit_enable_translucency: bool | None = None + """Maps to '/rtx/translucency/enabled'.""" + + kit_enable_reflections: bool | None = None + """Maps to '/rtx/reflections/enabled'.""" + + kit_enable_global_illumination: bool | None = None + """Maps to '/rtx/indirectDiffuse/enabled'.""" + + kit_antialiasing_mode: Literal["Off", "FXAA", "DLSS", "TAA", "DLAA"] | None = None + """Optional anti-aliasing mode applied via Replicator settings helper.""" + + kit_enable_dlssg: bool | None = None + """Maps to '/rtx-transient/dlssg/enabled'.""" + + kit_enable_dl_denoiser: bool | None = None + """Maps to '/rtx-transient/dldenoiser/enabled'.""" + + kit_dlss_mode: Literal[0, 1, 2, 3] | None = None + """Maps to '/rtx/post/dlss/execMode'.""" + + kit_enable_direct_lighting: bool | None = None + """Maps to '/rtx/directLighting/enabled'.""" + + kit_samples_per_pixel: int | None = None + """Maps to '/rtx/directLighting/sampledLighting/samplesPerPixel'.""" + + kit_enable_shadows: bool | None = None + """Maps to '/rtx/shadows/enabled'.""" + + kit_enable_ambient_occlusion: bool | None = None + """Maps to '/rtx/ambientOcclusion/enabled'.""" + + kit_dome_light_upper_lower_strategy: Literal[0, 3, 4] | None = None + """Maps to '/rtx/domeLight/upperLowerStrategy'.""" + + newton_enable_shadows: bool | None = True + """Overrides Newton visualizer shadow rendering.""" + + newton_enable_sky: bool | None = True + """Overrides Newton visualizer sky rendering.""" + + newton_enable_wireframe: bool | None = False + """Overrides Newton visualizer wireframe rendering.""" + + newton_sky_upper_color: tuple[float, float, float] | None = (0.2, 0.4, 0.6) + """Overrides Newton visualizer upper sky color.""" + + newton_sky_lower_color: tuple[float, float, float] | None = (0.5, 0.6, 0.7) + """Overrides Newton visualizer lower sky color.""" + + newton_light_color: tuple[float, float, float] | None = (1.0, 1.0, 1.0) + """Overrides Newton visualizer light color.""" + + # TODO: Consider supporting additional raw backend settings dictionaries. 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..8996e6b7955 --- /dev/null +++ b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_presets.py @@ -0,0 +1,87 @@ +# 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 rendering mode presets for RTX/Kit rendering. + +Presets are sourced from the latest Isaac Lab app rendering profiles (apps/rendering_modes). +""" + +from __future__ import annotations + +from copy import deepcopy +from typing import Any + +# Latest preset values sourced from apps/rendering_modes/*.kit. +_KIT_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": 0, + "/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_kit_rendering_preset(preset_name: str) -> dict[str, Any]: + """Return a deep copy of the requested rendering preset.""" + if preset_name not in {"performance", "balanced", "quality"}: + raise ValueError(f"Unknown preset '{preset_name}'.") + return deepcopy(_KIT_PRESETS[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..ed9229fcf30 --- /dev/null +++ b/source/isaaclab/isaaclab/rendering_mode/rendering_mode_utils.py @@ -0,0 +1,163 @@ +# 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 + +from typing import Any + +from .rendering_mode_cfg import RenderingModeCfg +from .rendering_mode_presets import get_kit_rendering_preset + + +def apply_kit_rendering_preset(set_setting: Any, preset_name: str) -> None: + """Apply a named kit preset via provided setting setter.""" + preset = get_kit_rendering_preset(preset_name) + for key, value in preset.items(): + set_setting(key, value) + + +def apply_kit_rendering_mode_cfg(set_setting: Any, mode_cfg: RenderingModeCfg) -> None: + """Apply kit-specific rendering mode fields.""" + if mode_cfg.rendering_mode_preset: + apply_kit_rendering_preset(set_setting, mode_cfg.rendering_mode_preset) + + field_to_carb = { + "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", + } + for field_name, carb_key in field_to_carb.items(): + value = getattr(mode_cfg, field_name, None) + if value is not None: + set_setting(carb_key, value) + + if mode_cfg.kit_antialiasing_mode is not None: + try: + import omni.replicator.core as rep + + rep.settings.set_render_rtx_realtime(antialiasing=mode_cfg.kit_antialiasing_mode) + except Exception: + pass + + +def apply_newton_mode_cfg_to_visualizer_cfg(visualizer_cfg: Any, mode_cfg: RenderingModeCfg) -> None: + """Apply Newton rendering mode values to a visualizer cfg object.""" + override_fields = { + "newton_enable_shadows": "enable_shadows", + "newton_enable_sky": "enable_sky", + "newton_enable_wireframe": "enable_wireframe", + "newton_sky_upper_color": "sky_upper_color", + "newton_sky_lower_color": "sky_lower_color", + "newton_light_color": "light_color", + } + for mode_field, viz_field in override_fields.items(): + value = getattr(mode_cfg, mode_field, None) + if value is not None and hasattr(visualizer_cfg, viz_field): + setattr(visualizer_cfg, viz_field, value) + + +def apply_newton_mode_cfg_to_viewer(viewer: Any, mode_cfg: RenderingModeCfg) -> None: + """Apply Newton rendering mode values to a live Newton viewer renderer, if available.""" + if viewer is None or not hasattr(viewer, "renderer"): + return + + if mode_cfg.newton_enable_shadows is not None: + viewer.renderer.draw_shadows = mode_cfg.newton_enable_shadows + if mode_cfg.newton_enable_sky is not None: + viewer.renderer.draw_sky = mode_cfg.newton_enable_sky + if mode_cfg.newton_enable_wireframe is not None: + viewer.renderer.draw_wireframe = mode_cfg.newton_enable_wireframe + if mode_cfg.newton_sky_upper_color is not None: + viewer.renderer.sky_upper = mode_cfg.newton_sky_upper_color + if mode_cfg.newton_sky_lower_color is not None: + viewer.renderer.sky_lower = mode_cfg.newton_sky_lower_color + if mode_cfg.newton_light_color is not None: + viewer.renderer._light_color = mode_cfg.newton_light_color + + +def resolve_rendering_mode_name_for_visualizer_cfg(get_setting: Any, visualizer_cfg: Any) -> str | None: + """Resolve effective rendering mode profile name for a visualizer cfg.""" + cli_mode_explicit = bool(get_setting("/isaaclab/rendering/rendering_mode/explicit")) + cli_mode = get_setting("/isaaclab/rendering/rendering_mode") + if cli_mode_explicit: + return cli_mode if cli_mode else None + mode_name = getattr(visualizer_cfg, "rendering_mode", None) + return mode_name if mode_name else None + + +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 + 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 to a visualizer config.""" + mode_name = resolve_rendering_mode_name_for_visualizer_cfg(get_setting, visualizer_cfg) + mode_cfg = resolve_rendering_mode_cfg(mode_name, mode_cfgs, logger) + if mode_cfg is None: + return + + visualizer_type = getattr(visualizer_cfg, "visualizer_type", None) + if visualizer_type == "kit": + apply_kit_rendering_mode_cfg(set_setting, mode_cfg) + elif visualizer_type == "newton": + apply_newton_mode_cfg_to_visualizer_cfg(visualizer_cfg, mode_cfg) + + +def apply_runtime_mode_profile_to_visualizer( + get_setting: Any, + set_setting: Any, + viz: Any, + visualizer_mode_keys: dict[int, str | None], + mode_cfgs: dict[str, RenderingModeCfg], + logger: Any, + force: bool = False, +) -> None: + """Resolve and apply runtime rendering mode profile to an active visualizer.""" + mode_name = resolve_rendering_mode_name_for_visualizer_cfg(get_setting, viz.cfg) + viz_id = id(viz) + if not force and visualizer_mode_keys.get(viz_id) == mode_name: + return + + mode_cfg = resolve_rendering_mode_cfg(mode_name, mode_cfgs, logger) + if mode_cfg is None: + visualizer_mode_keys[viz_id] = mode_name + return + + viz_type = getattr(viz.cfg, "visualizer_type", None) + if viz_type == "kit": + apply_kit_rendering_mode_cfg(set_setting, mode_cfg) + elif viz_type == "newton": + apply_newton_mode_cfg_to_visualizer_cfg(viz.cfg, mode_cfg) + apply_newton_mode_cfg_to_viewer(getattr(viz, "_viewer", None), mode_cfg) + + visualizer_mode_keys[viz_id] = mode_name diff --git a/source/isaaclab/isaaclab/sensors/camera/tiled_camera.py b/source/isaaclab/isaaclab/sensors/camera/tiled_camera.py index b07b5d20b64..99d0d4003a7 100644 --- a/source/isaaclab/isaaclab/sensors/camera/tiled_camera.py +++ b/source/isaaclab/isaaclab/sensors/camera/tiled_camera.py @@ -25,7 +25,7 @@ logger = logging.getLogger(__name__) if TYPE_CHECKING: - from isaaclab.renderers import Renderer + from isaaclab.renderers.renderer import Renderer from .tiled_camera_cfg import TiledCameraCfg diff --git a/source/isaaclab/isaaclab/sim/__init__.py b/source/isaaclab/isaaclab/sim/__init__.py index 9cb5fdc13aa..3f012a709ea 100644 --- a/source/isaaclab/isaaclab/sim/__init__.py +++ b/source/isaaclab/isaaclab/sim/__init__.py @@ -29,8 +29,9 @@ import warnings from .converters import * # noqa: F401, F403 +from isaaclab.rendering_mode.rendering_mode_cfg import RenderingModeCfg # noqa: F401 from .schemas import * # noqa: F401, F403 -from .simulation_cfg import RenderCfg, SimulationCfg # noqa: F401, F403 +from .simulation_cfg import SimulationCfg # noqa: F401, F403 from .simulation_context import SimulationContext, build_simulation_context # noqa: F401, F403 from .spawners import * # noqa: F401, F403 from .utils import * # noqa: F401, F403 diff --git a/source/isaaclab/isaaclab/sim/scene_data_providers/physx_scene_data_provider.py b/source/isaaclab/isaaclab/sim/scene_data_providers/physx_scene_data_provider.py index aab6371b464..b614fd0cbea 100644 --- a/source/isaaclab/isaaclab/sim/scene_data_providers/physx_scene_data_provider.py +++ b/source/isaaclab/isaaclab/sim/scene_data_providers/physx_scene_data_provider.py @@ -151,9 +151,17 @@ def _build_newton_model_from_usd(self) -> None: self._newton_model = builder.finalize(device=self._device) self._newton_state = self._newton_model.state() - # Extract scene structure from Newton model (single source of truth) - self._rigid_body_paths = list(self._newton_model.body_label) - self._articulation_paths = list(self._newton_model.articulation_label) + # Extract scene structure from Newton model (single source of truth). + # Support both legacy and newer Newton model field names. + body_paths = getattr(self._newton_model, "body_label", None) + if body_paths is None: + body_paths = getattr(self._newton_model, "body_key", []) + articulation_paths = getattr(self._newton_model, "articulation_label", None) + if articulation_paths is None: + articulation_paths = getattr(self._newton_model, "articulation_key", []) + + self._rigid_body_paths = list(body_paths) + self._articulation_paths = list(articulation_paths) self._xform_views.clear() self._view_body_index_map = {} diff --git a/source/isaaclab/isaaclab/sim/simulation_cfg.py b/source/isaaclab/isaaclab/sim/simulation_cfg.py index df531f82efb..c77ae8dcaf9 100644 --- a/source/isaaclab/isaaclab/sim/simulation_cfg.py +++ b/source/isaaclab/isaaclab/sim/simulation_cfg.py @@ -11,161 +11,16 @@ from __future__ import annotations -from typing import Any, Literal # Literal used by RenderCfg +from typing import Literal from isaaclab.physics import PhysicsCfg +from isaaclab.renderers import RendererCfg +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 +93,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/renderers.""" create_stage_in_memory: bool = False """If stage is first created in memory. Default is False. @@ -262,3 +121,9 @@ class SimulationCfg: visualizer_cfgs: list[VisualizerCfg] | VisualizerCfg | None = None """The list of visualizer configurations. Default is None.""" + + renderer_cfgs: list[RendererCfg] | RendererCfg | None = None + """Placeholder list of renderer configurations. Default is None. + + TODO: Hook renderer lifecycle and execution flow into SimulationContext. + """ diff --git a/source/isaaclab/isaaclab/sim/simulation_context.py b/source/isaaclab/isaaclab/sim/simulation_context.py index c555233b18a..8b9ac345d4e 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 @@ -22,8 +20,12 @@ import isaaclab.sim.utils.stage as stage_utils from isaaclab.app.settings_manager import SettingsManager from isaaclab.physics import PhysicsManager +from isaaclab.rendering_mode.rendering_mode_utils import ( + apply_mode_profile_to_visualizer_cfg, + apply_runtime_mode_profile_to_visualizer, +) from isaaclab.sim.utils import create_new_stage -from isaaclab.visualizers import KitVisualizerCfg, NewtonVisualizerCfg, RerunVisualizerCfg, Visualizer +from isaaclab.visualizers import Visualizer from .scene_data_providers import SceneDataProvider from .simulation_cfg import SimulationCfg @@ -145,11 +147,12 @@ def __init__(self, cfg: SimulationCfg | None = None): self._physics = self.cfg.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: SceneDataProvider | None = None self._visualizers: list[Visualizer] = [] + # Runtime cache of applied per-visualizer rendering mode profile names. + self._visualizer_mode_keys: dict[int, str | None] = {} self._visualizer_step_counter = 0 # Default visualization dt used before/without visualizer initialization. physics_dt = getattr(self.cfg.physics, "dt", None) @@ -169,94 +172,27 @@ 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 + def _apply_mode_profile_to_visualizer_cfg(self, visualizer_cfg: Any) -> None: + mode_cfgs = getattr(self.cfg, "rendering_mode_cfgs", None) or {} + apply_mode_profile_to_visualizer_cfg( + self.get_setting, + self.set_setting, + visualizer_cfg, + mode_cfgs, + logger, + ) - rep.settings.set_render_rtx_realtime(antialiasing=antialiasing_mode) - except Exception: - pass + def _apply_runtime_mode_profile_to_visualizer(self, viz: Visualizer, force: bool = False) -> None: + mode_cfgs = getattr(self.cfg, "rendering_mode_cfgs", None) or {} + apply_runtime_mode_profile_to_visualizer( + self.get_setting, + self.set_setting, + viz, + self._visualizer_mode_keys, + mode_cfgs, + logger, + force=force, + ) def _init_usd_physics_scene(self) -> None: """Create and configure the USD physics scene.""" @@ -335,10 +271,16 @@ def _create_default_visualizer_configs(self, requested_visualizers: list[str]) - for viz_type in requested_visualizers: try: if viz_type == "newton": + from isaaclab_newton.visualizers import NewtonVisualizerCfg + default_configs.append(NewtonVisualizerCfg()) elif viz_type == "rerun": + from isaaclab_newton.visualizers import RerunVisualizerCfg + default_configs.append(RerunVisualizerCfg()) elif viz_type == "kit": + from isaaclab_physx.visualizers import KitVisualizerCfg + default_configs.append(KitVisualizerCfg()) else: logger.warning( @@ -409,10 +351,11 @@ 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._apply_runtime_mode_profile_to_visualizer(visualizer, force=True) self._visualizers.append(visualizer) - logger.info(f"Initialized visualizer: {type(visualizer).__name__} (type: {cfg.visualizer_type})") except Exception as exc: logger.error(f"Failed to initialize visualizer '{cfg.visualizer_type}' ({type(cfg).__name__}): {exc}") @@ -507,6 +450,7 @@ def update_visualizers(self, dt: float) -> None: visualizers_to_remove = [] for viz in self._visualizers: try: + self._apply_runtime_mode_profile_to_visualizer(viz) if viz.is_rendering_paused(): continue if viz.is_closed: @@ -526,6 +470,7 @@ def update_visualizers(self, dt: float) -> None: for viz in visualizers_to_remove: try: + self._visualizer_mode_keys.pop(id(viz), None) viz.close() self._visualizers.remove(viz) logger.info("Removed visualizer: %s", type(viz).__name__) @@ -603,6 +548,7 @@ def clear_instance(cls) -> None: # Close all visualizers for viz in cls._instance._visualizers: + cls._instance._visualizer_mode_keys.pop(id(viz), None) viz.close() cls._instance._visualizers.clear() if cls._instance._scene_data_provider is not None: diff --git a/source/isaaclab/isaaclab/visualizers/__init__.py b/source/isaaclab/isaaclab/visualizers/__init__.py index 463a43527ea..a380e8c91cb 100644 --- a/source/isaaclab/isaaclab/visualizers/__init__.py +++ b/source/isaaclab/isaaclab/visualizers/__init__.py @@ -3,36 +3,24 @@ # # SPDX-License-Identifier: BSD-3-Clause -"""Visualizer Registry. - -This module uses a registry pattern to decouple visualizer instantiation -from specific types. Configs can create visualizers via the -`create_visualizer()` factory method. -""" +"""Visualizer registry and base interfaces.""" from __future__ import annotations from typing import TYPE_CHECKING, Any -from .kit_visualizer_cfg import KitVisualizerCfg -from .newton_visualizer_cfg import NewtonVisualizerCfg -from .rerun_visualizer_cfg import RerunVisualizerCfg from .visualizer import Visualizer from .visualizer_cfg import VisualizerCfg if TYPE_CHECKING: - from .kit_visualizer import KitVisualizer - from .newton_visualizer import NewtonVisualizer - from .rerun_visualizer import RerunVisualizer + from isaaclab_newton.visualizers import NewtonVisualizer, RerunVisualizer + from isaaclab_physx.visualizers import KitVisualizer _VISUALIZER_REGISTRY: dict[str, Any] = {} __all__ = [ "Visualizer", "VisualizerCfg", - "NewtonVisualizerCfg", - "KitVisualizerCfg", - "RerunVisualizerCfg", "get_visualizer_class", ] @@ -44,17 +32,17 @@ def get_visualizer_class(name: str) -> type[Visualizer] | None: try: if name == "newton": - from .newton_visualizer import NewtonVisualizer + from isaaclab_newton.visualizers import NewtonVisualizer _VISUALIZER_REGISTRY["newton"] = NewtonVisualizer return NewtonVisualizer if name == "kit": - from .kit_visualizer import KitVisualizer + from isaaclab_physx.visualizers import KitVisualizer _VISUALIZER_REGISTRY["kit"] = KitVisualizer return KitVisualizer if name == "rerun": - from .rerun_visualizer import RerunVisualizer + from isaaclab_newton.visualizers import RerunVisualizer _VISUALIZER_REGISTRY["rerun"] = RerunVisualizer return RerunVisualizer @@ -64,3 +52,20 @@ def get_visualizer_class(name: str) -> type[Visualizer] | None: warnings.warn(f"Failed to load visualizer '{name}': {exc}", ImportWarning) return None + + +def __getattr__(name: str) -> Any: + """Lazily expose backend visualizer config classes from core namespace.""" + if name == "KitVisualizerCfg": + from isaaclab_physx.visualizers import KitVisualizerCfg + + return KitVisualizerCfg + if name == "NewtonVisualizerCfg": + from isaaclab_newton.visualizers import NewtonVisualizerCfg + + return NewtonVisualizerCfg + if name == "RerunVisualizerCfg": + from isaaclab_newton.visualizers import RerunVisualizerCfg + + return RerunVisualizerCfg + raise AttributeError(f"module '{__name__}' has no attribute '{name}'") diff --git a/source/isaaclab/isaaclab/visualizers/visualizer.py b/source/isaaclab/isaaclab/visualizers/visualizer.py index 87d74974f89..484c158cbf7 100644 --- a/source/isaaclab/isaaclab/visualizers/visualizer.py +++ b/source/isaaclab/isaaclab/visualizers/visualizer.py @@ -114,7 +114,7 @@ def _compute_visualized_env_ids(self) -> list[int] | None: if num_envs <= 0: logger.debug("[Visualizer] num_envs is 0 or missing from provider metadata; env filtering disabled.") return None - if filter_mode == "env_ids": + if filter_mode == "env_filter_ids": env_ids_cfg = getattr(self.cfg, "env_filter_ids", None) if env_ids_cfg is not None and len(env_ids_cfg) > 0: return [i for i in env_ids_cfg if 0 <= i < num_envs] diff --git a/source/isaaclab/isaaclab/visualizers/visualizer_cfg.py b/source/isaaclab/isaaclab/visualizers/visualizer_cfg.py index 17afda08a29..3e3baaad98c 100644 --- a/source/isaaclab/isaaclab/visualizers/visualizer_cfg.py +++ b/source/isaaclab/isaaclab/visualizers/visualizer_cfg.py @@ -45,8 +45,8 @@ class VisualizerCfg: camera_usd_path: str = "/World/envs/env_0/Camera" """Absolute USD path to a camera prim when camera_source='usd_path'.""" - env_filter_mode: Literal["none", "env_ids", "random_n"] = "none" - """Env filter mode: 'none', 'env_ids', or 'random_n'.""" + env_filter_mode: Literal["none", "env_filter_ids", "random_n"] = "none" + """Env filter mode: 'none', 'env_filter_ids', or 'random_n'.""" env_filter_random_n: int = 64 """If env_filter_mode='random_n', number of envs to sample.""" @@ -55,12 +55,19 @@ class VisualizerCfg: """Seed for deterministic env sampling.""" env_filter_ids: list[int] = [i for i in range(0, 64, 4)] - """If env_filter_mode='env_ids', only these env indices are shown. + """If env_filter_mode='env_filter_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). """ + rendering_mode: str | None = "balanced" + """Name of the rendering mode profile for this visualizer. + + Selects an entry from 'isaaclab.sim.SimulationCfg.rendering_mode_cfgs'. + If None, no rendering mode overrides are applied and backend/native defaults are used. + """ + def get_visualizer_type(self) -> str | None: """Get the visualizer type identifier. diff --git a/source/isaaclab/test/envs/test_env_rendering_logic.py b/source/isaaclab/test/envs/test_env_rendering_logic.py index 751717ac26a..e1943b81055 100644 --- a/source/isaaclab/test/envs/test_env_rendering_logic.py +++ b/source/isaaclab/test/envs/test_env_rendering_logic.py @@ -16,6 +16,8 @@ import pytest import torch from isaaclab_physx.physics import IsaacEvents +from isaaclab_physx.visualizers.kit_visualizer import KitVisualizer +from isaaclab_physx.visualizers.kit_visualizer_cfg import KitVisualizerCfg import isaaclab.sim as sim_utils from isaaclab.envs import ( @@ -29,8 +31,6 @@ from isaaclab.scene import InteractiveSceneCfg from isaaclab.sim import SimulationCfg, SimulationContext from isaaclab.utils import configclass -from isaaclab.visualizers.kit_visualizer import KitVisualizer -from isaaclab.visualizers.kit_visualizer_cfg import KitVisualizerCfg @configclass diff --git a/source/isaaclab/test/sim/test_simulation_render_config.py b/source/isaaclab/test/sim/test_simulation_render_config.py index e5ad4274d18..aae59919162 100644 --- a/source/isaaclab/test/sim/test_simulation_render_config.py +++ b/source/isaaclab/test/sim/test_simulation_render_config.py @@ -14,87 +14,19 @@ """Rest everything follows.""" -import os - -import flatdict import pytest -import toml +from isaaclab_physx.visualizers import KitVisualizerCfg -from isaaclab.app.settings_manager import get_settings_manager -from isaaclab.sim.simulation_cfg import RenderCfg, SimulationCfg +from isaaclab.rendering_mode.rendering_mode_presets import get_kit_rendering_preset +from isaaclab.sim.simulation_cfg import RenderingModeCfg, 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 +# @pytest.mark.isaacsim_ci def test_render_cfg_presets(): - """Test that the simulation context is created with the correct render cfg preset with overrides.""" + """Test that rendering mode presets are applied and can be overridden via RenderingModeCfg.""" - # carb setting dictionary overrides - carb_settings = {"/rtx/raytracing/subpixel/mode": 3, "/rtx/pathtracing/maxSamplesPerLaunch": 999999} - # user-friendly setting overrides + # user-friendly field override dlss_mode = ("/rtx/post/dlss/execMode", 5) rendering_modes = ["performance", "balanced", "quality"] @@ -103,40 +35,28 @@ def test_render_cfg_presets(): # 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) + preset_dict = get_kit_rendering_preset(rendering_mode) - SimulationContext(cfg) + profile_name = f"profile_{rendering_mode}" + mode_cfg = RenderingModeCfg( + rendering_mode_preset=rendering_mode, + kit_dlss_mode=dlss_mode[1], + ) + cfg = SimulationCfg( + rendering_mode_cfgs={profile_name: mode_cfg}, + visualizer_cfgs=KitVisualizerCfg(rendering_mode=profile_name), + ) - settings = get_settings_manager() - for key, val in preset_dict.items(): - setting_name = "/" + key.replace(".", "/") # convert to setting path format + sim = SimulationContext(cfg) + sim.reset() - if setting_name in carb_settings: - setting_gt = carb_settings[setting_name] - elif setting_name == dlss_mode[0]: + for setting_name, val in preset_dict.items(): + if setting_name == dlss_mode[0]: setting_gt = dlss_mode[1] else: setting_gt = val - setting_val = settings.get(setting_name) + setting_val = sim.get_setting(setting_name) assert setting_gt == setting_val, ( f"Mismatch for '{setting_name}' in mode '{rendering_mode}': " @@ -148,59 +68,37 @@ def test_render_cfg_presets(): @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, +# @pytest.mark.isaacsim_ci +def test_rendering_mode_cfg_field_overrides(): + """Test that explicit RenderingModeCfg fields map to carb settings.""" + 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"), ) - - 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 + 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 + assert sim.get_setting("/rtx/post/aa/op") == 4 # dlss = 3, dlaa=4 diff --git a/source/isaaclab_newton/isaaclab_newton/renderers/__init__.py b/source/isaaclab_newton/isaaclab_newton/renderers/__init__.py index 84e13e0cf4d..846e5f0f973 100644 --- a/source/isaaclab_newton/isaaclab_newton/renderers/__init__.py +++ b/source/isaaclab_newton/isaaclab_newton/renderers/__init__.py @@ -3,11 +3,18 @@ # # SPDX-License-Identifier: BSD-3-Clause +<<<<<<< mtrepte/add_rendering_quality_cfg +"""Newton-backed renderer configurations and implementations.""" +======= """Sub-module for Newton renderer backends (Newton Warp).""" +>>>>>>> develop from .newton_warp_renderer import NewtonWarpRenderer from .newton_warp_renderer_cfg import NewtonWarpRendererCfg +<<<<<<< mtrepte/add_rendering_quality_cfg +__all__ = ["NewtonWarpRenderer", "NewtonWarpRendererCfg"] +======= Renderer = NewtonWarpRenderer __all__ = [ @@ -15,3 +22,4 @@ "NewtonWarpRendererCfg", "Renderer", ] +>>>>>>> develop diff --git a/source/isaaclab_newton/isaaclab_newton/renderers/newton_warp_renderer.py b/source/isaaclab_newton/isaaclab_newton/renderers/newton_warp_renderer.py index 3b565c69ea1..e69272c06ed 100644 --- a/source/isaaclab_newton/isaaclab_newton/renderers/newton_warp_renderer.py +++ b/source/isaaclab_newton/isaaclab_newton/renderers/newton_warp_renderer.py @@ -3,12 +3,18 @@ # # SPDX-License-Identifier: BSD-3-Clause +<<<<<<< mtrepte/add_rendering_quality_cfg +from __future__ import annotations + +import logging +======= """Newton Warp renderer for tiled camera rendering.""" from __future__ import annotations import logging import weakref +>>>>>>> develop from dataclasses import dataclass from typing import TYPE_CHECKING @@ -16,17 +22,27 @@ import torch import warp as wp +<<<<<<< mtrepte/add_rendering_quality_cfg +======= from isaaclab.renderers import BaseRenderer +>>>>>>> develop from isaaclab.sim import SimulationContext from isaaclab.utils.math import convert_camera_frame_orientation_convention from isaaclab.visualizers import VisualizerCfg +<<<<<<< mtrepte/add_rendering_quality_cfg +======= from .newton_warp_renderer_cfg import NewtonWarpRendererCfg +>>>>>>> develop if TYPE_CHECKING: from isaaclab.sensors import SensorBase from isaaclab.sim.scene_data_providers import SceneDataProvider +<<<<<<< mtrepte/add_rendering_quality_cfg + +======= +>>>>>>> develop logger = logging.getLogger(__name__) @@ -49,12 +65,16 @@ class CameraOutputs: def __init__(self, render_context: newton.sensors.SensorTiledCamera.RenderContext, sensor: SensorBase): self.render_context = render_context +<<<<<<< mtrepte/add_rendering_quality_cfg + self.sensor = sensor +======= # Currently camera owns the renderer and render data. By holding full # reference of the sensor, we create a circular reference between the # sensor and the render data. Weak reference ensures proper garbage # collection. self.sensor = weakref.ref(sensor) +>>>>>>> develop self.num_cameras = 1 self.camera_rays: wp.array(dtype=wp.vec3f, ndim=4) = None @@ -141,6 +161,21 @@ def _update_transforms( output[0, tid] = wp.transformf(positions[tid], orientations[tid]) +<<<<<<< mtrepte/add_rendering_quality_cfg +class NewtonWarpRenderer: + RenderData = RenderData + + def __init__(self): + self.newton_sensor = newton.sensors.SensorTiledCamera(self.get_scene_data_provider().get_newton_model()) + + def create_render_data(self, sensor: SensorBase) -> RenderData: + return RenderData(self.newton_sensor.render_context, sensor) + + def set_outputs(self, render_data: RenderData, output_data: dict[str, torch.Tensor]): + render_data.set_outputs(output_data) + + def update_transforms(self): +======= class NewtonWarpRenderer(BaseRenderer): """Newton Warp backend for tiled camera rendering.""" @@ -161,17 +196,24 @@ def set_outputs(self, render_data: RenderData, output_data: dict[str, torch.Tens def update_transforms(self): """Sync Newton scene state before rendering. See :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.update_transforms`.""" +>>>>>>> develop SimulationContext.instance().update_scene_data_provider(True) def update_camera( self, render_data: RenderData, positions: torch.Tensor, orientations: torch.Tensor, intrinsics: torch.Tensor ): +<<<<<<< mtrepte/add_rendering_quality_cfg + render_data.update(positions, orientations, intrinsics) + + def render(self, render_data: RenderData): +======= """Update camera poses and intrinsics. See :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.update_camera`.""" render_data.update(positions, orientations, intrinsics) def render(self, render_data: RenderData): """Render and write to output buffers. See :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.render`.""" +>>>>>>> develop self.newton_sensor.render( self.get_scene_data_provider().get_newton_state(), render_data.camera_transforms, @@ -184,6 +226,11 @@ def render(self, render_data: RenderData): ) def write_output(self, render_data: RenderData, output_name: str, output_data: torch.Tensor): +<<<<<<< mtrepte/add_rendering_quality_cfg + image_data = render_data.get_output(output_name) + if image_data is not None and image_data.ptr != output_data.data_ptr(): + wp.copy(wp.from_torch(output_data), image_data) +======= """Copy a specific output to the given buffer. See :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.write_output`.""" image_data = render_data.get_output(output_name) @@ -196,6 +243,7 @@ def cleanup(self, render_data: RenderData | None): See :meth:`~isaaclab.renderers.base_renderer.BaseRenderer.cleanup`.""" if render_data: render_data.sensor = None +>>>>>>> develop def get_scene_data_provider(self) -> SceneDataProvider: return SimulationContext.instance().initialize_scene_data_provider([VisualizerCfg(visualizer_type="newton")]) diff --git a/source/isaaclab_newton/isaaclab_newton/renderers/newton_warp_renderer_cfg.py b/source/isaaclab_newton/isaaclab_newton/renderers/newton_warp_renderer_cfg.py index 742f4df16e1..2beddfc4e05 100644 --- a/source/isaaclab_newton/isaaclab_newton/renderers/newton_warp_renderer_cfg.py +++ b/source/isaaclab_newton/isaaclab_newton/renderers/newton_warp_renderer_cfg.py @@ -3,15 +3,31 @@ # # SPDX-License-Identifier: BSD-3-Clause +<<<<<<< mtrepte/add_rendering_quality_cfg +"""Stub config for future Warp/Newton renderer integration.""" + +from isaaclab.renderers import RendererCfg +======= """Configuration for Newton Warp Renderer.""" from isaaclab.renderers.renderer_cfg import RendererCfg +>>>>>>> develop from isaaclab.utils import configclass @configclass class NewtonWarpRendererCfg(RendererCfg): +<<<<<<< mtrepte/add_rendering_quality_cfg + """Stub config for future Warp/Newton renderer integration. + + TODO: Implement renderer lifecycle, sensor/render-product routing, and + backend-specific settings application. + """ + + renderer_type: str = "warp" +======= """Configuration for Newton Warp Renderer.""" renderer_type: str = "newton_warp" """Type identifier for Newton Warp renderer.""" +>>>>>>> develop diff --git a/source/isaaclab_newton/isaaclab_newton/visualizers/__init__.py b/source/isaaclab_newton/isaaclab_newton/visualizers/__init__.py new file mode 100644 index 00000000000..acf90d731cf --- /dev/null +++ b/source/isaaclab_newton/isaaclab_newton/visualizers/__init__.py @@ -0,0 +1,13 @@ +# 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 + +"""Newton-backed visualizer implementations.""" + +from .newton_visualizer import NewtonVisualizer +from .newton_visualizer_cfg import NewtonVisualizerCfg +from .rerun_visualizer import RerunVisualizer +from .rerun_visualizer_cfg import RerunVisualizerCfg + +__all__ = ["NewtonVisualizer", "NewtonVisualizerCfg", "RerunVisualizer", "RerunVisualizerCfg"] diff --git a/source/isaaclab/isaaclab/visualizers/newton_visualizer.py b/source/isaaclab_newton/isaaclab_newton/visualizers/newton_visualizer.py similarity index 96% rename from source/isaaclab/isaaclab/visualizers/newton_visualizer.py rename to source/isaaclab_newton/isaaclab_newton/visualizers/newton_visualizer.py index ce1086831a4..2612a1b6d42 100644 --- a/source/isaaclab/isaaclab/visualizers/newton_visualizer.py +++ b/source/isaaclab_newton/isaaclab_newton/visualizers/newton_visualizer.py @@ -14,8 +14,9 @@ import warp as wp from newton.viewer import ViewerGL +from isaaclab.visualizers import Visualizer + from .newton_visualizer_cfg import NewtonVisualizerCfg -from .visualizer import Visualizer logger = logging.getLogger(__name__) @@ -255,18 +256,12 @@ def initialize(self, scene_data_provider: SceneDataProvider) -> None: self._viewer.show_springs = self.cfg.show_springs self._viewer.show_com = self.cfg.show_com - self._viewer.renderer.draw_shadows = self.cfg.enable_shadows - self._viewer.renderer.draw_sky = self.cfg.enable_sky - self._viewer.renderer.draw_wireframe = self.cfg.enable_wireframe - - self._viewer.renderer.sky_upper = self.cfg.sky_upper_color - self._viewer.renderer.sky_lower = self.cfg.sky_lower_color - self._viewer.renderer._light_color = self.cfg.light_color - + mode_name = self.cfg.rendering_mode if self.cfg.rendering_mode is not None else "none" logger.info( - "[NewtonVisualizer] initialized | camera_pos=%s camera_target=%s", + "[NewtonVisualizer] initialized | camera_pos=%s camera_target=%s mode=%s", self._viewer.camera.pos, self._last_camera_pose[1] if self._last_camera_pose else self.cfg.camera_target, + mode_name, ) self._is_initialized = True diff --git a/source/isaaclab/isaaclab/visualizers/newton_visualizer_cfg.py b/source/isaaclab_newton/isaaclab_newton/visualizers/newton_visualizer_cfg.py similarity index 64% rename from source/isaaclab/isaaclab/visualizers/newton_visualizer_cfg.py rename to source/isaaclab_newton/isaaclab_newton/visualizers/newton_visualizer_cfg.py index 0d0439843b7..cefaaac5124 100644 --- a/source/isaaclab/isaaclab/visualizers/newton_visualizer_cfg.py +++ b/source/isaaclab_newton/isaaclab_newton/visualizers/newton_visualizer_cfg.py @@ -6,8 +6,7 @@ """Configuration for Newton OpenGL Visualizer.""" from isaaclab.utils import configclass - -from .visualizer_cfg import VisualizerCfg +from isaaclab.visualizers import VisualizerCfg @configclass @@ -37,21 +36,3 @@ class NewtonVisualizerCfg(VisualizerCfg): show_com: bool = False """Show center of mass visualization.""" - - enable_shadows: bool = True - """Enable shadow rendering.""" - - enable_sky: bool = True - """Enable sky rendering.""" - - enable_wireframe: bool = False - """Enable wireframe rendering.""" - - sky_upper_color: tuple[float, float, float] = (0.2, 0.4, 0.6) - """Sky upper color RGB [0,1].""" - - sky_lower_color: tuple[float, float, float] = (0.5, 0.6, 0.7) - """Sky lower color RGB [0,1].""" - - light_color: tuple[float, float, float] = (1.0, 1.0, 1.0) - """Light color RGB [0,1].""" diff --git a/source/isaaclab/isaaclab/visualizers/rerun_visualizer.py b/source/isaaclab_newton/isaaclab_newton/visualizers/rerun_visualizer.py similarity index 79% rename from source/isaaclab/isaaclab/visualizers/rerun_visualizer.py rename to source/isaaclab_newton/isaaclab_newton/visualizers/rerun_visualizer.py index dad28b87d54..20d29f0666c 100644 --- a/source/isaaclab/isaaclab/visualizers/rerun_visualizer.py +++ b/source/isaaclab_newton/isaaclab_newton/visualizers/rerun_visualizer.py @@ -10,14 +10,17 @@ import contextlib import logging import os +import socket +import time from typing import TYPE_CHECKING import rerun as rr import rerun.blueprint as rrb from newton.viewer import ViewerRerun +from isaaclab.visualizers import Visualizer + from .rerun_visualizer_cfg import RerunVisualizerCfg -from .visualizer import Visualizer logger = logging.getLogger(__name__) @@ -108,10 +111,12 @@ def initialize(self, scene_data_provider: SceneDataProvider) -> None: self._setup_rerun_server() self._active_record_path = self.cfg.record_to_rrd self._create_viewer(record_to_rrd=self.cfg.record_to_rrd, metadata=metadata) + mode_name = self.cfg.rendering_mode if self.cfg.rendering_mode is not None else "none" logger.info( - "[RerunVisualizer] initialized | camera_pos=%s camera_target=%s", + "[RerunVisualizer] initialized | camera_pos=%s camera_target=%s mode=%s", self.cfg.camera_position, self.cfg.camera_target, + mode_name, ) self._is_initialized = True except Exception as exc: @@ -175,26 +180,69 @@ def _setup_rerun_server(self) -> None: logger.warning("[RerunVisualizer] 'rerun' binary not found in PATH. Skipping external bind.") return + bind_host = self.cfg.bind_address + grpc_port = int(self.cfg.grpc_port) + web_port = int(self.cfg.web_port) + if not self._is_bind_port_available(bind_host, grpc_port) or not self._is_bind_port_available( + bind_host, web_port + ): + # If ports are already occupied, reuse any existing rerun server and avoid noisy subprocess crashes. + logger.warning( + "[RerunVisualizer] Requested bind %s (gRPC=%d, web=%d) is already in use. " + "Skipping server launch and attempting to connect to existing rerun server.", + bind_host, + grpc_port, + web_port, + ) + self._rerun_address = f"rerun+http://127.0.0.1:{grpc_port}/proxy" + return + cmd = [ rerun_bin, "--serve-web", "--bind", - self.cfg.bind_address, + bind_host, "--port", - str(self.cfg.grpc_port), + str(grpc_port), "--web-viewer-port", - str(self.cfg.web_port), + str(web_port), ] if self.cfg.open_browser: cmd.append("--web-viewer") - self._rerun_server_process = subprocess.Popen(cmd) + self._rerun_server_process = subprocess.Popen( + cmd, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + # Give the process a brief window to fail fast (e.g. race on busy port). + time.sleep(0.15) + if self._rerun_server_process.poll() is not None: + logger.warning( + "[RerunVisualizer] Rerun server exited immediately; proceeding without managed server process." + ) + self._rerun_server_process = None + self._rerun_address = f"rerun+http://127.0.0.1:{grpc_port}/proxy" + return + logger.info( "[RerunVisualizer] Server bind %s:%s, web %s", - self.cfg.bind_address, - self.cfg.grpc_port, - self.cfg.web_port, + bind_host, + grpc_port, + web_port, ) - self._rerun_address = f"rerun+http://127.0.0.1:{self.cfg.grpc_port}/proxy" + self._rerun_address = f"rerun+http://127.0.0.1:{grpc_port}/proxy" + + def _is_bind_port_available(self, host: str, port: int) -> bool: + """Check whether a host:port can be bound by a new server process.""" + bind_host = "" if host in {"0.0.0.0", "::"} else host + family = socket.AF_INET6 if ":" in host and host not in {"0.0.0.0", "::"} else socket.AF_INET + with socket.socket(family, socket.SOCK_STREAM) as sock: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + sock.bind((bind_host, port)) + except OSError: + return False + return True def _create_viewer(self, record_to_rrd: str | None, metadata: dict | None = None, reset_time: bool = True) -> None: self._viewer = NewtonViewerRerun( diff --git a/source/isaaclab/isaaclab/visualizers/rerun_visualizer_cfg.py b/source/isaaclab_newton/isaaclab_newton/visualizers/rerun_visualizer_cfg.py similarity index 96% rename from source/isaaclab/isaaclab/visualizers/rerun_visualizer_cfg.py rename to source/isaaclab_newton/isaaclab_newton/visualizers/rerun_visualizer_cfg.py index 7c9fbb6a909..5bb62773080 100644 --- a/source/isaaclab/isaaclab/visualizers/rerun_visualizer_cfg.py +++ b/source/isaaclab_newton/isaaclab_newton/visualizers/rerun_visualizer_cfg.py @@ -8,8 +8,7 @@ from __future__ import annotations from isaaclab.utils import configclass - -from .visualizer_cfg import VisualizerCfg +from isaaclab.visualizers import VisualizerCfg @configclass diff --git a/source/isaaclab_physx/isaaclab_physx/renderers/__init__.py b/source/isaaclab_physx/isaaclab_physx/renderers/__init__.py index 1efb09ae878..d098d911d95 100644 --- a/source/isaaclab_physx/isaaclab_physx/renderers/__init__.py +++ b/source/isaaclab_physx/isaaclab_physx/renderers/__init__.py @@ -3,6 +3,13 @@ # # SPDX-License-Identifier: BSD-3-Clause +<<<<<<< mtrepte/add_rendering_quality_cfg +"""PhysX-backed renderer configurations and implementations.""" + +from .rtx_renderer_cfg import RTXRendererCfg + +__all__ = ["RTXRendererCfg"] +======= """Sub-module for PhysX renderer backends (Isaac RTX / Omniverse Replicator).""" from .isaac_rtx_renderer import IsaacRtxRenderer @@ -15,3 +22,4 @@ "IsaacRtxRendererCfg", "Renderer", ] +>>>>>>> develop diff --git a/source/isaaclab_physx/isaaclab_physx/renderers/rtx_renderer_cfg.py b/source/isaaclab_physx/isaaclab_physx/renderers/rtx_renderer_cfg.py new file mode 100644 index 00000000000..5bd6c7e2644 --- /dev/null +++ b/source/isaaclab_physx/isaaclab_physx/renderers/rtx_renderer_cfg.py @@ -0,0 +1,21 @@ +# 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 + +"""Stub config for future RTX renderer integration.""" + +from isaaclab.renderers import RendererCfg +from isaaclab.utils import configclass + + +@configclass +class RTXRendererCfg(RendererCfg): + """Stub config for future RTX renderer integration. + + TODO: Implement renderer lifecycle, sensor/render-product routing, and + backend-specific settings application. + """ + + renderer_type: str = "rtx" + rendering_mode: str | None = None diff --git a/source/isaaclab_physx/isaaclab_physx/visualizers/__init__.py b/source/isaaclab_physx/isaaclab_physx/visualizers/__init__.py new file mode 100644 index 00000000000..c831ff4bf28 --- /dev/null +++ b/source/isaaclab_physx/isaaclab_physx/visualizers/__init__.py @@ -0,0 +1,11 @@ +# 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 + +"""PhysX-backed visualizer implementations.""" + +from .kit_visualizer import KitVisualizer +from .kit_visualizer_cfg import KitVisualizerCfg + +__all__ = ["KitVisualizer", "KitVisualizerCfg"] diff --git a/source/isaaclab/isaaclab/visualizers/kit_visualizer.py b/source/isaaclab_physx/isaaclab_physx/visualizers/kit_visualizer.py similarity index 97% rename from source/isaaclab/isaaclab/visualizers/kit_visualizer.py rename to source/isaaclab_physx/isaaclab_physx/visualizers/kit_visualizer.py index dcbb6779a20..b99d6b02f64 100644 --- a/source/isaaclab/isaaclab/visualizers/kit_visualizer.py +++ b/source/isaaclab_physx/isaaclab_physx/visualizers/kit_visualizer.py @@ -13,8 +13,9 @@ from pxr import UsdGeom +from isaaclab.visualizers import Visualizer + from .kit_visualizer_cfg import KitVisualizerCfg -from .visualizer import Visualizer logger = logging.getLogger(__name__) @@ -63,7 +64,13 @@ def initialize(self, scene_data_provider: SceneDataProvider) -> None: self._apply_env_visibility(usd_stage, metadata) cam_pos = self.cfg.camera_position cam_target = self.cfg.camera_target - logger.info("[KitVisualizer] initialized | camera_pos=%s camera_target=%s", cam_pos, cam_target) + mode_name = self.cfg.rendering_mode if self.cfg.rendering_mode is not None else "none" + logger.info( + "[KitVisualizer] initialized | camera_pos=%s camera_target=%s mode=%s", + cam_pos, + cam_target, + mode_name, + ) self._is_initialized = True diff --git a/source/isaaclab/isaaclab/visualizers/kit_visualizer_cfg.py b/source/isaaclab_physx/isaaclab_physx/visualizers/kit_visualizer_cfg.py similarity index 95% rename from source/isaaclab/isaaclab/visualizers/kit_visualizer_cfg.py rename to source/isaaclab_physx/isaaclab_physx/visualizers/kit_visualizer_cfg.py index 230242eed77..bba48cb7d8f 100644 --- a/source/isaaclab/isaaclab/visualizers/kit_visualizer_cfg.py +++ b/source/isaaclab_physx/isaaclab_physx/visualizers/kit_visualizer_cfg.py @@ -6,8 +6,7 @@ """Configuration for Kit-based visualizer.""" from isaaclab.utils import configclass - -from .visualizer_cfg import VisualizerCfg +from isaaclab.visualizers import VisualizerCfg @configclass