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

Code before:
    assert shared_metadata.renderer is None


@pytest.mark.required
@pytest.mark.parametrize("backend", [gs.cuda])
@pytest.mark.skipif(not ENABLE_RAYTRACER, reason="RayTracer is not supported because 'LuisaRenderPy' is not available.")
def test_raytracer_attached_without_offset_T():
    """Test that RaytracerCameraSensor works when attached without explicit offset_T."""
    scene = gs.Scene(renderer=gs.renderers.RayTracer())
    scene.add_entity(morph=gs.morphs.Plane())
    sphere = scene.add_entity(morph=gs.morphs.Sphere(pos=(0.0, 0.0, 0.0)))

    # Create attached camera WITHOUT offset_T - should use pos as offset (consistent with other cameras)
    camera = scene.add_sensor(
        gs.sensors.RaytracerCameraOptions(
            res=(64, 64),
            pos=(0.0, 0.0, 2.0),
            entity_idx=sphere.idx,
        )
    )

    scene.build()
    data = camera.read()

    assert data.rgb.shape == (64, 64, 3)
    assert data.rgb.float().std() > 1.0, "RGB std too low, image may be blank"


@pytest.mark.required
@pytest.mark.parametrize("backend", [gs.cuda])
@pytest.mark.parametrize("n_envs", [0, 1])
@pytest.mark.skipif(not ENABLE_RAYTRACER, reason="RayTracer is not supported because 'LuisaRenderPy' is not available.")
def test_raytracer(n_envs, png_snapshot):
    CAM_RES = (128, 256)

    scene = gs.Scene(
        renderer=gs.renderers.RayTracer(
            env_surface=gs.surfaces.Emission(
                emissive_texture=gs.textures.ColorTexture(
                    color=(0.2, 0.3, 0.5),
                ),
            ),
            env_radius=20.0,
        ),
        show_viewer=False,
    )
    scene.add_entity(
        morph=gs.morphs.Plane(),
    )
    sphere = scene.add_entity(
        morph=gs.morphs.Sphere(

Review comment (suggestion):
I would rather update `test_raytracer` to add `pos=(0.0, 0.0, 2.0),` to `camera_1` instead of adding a new test? Because every single test we add is very costly (it requires building an entire scene), so it can be avoided, it is much better.

Code after:
    assert shared_metadata.renderer is None


@pytest.mark.required
@pytest.mark.parametrize("backend", [gs.cuda])
@pytest.mark.skipif(not ENABLE_RAYTRACER, reason="RayTracer is not supported because 'LuisaRenderPy' is not available.")
def test_raytracer_attached_without_offset_T():
    """Test that RaytracerCameraSensor works when attached without explicit offset_T.

    Also checks consistency with a scene-level camera (scene.add_camera) using the same
    pose and attachment, to make sure both camera APIs produce matching output.
    """
    CAM_RES = (128, 64)
    CAM_POS = (0.0, 0.0, 2.0)

    scene = gs.Scene(renderer=gs.renderers.RayTracer())
    scene.add_entity(morph=gs.morphs.Plane())
    sphere = scene.add_entity(morph=gs.morphs.Sphere())

    # Sensor camera attached WITHOUT offset_T - should use pos as offset
    camera_common_options = dict(
        res=CAM_RES,
        lookat=(0.0, 0.0, 0.0),
        up=(0.0, 1.0, 0.0),
        fov=30.0,
        spp=64,
        denoise=False,
    )
    sensor_camera = scene.add_sensor(
        gs.sensors.RaytracerCameraOptions(
            **camera_common_options,
            pos=CAM_POS,
            entity_idx=sphere.idx,
        )
    )

    # Scene-level camera with the same pose, attached with explicit offset_T
    scene_camera = scene.add_camera(
        **camera_common_options,
    )

    scene.build()

    # Attach scene-level camera with equivalent offset_T
    scene_camera.attach(sphere.base_link, offset_T=trans_to_T(np.array(CAM_POS)))

    scene.step()

    sensor_data = sensor_camera.read()
    assert sensor_data.rgb.shape == (CAM_RES[1], CAM_RES[0], 3)
    assert sensor_data.rgb.float().std() > 1.0, "Sensor camera RGB std too low, image may be blank"