渲染#
相机可以把 Genesis World 场景离屏渲染成图像:颜色、深度、分割结果、表面法线,以及视频。与查看器不同,相机不需要显示器,因此可以在渲染农场、容器中或通过 SSH 以无头方式运行。本页介绍如何添加相机、相机产出哪些图像类型、如何录制视频、光照,以及各类渲染后端——从快速的默认光栅化器到照片级真实感的光线追踪。
完整脚本见 examples/tutorials/visualization.py。
添加相机#
用 scene.add_camera() 添加相机。相机的渲染独立于查看器,因此适用于无头渲染,也适合拍摄查看器没有对准的角度:
cam = scene.add_camera(
res=(640, 480), # (width, height) in pixels
pos=(3.5, 0.0, 2.5),
lookat=(0, 0, 0.5),
fov=30,
GUI=False,
)
设置 GUI=True 时,相机会打开一个独立于查看器窗口的 OpenCV 窗口,显示每一帧渲染结果。以无头方式运行时保持 False。
渲染图像#
构建场景,然后调用 cam.render()。相机能产出四种图像:颜色、深度、分割掩码和表面法线。默认只渲染 RGB,其他类型要用关键字开关启用。render() 始终按同样的顺序返回这四种结果,未启用的类型返回 None:
scene.build()
# render rgb, depth, segmentation, normal
rgb, depth, segmentation, normal = cam.render(rgb=True, depth=True, segmentation=True, normal=True)
返回的每个数组形状为 (height, width, ...),即相对于 res=(width, height) 转置后的结果。默认情况下,分割掩码在每个像素上存一个整数对象索引;设置 colorize_seg=True 可获得可直接查看的彩色掩码。该索引按照 VisOptions.segmentation_level 设定的层级映射回场景对象(例如 link_idx 对应 scene.rigid_solver.links 中的下标)。
Tip
用 GUI=True 打开的 OpenCV 窗口有时第一帧显示为黑色。再次调用 cam.render() 刷新,或调用 cv2.waitKey(1)。
录制视频#
要录制视频,先用输出文件和帧率调用 start_recording(),推进场景,最后调用 stop_recording() 完成文件写入。每当需要输出一帧时,相机都会在 scene.step() 内部完成渲染,且每一帧都会立即编码并流式写入磁盘,因此录制时长不受内存限制。下面的例子让相机在仿真推进的同时环绕场景运动:
import math
cam.start_recording(save_to_filename="video.mp4", fps=60)
for i in range(120):
cam.set_pose(
pos=(3.0 * math.sin(i / 60), 3.0 * math.cos(i / 60), 2.5),
lookat=(0, 0, 0.5),
)
scene.step()
cam.stop_recording()
如果省略 save_to_filename,Genesis World 会根据调用脚本生成文件名,fps 默认为 60。任意两帧之间总是相隔整数个仿真步,因此不落在该网格上的帧率会被取整到最近的网格值并记录日志;场景能录制的最高帧率为每步一帧。视频中的一秒对应按 realtime_factor 步调计时的一秒(参见查看器),因此在默认的 realtime_factor=1.0 下,无论帧率是多少,播放都按实时进行;而每步一帧时,编码帧率为 1 / dt。效果如下:
调用 cam.pause_recording() 可以把仿真中的一段时间排除在视频之外(例如稳定阶段),然后用不带参数的 cam.start_recording() 继续写入同一个文件;暂停的这段时间不会在视频中留下空档。文件名和帧率在整段视频中固定不变,因此恢复录制时传入其中任何一个都会报错。调用 stop_recording() 之后,相机可以以新的帧率录制到新文件。
在批处理场景中,如果相机渲染所有环境,则每个被渲染的环境各写一个文件,文件名带有该环境的索引后缀(video_0.mp4、video_1.mp4、……)。BatchRenderer 后端就是这样做的,光栅化器在 VisOptions 中设置 split_envs=True 时也是如此;否则相机会绑定到单个环境 env_idx,只录制一个文件。
如果需要按计划记录传感器和仿真数据(而不只是视频),请参阅记录数据。
光照#
光栅化器(查看器,以及任何执行光栅化的相机或相机传感器)用 VisOptions 上的灯光列表为场景打光。在没有任何配置时,它使用单个平行光,因此场景开箱即处于被照亮的状态;设置 lights 可自行控制方向、颜色和强度。灯光类位于 gs.options.vis:
scene = gs.Scene(
vis_options=gs.options.VisOptions(
lights=[
gs.options.vis.DirectionalLight(
dir=(-1, -1, -1), # direction the light travels, world frame
color=(1.0, 1.0, 1.0), # RGB in [0, 1]
intensity=5.0,
),
gs.options.vis.PointLight(
pos=(2.0, 0.0, 3.0), # meters, world frame
color=(1.0, 0.9, 0.8),
intensity=8.0,
),
],
ambient_light=(0.1, 0.1, 0.1), # uniform fill so shadows are not pure black
),
)
lights 列表接受两种类型:
DirectionalLight: 从固定方向射出的平行光线,类似阳光。设置dir(光线传播方向)、color和intensity。位置无关紧要。PointLight: 从一个点向外辐射的光。设置pos、color和intensity。
环境光是独立于 lights 条目的一种均匀补光,通过 ambient_light 字段设置。
渲染后端#
gs.Scene(renderer=...) 决定场景中的相机如何把场景转换为像素:
gs.renderers.Rasterizer():默认选项。速度快,也是查看器始终使用的后端。gs.renderers.RayTracer():路径追踪器,用于生成照片级真实感的静帧(见下文)。gs.renderers.BatchRenderer(...):跨多个环境的高吞吐量渲染(见使用 gs-madrona 进行批渲染)。
使用 Nyx 进行照片级真实感渲染#
Nyx 是实现照片级真实感渲染的推荐途径。与上文的后端不同,它以相机传感器的形式挂载,而不是作为场景级渲染器:添加一个 NyxCameraOptions 传感器,再从 cam.read().rgb 读回帧。它支持 PBR 材质、HDRI 光照、3D 高斯泼溅资产、多相机与多环境渲染,以及逐像素对象拾取。安装方法、最小示例和完整功能集请参阅Nyx 渲染器页面。
Note
路线图。 我们正在把光栅化和路径追踪统一到 Nyx 之下,形成单一的、基于传感器的渲染接口。Nyx 将逐步取代下文的 Luisa 后端和默认光栅化器,最终 Genesis World 中所有基于相机的渲染都由它承担。
使用 Luisa 进行照片级真实感渲染(已弃用)#
Genesis World 还提供基于 Luisa 的光线追踪后端。创建场景时传入 renderer=gs.renderers.RayTracer() 即可启用;它暴露了 spp、aperture 以及相机 model 等额外参数。
Warning
该后端已弃用并由 Nyx 取代,且需要从源码构建 LuisaRender。
安装步骤(已在 Ubuntu 22.04、CUDA 12.4 和 Python 3.9 上测试):
拉取子模块并安装渲染相关的额外依赖:
# inside the genesis-world repo git submodule update --init --recursive pip install -e ".[render]"
确保
PATH中有gcc/g++>= 11 和 CMake >= 3.26,并安装 Vulkan、X11、UUID 和 zlib 的开发头文件(有 sudo 时用apt,没有时用conda install -c conda-forge)。构建
LuisaRender:cd genesis/ext/LuisaRender cmake -S . -B build -D CMAKE_BUILD_TYPE=Release -D PYTHON_VERSIONS=3.9 \ -D LUISA_COMPUTE_DOWNLOAD_NVCOMP=ON -D LUISA_COMPUTE_ENABLE_GUI=OFF \ -D LUISA_RENDER_BUILD_TESTS=OFF cmake --build build -j $(nproc)
运行示例:
cd examples/rendering python demo.py
Note
常见 CUDA 与 Python 组合的预编译 LuisaRender 二进制文件可在 Google Drive 上获取,命名格式为 build_<commit-tag>_cuda<version>_python<version>。下载与你的系统匹配的文件,重命名为 build/,放入 genesis/ext/LuisaRender。构建和 CUDA 工具包的故障排查请参阅 genesis-world README。
使用 gs-madrona 进行批渲染#
要在大量并行环境上实现高吞吐量渲染,可传入 renderer=gs.renderers.BatchRenderer(use_rasterizer=True) 使用 gs-madrona 后端(设为 use_rasterizer=False 则改用路径追踪)。
先安装该包。PyPI 上提供适用于 x86 和 Python >= 3.10 的预编译 wheel:
pip install gs-madrona
然后运行随附的示例,它会把帧写入 out/batch_render,也可以用 -o 写到其他位置:
python examples/rigid/single_franka_batch_render.py
批渲染器只能在 CUDA 上运行,因此该示例没有可回退的 CPU 后端。
批渲染器不在 VisOptions 中取灯光,而是在场景创建之后通过 scene.add_light(...) 在运行时设置:
scene.add_light(
pos=(0.0, 0.0, 10.0), # position, used for positional lights
dir=(0.0, 0.0, -1.0), # direction the light travels, normalized internally
color=(1.0, 1.0, 1.0), # RGB, each channel in [0, 1]
intensity=1.0,
directional=True, # parallel rays if True, positional if False
castshadow=True,
cutoff=45.0, # spotlight cutoff angle, degrees
attenuation=0.0, # distance falloff for positional lights
)