1
0
forked from Rowland/EG

vr画面抖动修复

This commit is contained in:
Rowland 2025-09-23 14:14:13 +08:00
parent ef639ab0b1
commit b067e3a304
3 changed files with 291 additions and 11 deletions

View File

@ -144,6 +144,9 @@ class VRManager(DirectObject):
# 帧同步标记 - 修复ATW闪烁
self._poses_updated_this_frame = False
# Running Start标记 - Valve最佳实践
self._waitgetposes_called_this_frame = False
# 姿态缓存 - 修复时序不匹配
self._cached_render_poses = None # 用于渲染的缓存姿态
self._first_frame = True # 首帧标记
@ -529,16 +532,19 @@ class VRManager(DirectObject):
# VR更新策略选择
if self.pose_strategy == 'update_task':
# 策略1在更新任务中调用waitGetPoses推荐用于高性能
timing = self._start_timing('wait_poses')
self._wait_get_poses_with_prediction()
self._end_timing(timing)
# 🚀 新的Running Start策略WaitGetPoses在Submit后调用此处只更新相机
# 不在此处调用WaitGetPoses避免错过VSync窗口
self.poses_updated_in_task = True
# 更新相机姿态
# 使用上一帧获取的姿态更新相机
self._update_camera_poses()
# 输出策略信息(仅第一次)
if not hasattr(self, '_running_start_logged'):
print("✓ Running Start模式已启用 - WaitGetPoses在Submit后调用")
self._running_start_logged = True
else:
# 策略2在渲染回调中调用waitGetPoses默认策略
# 策略2在渲染回调中调用waitGetPoses传统策略)
self.poses_updated_in_task = False
# 1. 更新手柄和其他跟踪设备
@ -750,6 +756,11 @@ class VRManager(DirectObject):
self._poses_updated_this_frame = False
return task.done
def _reset_waitgetposes_flag(self, task):
"""重置WaitGetPoses标记 - 确保下一帧可以调用WaitGetPoses"""
self._waitgetposes_called_this_frame = False
return task.done
def _update_tracking_data(self):
"""更新VR追踪数据"""
try:
@ -1065,6 +1076,12 @@ class VRManager(DirectObject):
# 禁用主相机避免干扰VR渲染
self._disable_main_cam()
# 优化VR性能切换到update_task姿态策略
print("🚀 正在优化VR性能...")
self.set_pose_strategy('update_task')
self.set_prediction_time(11.0) # 11ms预测时间
print("✓ VR性能优化完成 - 姿态策略已切换至update_task模式")
print("✅ VR模式已启用")
return True
@ -1437,6 +1454,18 @@ class VRManager(DirectObject):
self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
self._end_timing(submit_timing)
# 🚀 Valve的"Running Start"技术Submit后立即调用WaitGetPoses
# 这是获取下一帧姿态的最佳时机避免错过VSync窗口
if not hasattr(self, '_waitgetposes_called_this_frame') or not self._waitgetposes_called_this_frame:
pose_timing = self._start_timing('wait_poses')
self._wait_get_poses_immediate()
self._end_timing(pose_timing)
self._waitgetposes_called_this_frame = True
# print("✓ Running Start: 在Submit后立即获取下一帧姿态")
# 重置标记,准备下一帧
self.world.taskMgr.doMethodLater(0.001, self._reset_waitgetposes_flag, "reset_waitgetposes_flag")
except Exception as e:
self._end_timing(render_timing)
print(f"右眼渲染回调错误: {e}")
@ -1992,11 +2021,11 @@ class VRManager(DirectObject):
if old_strategy != strategy:
print(f"✓ VR姿态策略已切换: {old_strategy}{strategy}")
if strategy == 'update_task':
print(f" 使用预测时间: {self.use_prediction_time*1000:.1f}ms")
print(" 优势:降低VR回调延迟提高性能")
print(" 🚀 Valve Running Start模式Submit后立即获取姿态")
print(" 优势:避免错过VSync窗口显著降低WaitGetPoses延迟")
else:
print(" 使用传统渲染回调策略")
print(" 优势:更低延迟,更精确的姿态")
print(" 缺点可能在渲染前调用WaitGetPoses容易错过VSync")
# 重置相关标记
if hasattr(self, '_poses_updated_this_frame'):
@ -2025,8 +2054,8 @@ class VRManager(DirectObject):
'strategy': self.pose_strategy,
'prediction_time_ms': self.use_prediction_time * 1000,
'description': {
'render_callback': '在渲染回调中获取姿态 - 低延迟,精确',
'update_task': '在更新任务中获取姿态 - 高性能,预测'
'render_callback': '在渲染回调中获取姿态 - 传统模式可能错过VSync',
'update_task': 'Valve Running Start模式 - Submit后立即获取姿态避免VSync延迟'
}.get(self.pose_strategy, '未知策略')
}

View File

@ -0,0 +1,133 @@
{
"controller_type": "knuckles",
"description": "Valve Index\u63a7\u5236\u5668\u7ed1\u5b9a",
"name": "EG VR Editor - Index",
"bindings": {
"/actions/default": {
"sources": [
{
"inputs": {
"click": {
"output": "/actions/default/in/Trigger"
}
},
"mode": "button",
"path": "/user/hand/left/input/trigger"
},
{
"inputs": {
"click": {
"output": "/actions/default/in/Trigger"
}
},
"mode": "button",
"path": "/user/hand/right/input/trigger"
},
{
"inputs": {
"value": {
"output": "/actions/default/in/Squeeze"
}
},
"mode": "trigger",
"path": "/user/hand/left/input/grip"
},
{
"inputs": {
"value": {
"output": "/actions/default/in/Squeeze"
}
},
"mode": "trigger",
"path": "/user/hand/right/input/grip"
},
{
"inputs": {
"click": {
"output": "/actions/default/in/AButton"
}
},
"mode": "button",
"path": "/user/hand/right/input/a"
},
{
"inputs": {
"click": {
"output": "/actions/default/in/BButton"
}
},
"mode": "button",
"path": "/user/hand/right/input/b"
},
{
"inputs": {
"position": {
"output": "/actions/default/in/Trackpad"
},
"click": {
"output": "/actions/default/in/TrackpadClick"
},
"touch": {
"output": "/actions/default/in/TrackpadTouch"
}
},
"mode": "trackpad",
"path": "/user/hand/left/input/trackpad"
},
{
"inputs": {
"position": {
"output": "/actions/default/in/Trackpad"
},
"click": {
"output": "/actions/default/in/TrackpadClick"
},
"touch": {
"output": "/actions/default/in/TrackpadTouch"
}
},
"mode": "trackpad",
"path": "/user/hand/right/input/trackpad"
},
{
"inputs": {
"position": {
"output": "/actions/default/in/Joystick"
}
},
"mode": "joystick",
"path": "/user/hand/left/input/thumbstick"
},
{
"inputs": {
"position": {
"output": "/actions/default/in/Joystick"
}
},
"mode": "joystick",
"path": "/user/hand/right/input/thumbstick"
}
],
"poses": [
{
"output": "/actions/default/in/Pose",
"path": "/user/hand/left/pose/raw"
},
{
"output": "/actions/default/in/Pose",
"path": "/user/hand/right/pose/raw"
}
],
"haptics": [
{
"output": "/actions/default/out/Haptic",
"path": "/user/hand/left/output/haptic"
},
{
"output": "/actions/default/out/Haptic",
"path": "/user/hand/right/output/haptic"
}
]
}
}
}

View File

@ -0,0 +1,118 @@
{
"controller_type": "oculus_touch",
"description": "Oculus Touch\u63a7\u5236\u5668\u7ed1\u5b9a",
"name": "EG VR Editor - Oculus Touch",
"bindings": {
"/actions/default": {
"sources": [
{
"inputs": {
"click": {
"output": "/actions/default/in/Trigger"
}
},
"mode": "button",
"path": "/user/hand/left/input/trigger"
},
{
"inputs": {
"click": {
"output": "/actions/default/in/Trigger"
}
},
"mode": "button",
"path": "/user/hand/right/input/trigger"
},
{
"inputs": {
"value": {
"output": "/actions/default/in/Squeeze"
}
},
"mode": "trigger",
"path": "/user/hand/left/input/grip"
},
{
"inputs": {
"value": {
"output": "/actions/default/in/Squeeze"
}
},
"mode": "trigger",
"path": "/user/hand/right/input/grip"
},
{
"inputs": {
"click": {
"output": "/actions/default/in/AButton"
}
},
"mode": "button",
"path": "/user/hand/right/input/a"
},
{
"inputs": {
"click": {
"output": "/actions/default/in/BButton"
}
},
"mode": "button",
"path": "/user/hand/right/input/b"
},
{
"inputs": {
"position": {
"output": "/actions/default/in/Joystick"
},
"click": {
"output": "/actions/default/in/TrackpadClick"
}
},
"mode": "joystick",
"path": "/user/hand/left/input/thumbstick"
},
{
"inputs": {
"position": {
"output": "/actions/default/in/Joystick"
},
"click": {
"output": "/actions/default/in/TrackpadClick"
}
},
"mode": "joystick",
"path": "/user/hand/right/input/thumbstick"
},
{
"inputs": {
"click": {
"output": "/actions/default/in/Menu"
}
},
"mode": "button",
"path": "/user/hand/left/input/menu"
}
],
"poses": [
{
"output": "/actions/default/in/Pose",
"path": "/user/hand/left/pose/raw"
},
{
"output": "/actions/default/in/Pose",
"path": "/user/hand/right/pose/raw"
}
],
"haptics": [
{
"output": "/actions/default/out/Haptic",
"path": "/user/hand/left/output/haptic"
},
{
"output": "/actions/default/out/Haptic",
"path": "/user/hand/right/output/haptic"
}
]
}
}
}