Repository: Genesis-Embodied-AI/Genesis
File: tests/test_render.py (Python)

Code before:
    # Compare brightness (mean pixel value)
    viewer_brightness = viewer_rgb.mean()
    add_cam_brightness = add_cam_rgb.mean()

    brightness_ratio = add_cam_brightness / viewer_brightness
    assert 0.99 <= brightness_ratio <= 1.01, (
        f"add_camera brightness ({add_cam_brightness:.2f}) should match "
        f"interactive viewer brightness ({viewer_brightness:.2f}), "
        f"but ratio is {brightness_ratio:.2f}"
    )


@pytest.mark.required
@pytest.mark.parametrize("renderer_type", [RENDERER_TYPE.RASTERIZER])
@pytest.mark.skipif(not IS_INTERACTIVE_VIEWER_AVAILABLE, reason="Interactive viewer not supported on this platform.")
@pytest.mark.xfail(sys.platform == "win32", raises=OpenGL.error.Error, reason="Invalid OpenGL context.")
def test_rasterizer_camera_sensor_with_viewer(renderer):
    """Test that RasterizerCameraSensor works correctly when interactive viewer is enabled.

    This verifies that the sensor properly shares the viewer's OpenGL context instead of
    creating a conflicting separate context.
    """
    from genesis.options.sensors import RasterizerCameraOptions

    scene = gs.Scene(
        viewer_options=gs.options.ViewerOptions(run_in_thread=(sys.platform == "linux")),
        renderer=renderer,
        show_viewer=True,
    )
    scene.add_entity(morph=gs.morphs.Plane())
    camera_sensor = scene.add_sensor(RasterizerCameraOptions(res=(256, 256)))
    scene.build()

    assert scene.visualizer.viewer._pyrender_viewer.is_active

    scene.step()
    data = camera_sensor.read()
    assert data.rgb.float().std() > 1.0, "RGB std too low, image may be blank"


Review comment (suggestion):
`viewer_options=gs.options.ViewerOptions(run_in_thread=False),`

Code after:
            dt=0.04,
            substeps=6,
        ),
        pbd_options=gs.options.PBDOptions(
            particle_size=1e-2,
        ),
        fem_options=gs.options.FEMOptions(
            use_implicit_solver=True,  # Implicit solver allows for larger timestep without failure on GPU backend
            n_pcg_iterations=40,  # Reduce number of iterations to speedup runtime
        ),
        renderer=renderer,
        show_viewer=show_viewer,
        show_FPS=False,
    )

    # Add ground plane
    scene.add_entity(
        morph=gs.morphs.Plane(),
        surface=gs.surfaces.Aluminium(
            ior=10.0,
        ),
    )

    # Add PBD cloth with checker texture
    asset_path = get_hf_dataset(pattern="uv_plane.obj")
    scene.add_entity(
        morph=gs.morphs.Mesh(
            file=f"{asset_path}/uv_plane.obj",
            scale=0.4,
            pos=(-0.2, 0.0, 0.4),
        ),
        material=gs.materials.PBD.Cloth(),
        surface=gs.surfaces.Default(
            diffuse_texture=gs.textures.ImageTexture(
                image_path="textures/checker.png",
            ),
            vis_mode="visual",
        ),
    )

    # Add FEM elastic object with checker texture
    scene.add_entity(
        morph=gs.morphs.Mesh(
            file="meshes/duck.obj",
            scale=0.1,
            pos=(0.2, 0.0, 0.2),
        ),
        material=gs.materials.FEM.Elastic(E=1e5, nu=0.4),
        surface=gs.surfaces.Default(
            diffuse_texture=gs.textures.ImageTexture(
                image_path="textures/checker.png",