Skip to content

Path resolution issue on Windows causes crash when loading 3D environment, which may be related to the Shader.load() function. #88

@L1ner313

Description

@L1ner313

Environment

  • Operating System: Windows 11
  • Python Version: 3.10
  • Relevant Libraries: stable-baselines3, panda3d

Bug Description

When running the vlm_tsc_zh/vlmlight_decision.py script on Windows, the program crashes during the initialization of the TSC3DEnvironment.

The traceback shows a sequence of errors:

  1. A shader error indicates a file cannot be found, but the path format is incorrect for Windows (e.g., /d/l1ner/... instead of D:\L1ner\...).
  2. This leads to a TypeError: NodePath.set_shader() argument 1 must be Shader, not NoneType because the shader object failed to load and is None.
  3. The child process running the environment crashes, which in turn causes an EOFError in the main process waiting for it.

Full Traceback:


'2025-08-19 16:15:07.354 | INFO     | tshub.tshub_env3d.vis3d_renderer._showbase_instance:init:103 - SIM: 初始化 ShowBase 实例'
:shader(error): Could not find shader file: /d/l1ner/tsinghua/vlmlight-main/transsimhub/tshub/tshub_env3d/_assets_3d/shader/unlit_shader.vert
Process SpawnProcess-1:
Traceback (most recent call last):
  ...
TypeError: NodePath.set_shader() argument 1 must be Shader, not NoneType
  ...
EOFError

Root Cause Analysis

The issue stems from how shader file paths are loaded in transsimhub/tshub/tshub_env3d/vis3d_renderer/_showbase_instance.py (or a related file).

The Shader.load() function from Panda3D seems to have trouble resolving relative paths containing .. on Windows. It incorrectly converts a native Windows path like D:\path\to\project into a POSIX-like path /d/path/to/project, which is invalid on Windows and causes the file lookup to fail.

The original failing code is likely similar to this:

# This code fails on Windows
unlit_shader = Shader.load(
    Shader.SL_GLSL,
    vertex=current_file_path("../_assets_3d/shader/unlit_shader.vert"),
    fragment=current_file_path("../_assets_3d/shader/unlit_shader.frag"),
)

Suggested Solution & Workaround

A robust, cross-platform solution is to use Python's os module to resolve the path natively before passing the shader's content (not its path) to Panda3D using Shader.make(). This bypasses Panda3D's path resolution issues on Windows.

This implementation works correctly on Windows:

import os
from panda3d.core import Shader
# Assuming 'current_file_path' and 'logger' are defined in the context

# Normalize to an absolute OS-specific path to resolve ".." and separator issues
_v_path = os.path.normpath(current_file_path("../_assets_3d/shader/unlit_shader.vert"))
_f_path = os.path.normpath(current_file_path("../_assets_3d/shader/unlit_shader.frag"))

# Read the shader source code directly using Python's robust I/O
try:
    with open(_v_path, 'r', encoding='utf-8') as f:
        _v_src = f.read()
    with open(_f_path, 'r', encoding='utf-8') as f:
        _f_src = f.read()
except Exception as e:
    logger.error(f"Failed to read shader sources. v={_v_path}, f={_f_path}, err={e}")
    raise

# Create the shader from its source code, avoiding path issues
unlit_shader = Shader.make(
    Shader.SL_GLSL,
    vertex=_v_src,
    fragment=_f_src,
)

# This now works correctly
root_np.setShader(unlit_shader, priority=10)

It is recommended to adopt this more robust method for loading shaders to ensure cross-platform compatibility, especially for Windows users.

Thank you for your great work on this project!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions