Cameras#
Camera sensors in ovrtx simulate physically accurate imaging and produce rendered outputs through RenderVar prims attached to a RenderProduct.
For how to configure RenderProducts and RenderVars, refer to Sensor Configuration.
Example USD#
A RenderProduct that outputs both LdrColor and HdrColor from a camera:
def "Render" {
def RenderProduct "Camera" {
int2 resolution = (1920, 1080)
rel camera = </World/Camera>
rel orderedVars = [<LdrColor>, <HdrColor>]
def RenderVar "LdrColor" {
string sourceName = "LdrColor"
}
def RenderVar "HdrColor" {
string sourceName = "HdrColor"
}
}
}
render_scope = stage.DefinePrim("/Render")
camera_product = UsdRender.Product.Define(stage, "/Render/Camera")
camera_product.GetResolutionAttr().Set(Gf.Vec2i(1920, 1080))
camera_product.GetCameraRel().SetTargets(["/World/Camera"])
ldr_var = UsdRender.Var.Define(stage, "/Render/Camera/LdrColor")
ldr_var.GetSourceNameAttr().Set("LdrColor")
hdr_var = UsdRender.Var.Define(stage, "/Render/Camera/HdrColor")
hdr_var.GetSourceNameAttr().Set("HdrColor")
camera_product.GetOrderedVarsRel().SetTargets([
"/Render/Camera/LdrColor",
"/Render/Camera/HdrColor",
])
Accessing Outputs in Code#
After stepping the renderer with a RenderProduct path, the outputs are available by full RenderVar prim path:
products = renderer.step(
render_products={"/Render/Camera"},
delta_time=1.0 / 60,
ordinal=ordinal,
)
for frame in products["/Render/Camera"].frames:
# RenderVar outputs are keyed by their full prim paths.
ldr_var = frame.render_vars["/Render/Camera/LdrColor"]
hdr_var = frame.render_vars["/Render/Camera/HdrColor"]
# LdrColor: uint8 sRGB image
var = ldr_var.map(device=ovrtx.Device.CPU)
ldr_pixels = np.from_dlpack(var) # shape: (H, W, 4), dtype: uint8
assert ldr_pixels.shape == (1080, 1920, 4)
assert ldr_pixels.dtype == np.uint8
Image.fromarray(ldr_pixels).save(output_dir / "test_camera_sensors.LdrColor.png")
# HdrColor: float16 linear image
var = hdr_var.map(device=ovrtx.Device.CPU)
hdr_pixels = np.from_dlpack(var) # shape: (H, W, 4), dtype: float16
assert hdr_pixels.shape == (1080, 1920, 4)
assert hdr_pixels.dtype == np.float16
ovrtx_render_var_output_handle_t ldr_handle = OVRTX_INVALID_HANDLE;
ovrtx_render_var_output_handle_t hdr_handle = OVRTX_INVALID_HANDLE;
// This step requested one RenderProduct. Select its first output frame,
// then find RenderVars by their full prim paths.
ovrtx_render_product_frame_output_t const& frame = outputs.outputs[0].output_frames[0];
for (size_t var_index = 0; var_index < frame.render_var_count; ++var_index) {
ovrtx_render_product_render_var_output_t const& var = frame.output_render_vars[var_index];
if (!var.render_var_path.ptr) {
continue;
}
std::string_view const path(var.render_var_path.ptr, var.render_var_path.length);
if (path == "/Render/Camera/LdrColor") {
ldr_handle = var.output_handle;
} else if (path == "/Render/Camera/HdrColor") {
hdr_handle = var.output_handle;
}
}
ASSERT_NE(ldr_handle, OVRTX_INVALID_HANDLE);
ASSERT_NE(hdr_handle, OVRTX_INVALID_HANDLE);
// Map LdrColor to CPU
ovrtx_map_output_description_t map_desc = {};
map_desc.device_type = OVRTX_MAP_DEVICE_TYPE_CPU;
ovrtx_render_var_output_t ldr_output = {};
result = ovrtx_map_render_var_output(renderer_, ldr_handle, &map_desc,
ovrtx_timeout_infinite, &ldr_output);
ASSERT_API_SUCCESS(result.status);
DLTensor const& ldr_tensor = *ldr_output.tensors[0].dl;
// ldr_tensor.data: RGBA uint8 pixels
// ldr_tensor.shape[0]: height, ldr_tensor.shape[1]: width
save_ldr_png("CameraSensors.LdrColor",
ldr_tensor.data,
static_cast<int>(ldr_tensor.shape[1]),
static_cast<int>(ldr_tensor.shape[0]));
ovrtx_cuda_sync_t no_sync = {};
ovrtx_unmap_render_var_output(renderer_, ldr_output.map_handle, no_sync);