🎨 渲染器#
启动与加载#
RenderApp 负责基本的场景渲染。一般的,在代码中创建一个 RenderApp 实例,通过 load_model 加载模型后调用 render.launch(model) 来为渲染器加载模型。
同步#
在 motrixsim 中,渲染器跑在一个独立的线程中,因此我们需要在 python 主线程中调用 render.sync(data) 来实现物理模拟数据与渲染器的双向同步更新。render.sync 方法实际上执行了如下的逻辑:
向渲染器发送所有物理对象的位姿、用户绘制指令等数据。
从渲染器获取窗口、UI 等输入事件以及相机渲染数据
其背后的线程模型如下:

主线程,即 python 代码执行的线程,我们通常在若干次物理步后执行一次
render.sync(data)来同步数据。sync 会做两件事:从 Event 管道接受来自渲染线程的输入事件与相机数据
向 Frame 管道发送帧数据(如果 Frame 管道已满,则阻塞等待)
渲染线程,负责窗口的创建与渲染循环的执行。其在每个循环中都会做两件事:
从 Frame 管道接受来自主线程的帧数据,并提交给 GPU 渲染(如果管道为空,则跳过)
处理窗口以及 UI 以及相机数据请求,并将其发送到 Event 管道
渲染配置#
当前,有配置项RenderSettings来进行全局渲染配置:
参数名 |
解释 |
默认值 |
|---|---|---|
simplify_render_mesh |
是否自动进行网格的简化 |
False |
enable_shadow |
是否启用灯光阴影 |
True |
enable_ssao |
是否启用屏幕空间环境光遮蔽 |
True |
enable_oit |
是否启用顺序无关透明渲染 |
True |
特别的,当且仅当全局配置开启,且场景描述文件(mjcf/msd)中也启用某些渲染项时,才会有最终的效果。
自定义 UI 组件#
目前支持按钮 add_button 与复选框 add_toggle 两种组件,通过设置回调函数的方式来响应用户的点击事件。
用户需要通过 render.opt.set_left_panel_vis(True) 来显示左侧面板,组件会按添加顺序显示在面板上。
force = 10
# button
def on_click():
nonlocal force
print("Button clicked!")
model.get_actuator("actuator_slider").set_ctrl(data, force)
force = -force
def on_toggle_changed(value: bool):
print("toggle value:", value)
render.opt.set_left_panel_vis(True)
render.ui.add_button("Click Me", on_click)
render.ui.add_toggle("Some Toggle", False, on_toggle_changed)
Gizmos 绘制#
Gizmos 是一种用于辅助调试的图形元素,渲染器提供了一个简单的 API 来绘制 gizmos。
方法名 |
释义 |
|---|---|
draw_sphere |
绘制线框球形 |
draw_cuboid |
绘制线框矩体 |
draw_cylinder |
绘制线框圆柱体 |
draw_capsule |
绘制线框胶囊体 |
draw_ray |
绘制射线 |
draw_line |
绘制线段 |
draw_arrow |
绘制箭头 |
draw_rect |
绘制 2D 矩形 |
draw_grid |
绘制 3D 栅格 |
draw_axes |
绘制坐标轴 |
set_draw_collider |
开启/关闭碰撞体绘制 |
set_draw_joint |
开启/关闭关节绘制 |
set_draw_site |
开启/关闭参考点绘制 |
set_collider_color |
设置碰撞体绘制颜色 |
set_joint_color |
设置关节绘制颜色 |
set_line_width |
设置绘制线段宽度 |
set_joint_size |
设置关节绘制大小 |
Gizmos 采用即时模式,即使不需要更新,用户也需要在每次渲染同步时添加 gizmos。
nonlocal rot, dir, x
# gizmos is drawning in immediate mode. so you must call it every frame
gizmos = render.gizmos
gizmos.draw_sphere(0.1, np.array([x, 0, 1]), color=Color.rgb(1, 0, 0))
gizmos.draw_cuboid(
size=np.array([0.2, 0.3, 0.4]), pos=np.array([1, 0, 1]), rot=rot.as_quat(), color=Color.rgb(0, 1, 0)
)
gizmos.draw_cuboid(
size=np.array([0.1, 0.1, 1]), pos=np.array([3, 0, 1]), rot=rot.as_quat(), color=Color.rgb(0, 1, 0)
)
gizmos.draw_capsule(0.5, 0.5, pos=np.array([1, 1, 1]), rot=Rotation.identity().as_quat())
gizmos.draw_cylinder(0.5, 0.5, pos=np.array([2, 1, 1]), rot=Rotation.identity().as_quat())
gizmos.draw_arrow(start=np.array([3, 1, 1]), end=np.array([4, 2, 1]), color=Color.rgb(1, 1, 0))
gizmos.draw_line(start=np.array([3, 2, 1]), end=np.array([4, 3, 1]), color=Color.rgb(1, 1, 0))
gizmos.draw_ray(start=np.array([4, 1, 1]), vector=np.array([3, 0.2, 0]), color=Color.rgb(1, 1, 0.2))
gizmos.draw_grid(
pos=np.array([0, -2, 1]),
rot=rot.as_quat(),
color=Color.rgb(1, 0.5, 0.2),
)
gizmos.draw_rect(
pos=np.array([3, -2, 1]),
rot=Rotation.identity().as_quat(),
width=1.5,
height=3.5,
color=Color.rgb(0.5, 1, 0.2),
)
IO 输入事件#
通过 render.input 可以获取到Input对象,Input 对象提供了一系列方法,用于查询渲染器的鼠标、键盘以及 UI 事件。
您可以通过以下的例子来了解更详细的用法:
合法键盘输入列表#
以下是支持的键盘按键输入列表:
按键类型 |
示例按键 |
|---|---|
字母键 |
|
功能键 |
|
特殊键 |
|
方向键 |
|
注意:以上均不区分大小写,表格内未提及的键位暂不支持。
系统相机控制#
渲染器提供了一个自由的系统相机控制系统,用户可以通过鼠标操作来控制系统相机的视角和焦点(始终位于屏幕中心)。
鼠标左键按下并拖动:绕着焦点旋转系统相机
鼠标右键按下并拖动:移动焦点(此时显示红圈为焦点)
鼠标滚轮:缩放(到焦点位置不可再放大)
更多的相机控制方式请参考 相机。
单模型多实例渲染#
render.launch(model) 还有 batch:int 与 render_offset:List[:3] 两个可选参数,在需要单个模型多实例渲染时,分别用于设置实例数与偏移位置。
# Create the render instance of the model
# Try to create 3 model data
batch = 3
render_offset_1 = [0, 0, 0]
render_offset_2 = [0, 1, 0]
render_offset_3 = [0, -1, 0]
render.launch(
model,
batch,
[
render_offset_1,
render_offset_2,
render_offset_3,
],
)
完整代码见 examples/physics/model.py
实例可见性#
当我们进行单模型多实例渲染时,可以按需配置每一个实例的渲染可见性。
...
# 创建多个实例
render_offsets = []
batch = 10
for i in range(batch):
render_offsets.append([i * 2.0, 0, 0])
render.launch(model, batch, render_offsets)
data = SceneData(model, batch=(batch,))
target_scene_indices = [1, 3, 5, 7, 9] # 指定实例索引
render.set_scene_vis(target_scene_indices, False) # 隐藏目标实例
render.set_scene_vis(target_scene_indices, True) # 显示目标实例
也可以全局开启/关闭:
render.set_all_scene_vis(False) # 隐藏所有实例
render.set_all_scene_vis(True) # 显示所有实例
上述操作仅影响渲染可见性,不影响对象的物理仿真。