高级渲染添加
This commit is contained in:
parent
a8e27a56e9
commit
83fcb3ced4
@ -1,5 +1,5 @@
|
||||
{
|
||||
"render_mode": "normal",
|
||||
"render_mode": "render_pipeline",
|
||||
"resolution_scale": 0.75,
|
||||
"pipeline_resolution_scale": 0.75,
|
||||
"quality_preset": "quality",
|
||||
@ -13,6 +13,6 @@
|
||||
"ao_quality": "low"
|
||||
},
|
||||
"anti_aliasing": "4x",
|
||||
"refresh_rate": "72Hz",
|
||||
"refresh_rate": "144Hz",
|
||||
"async_reprojection": true
|
||||
}
|
||||
@ -404,6 +404,34 @@ class VRController(DirectObject):
|
||||
except Exception as e:
|
||||
print(f"⚠️ 轴数据调试失败: {e}")
|
||||
|
||||
def recreate_visualizer(self):
|
||||
"""重新创建visualizer - 用于渲染模式切换后刷新
|
||||
|
||||
当VR渲染模式在运行时改变时调用此方法,以确保visualizer
|
||||
使用正确的渲染设置(普通模式 vs RenderPipeline模式)
|
||||
"""
|
||||
# 清理旧visualizer
|
||||
if self.visualizer:
|
||||
try:
|
||||
self.visualizer.cleanup()
|
||||
self.visualizer = None
|
||||
print(f"🧹 {self.name}手柄visualizer已清理")
|
||||
except Exception as e:
|
||||
print(f"⚠️ 清理{self.name}手柄visualizer失败: {e}")
|
||||
|
||||
# 重新创建visualizer
|
||||
if self.anchor_node:
|
||||
self._create_visualizer()
|
||||
if self.visualizer:
|
||||
print(f"✨ {self.name}手柄visualizer已重建(使用当前渲染模式)")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ {self.name}手柄visualizer重建失败")
|
||||
return False
|
||||
else:
|
||||
print(f"⚠️ {self.name}手柄anchor_node不存在,无法重建visualizer")
|
||||
return False
|
||||
|
||||
def cleanup(self):
|
||||
"""清理资源"""
|
||||
self.ignoreAll()
|
||||
|
||||
@ -567,19 +567,24 @@ class VRManager(DirectObject):
|
||||
self.game_poses = poses_t() # 游戏逻辑姿态(当前的)
|
||||
print("✓ VR渲染和游戏姿态数组已创建")
|
||||
|
||||
# 创建VR渲染缓冲区 - 根据渲染模式选择
|
||||
print(f"🎨 VR渲染模式: {self.vr_render_mode.value}")
|
||||
if self.vr_render_mode == VRRenderMode.RENDER_PIPELINE:
|
||||
if not self._create_vr_buffers_with_pipeline():
|
||||
print("⚠️ RenderPipeline模式创建失败,回退到普通渲染模式")
|
||||
self.vr_render_mode = VRRenderMode.NORMAL
|
||||
if not self._create_vr_buffers():
|
||||
print("❌ 创建VR渲染缓冲区失败")
|
||||
return False
|
||||
# 🔧 关键修复:统一初始化流程
|
||||
# 如果目标模式是RenderPipeline,先用普通模式初始化,然后切换
|
||||
# 这样两个场景都走相同的、已验证的代码路径
|
||||
target_render_mode = self.vr_render_mode
|
||||
use_deferred_pipeline_switch = False
|
||||
|
||||
if target_render_mode == VRRenderMode.RENDER_PIPELINE:
|
||||
print("🎨 目标VR渲染模式: RenderPipeline")
|
||||
print(" 策略:先用普通模式初始化,然后切换到RenderPipeline")
|
||||
self.vr_render_mode = VRRenderMode.NORMAL
|
||||
use_deferred_pipeline_switch = True
|
||||
else:
|
||||
if not self._create_vr_buffers():
|
||||
print("❌ 创建VR渲染缓冲区失败")
|
||||
return False
|
||||
print(f"🎨 VR渲染模式: {self.vr_render_mode.value}")
|
||||
|
||||
# 创建VR渲染缓冲区 - 始终用普通模式初始化
|
||||
if not self._create_vr_buffers():
|
||||
print("❌ 创建VR渲染缓冲区失败")
|
||||
return False
|
||||
|
||||
# 设置VR相机
|
||||
if not self._setup_vr_cameras():
|
||||
@ -644,7 +649,18 @@ class VRManager(DirectObject):
|
||||
self._start_vr_task()
|
||||
|
||||
self.vr_initialized = True
|
||||
print("✅ VR系统初始化成功")
|
||||
print("✅ VR系统初始化成功(普通模式)")
|
||||
|
||||
# 🔧 关键修复:如果目标是RenderPipeline模式,现在切换过去
|
||||
# 这样场景2(先设RP再进VR)会走场景1(先VR再设RP)相同的代码路径
|
||||
if use_deferred_pipeline_switch:
|
||||
print("\n🔄 现在切换到目标渲染模式: RenderPipeline")
|
||||
print(" 这将触发buffer重建和visualizer刷新...")
|
||||
if self.set_vr_render_mode(target_render_mode):
|
||||
print("✅ 已成功切换到RenderPipeline模式")
|
||||
else:
|
||||
print("⚠️ 切换到RenderPipeline失败,保持普通模式")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
@ -725,6 +741,13 @@ class VRManager(DirectObject):
|
||||
def _prepare_and_cache_textures(self):
|
||||
"""准备纹理并缓存OpenGL ID - 解决重复准备问题"""
|
||||
try:
|
||||
# 🔧 验证纹理对象存在
|
||||
if not self.vr_left_texture or not self.vr_right_texture:
|
||||
print("❌ VR纹理对象不存在")
|
||||
print(f" 左眼纹理: {self.vr_left_texture}")
|
||||
print(f" 右眼纹理: {self.vr_right_texture}")
|
||||
return False
|
||||
|
||||
# 获取graphics state guardian和prepared objects
|
||||
gsg = self.world.win.getGsg()
|
||||
if not gsg:
|
||||
@ -737,32 +760,32 @@ class VRManager(DirectObject):
|
||||
return False
|
||||
|
||||
# 准备左眼纹理并缓存ID
|
||||
if self.vr_left_texture:
|
||||
texture_context = self.vr_left_texture.prepareNow(0, prepared_objects, gsg)
|
||||
if texture_context and hasattr(texture_context, 'getNativeId'):
|
||||
self.left_texture_id = texture_context.getNativeId()
|
||||
if self.left_texture_id > 0:
|
||||
print(f" ✅ 左眼纹理准备完成 ({self.vr_render_mode.value}): ID={self.left_texture_id}")
|
||||
else:
|
||||
print(" ❌ 左眼纹理ID无效")
|
||||
return False
|
||||
print(f" 准备左眼纹理: {self.vr_left_texture.getXSize()}x{self.vr_left_texture.getYSize()}")
|
||||
texture_context = self.vr_left_texture.prepareNow(0, prepared_objects, gsg)
|
||||
if texture_context and hasattr(texture_context, 'getNativeId'):
|
||||
self.left_texture_id = texture_context.getNativeId()
|
||||
if self.left_texture_id > 0:
|
||||
print(f" ✅ 左眼纹理准备完成 ({self.vr_render_mode.value}): ID={self.left_texture_id}")
|
||||
else:
|
||||
print(" ❌ 左眼纹理准备失败")
|
||||
print(" ❌ 左眼纹理ID无效")
|
||||
return False
|
||||
else:
|
||||
print(" ❌ 左眼纹理准备失败")
|
||||
return False
|
||||
|
||||
# 准备右眼纹理并缓存ID
|
||||
if self.vr_right_texture:
|
||||
texture_context = self.vr_right_texture.prepareNow(0, prepared_objects, gsg)
|
||||
if texture_context and hasattr(texture_context, 'getNativeId'):
|
||||
self.right_texture_id = texture_context.getNativeId()
|
||||
if self.right_texture_id > 0:
|
||||
print(f" ✅ 右眼纹理准备完成 ({self.vr_render_mode.value}): ID={self.right_texture_id}")
|
||||
else:
|
||||
print(" ❌ 右眼纹理ID无效")
|
||||
return False
|
||||
print(f" 准备右眼纹理: {self.vr_right_texture.getXSize()}x{self.vr_right_texture.getYSize()}")
|
||||
texture_context = self.vr_right_texture.prepareNow(0, prepared_objects, gsg)
|
||||
if texture_context and hasattr(texture_context, 'getNativeId'):
|
||||
self.right_texture_id = texture_context.getNativeId()
|
||||
if self.right_texture_id > 0:
|
||||
print(f" ✅ 右眼纹理准备完成 ({self.vr_render_mode.value}): ID={self.right_texture_id}")
|
||||
else:
|
||||
print(" ❌ 右眼纹理准备失败")
|
||||
print(" ❌ 右眼纹理ID无效")
|
||||
return False
|
||||
else:
|
||||
print(" ❌ 右眼纹理准备失败")
|
||||
return False
|
||||
|
||||
# 标记纹理已准备
|
||||
self.textures_prepared = True
|
||||
@ -971,6 +994,13 @@ class VRManager(DirectObject):
|
||||
self.vr_left_eye_buffer = self.vr_pipeline_controller.get_left_buffer()
|
||||
self.vr_right_eye_buffer = self.vr_pipeline_controller.get_right_buffer()
|
||||
|
||||
# 🔧 关键修复:验证buffer有效性
|
||||
if not self.vr_left_eye_buffer or not self.vr_right_eye_buffer:
|
||||
print("❌ VR Pipeline buffer创建失败")
|
||||
print(f" 左眼buffer: {self.vr_left_eye_buffer}")
|
||||
print(f" 右眼buffer: {self.vr_right_eye_buffer}")
|
||||
return False
|
||||
|
||||
# 获取最终输出纹理(用于提交到OpenVR)
|
||||
left_textures = self.vr_pipeline_controller.get_left_textures()
|
||||
right_textures = self.vr_pipeline_controller.get_right_textures()
|
||||
@ -998,10 +1028,26 @@ class VRManager(DirectObject):
|
||||
if self.vr_left_eye_buffer and self.vr_right_eye_buffer:
|
||||
print(" 设置RenderPipeline DisplayRegion回调...")
|
||||
try:
|
||||
# 🔧 验证DisplayRegion数量
|
||||
left_dr_count = self.vr_left_eye_buffer.getNumDisplayRegions()
|
||||
right_dr_count = self.vr_right_eye_buffer.getNumDisplayRegions()
|
||||
|
||||
print(f" 左眼buffer DisplayRegion数量: {left_dr_count}")
|
||||
print(f" 右眼buffer DisplayRegion数量: {right_dr_count}")
|
||||
|
||||
if left_dr_count == 0 or right_dr_count == 0:
|
||||
print(" ❌ DisplayRegion未创建,无法设置回调")
|
||||
return False
|
||||
|
||||
# 获取RenderTarget创建的DisplayRegion
|
||||
left_dr = self.vr_left_eye_buffer.get_display_region(0)
|
||||
right_dr = self.vr_right_eye_buffer.get_display_region(0)
|
||||
|
||||
# 验证DisplayRegion有效性
|
||||
if not left_dr or not right_dr:
|
||||
print(" ❌ DisplayRegion无效")
|
||||
return False
|
||||
|
||||
# 设置渲染回调(与普通模式一致)
|
||||
left_dr.setDrawCallback(PythonCallbackObject(self.simple_left_cb))
|
||||
right_dr.setDrawCallback(PythonCallbackObject(self.simple_right_cb))
|
||||
@ -1015,6 +1061,11 @@ class VRManager(DirectObject):
|
||||
print(f" ⚠️ 设置DisplayRegion回调失败: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
# 🔧 关键修复:强制同步GraphicsEngine,确保所有buffer完全初始化
|
||||
print(" 同步GraphicsEngine...")
|
||||
self.world.graphicsEngine.renderFrame()
|
||||
|
||||
# 准备纹理并缓存OpenGL ID
|
||||
if not self._prepare_and_cache_textures():
|
||||
@ -1779,6 +1830,22 @@ class VRManager(DirectObject):
|
||||
self.world.qtWidget.synchronizer.setInterval(int(1000/144))
|
||||
print("✓ Qt Timer调整为144Hz,让OpenVR控制VR渲染节奏")
|
||||
|
||||
# 🔧 关键修复:检测并重建缺失的手柄visualizer
|
||||
# 当渲染模式切换时,visualizer可能被清理但控制器对象仍存在
|
||||
if hasattr(self, 'left_controller') and self.left_controller:
|
||||
if not self.left_controller.visualizer and self.left_controller.anchor_node:
|
||||
print("🔧 检测到左手柄visualizer缺失,正在重建...")
|
||||
self.left_controller._create_visualizer()
|
||||
if self.left_controller.visualizer:
|
||||
print("✅ 左手柄visualizer已重建")
|
||||
|
||||
if hasattr(self, 'right_controller') and self.right_controller:
|
||||
if not self.right_controller.visualizer and self.right_controller.anchor_node:
|
||||
print("🔧 检测到右手柄visualizer缺失,正在重建...")
|
||||
self.right_controller._create_visualizer()
|
||||
if self.right_controller.visualizer:
|
||||
print("✅ 右手柄visualizer已重建")
|
||||
|
||||
print("✅ VR模式已启用")
|
||||
return True
|
||||
|
||||
@ -1913,6 +1980,14 @@ class VRManager(DirectObject):
|
||||
print(" 重新启用VR...")
|
||||
self.enable_vr()
|
||||
|
||||
# 🔧 关键修复:重建所有手柄的visualizer以适配新渲染模式
|
||||
print(" 刷新手柄visualizer以适配新渲染模式...")
|
||||
if hasattr(self, 'left_controller') and self.left_controller:
|
||||
self.left_controller.recreate_visualizer()
|
||||
|
||||
if hasattr(self, 'right_controller') and self.right_controller:
|
||||
self.right_controller.recreate_visualizer()
|
||||
|
||||
print(f"✅ VR渲染模式已切换为 {self.vr_render_mode.value}")
|
||||
|
||||
# 保存配置
|
||||
|
||||
@ -754,6 +754,16 @@ class VRPipelineController:
|
||||
return False
|
||||
self.left_gbuffer, self.left_lighting, self.left_ambient, self.left_final = result
|
||||
|
||||
# 🔧 关键修复:确保左眼buffer完全初始化后再创建右眼
|
||||
# 验证左眼buffer状态
|
||||
left_buffer = self.left_final.get_internal_buffer() if self.left_final else None
|
||||
if not left_buffer:
|
||||
print("❌ 左眼内部buffer无效")
|
||||
self.cleanup_left()
|
||||
return False
|
||||
|
||||
print(" ✅ 左眼管线验证通过,准备创建右眼...")
|
||||
|
||||
# 创建右眼完整管线
|
||||
result = self.create_eye_pipeline("Right", width, height, right_camera)
|
||||
if not all(result):
|
||||
|
||||
@ -114,8 +114,8 @@ class VRControllerVisualizer:
|
||||
# 暂时注释身份标记功能,避免额外几何体造成悬空零件
|
||||
# self._apply_controller_identity_marker(steamvr_model)
|
||||
|
||||
# 设置手柄始终显示在上层
|
||||
self._set_always_on_top(steamvr_model)
|
||||
# 根据渲染模式设置渲染属性
|
||||
self._apply_render_mode_settings(steamvr_model)
|
||||
|
||||
print(f"✅ {self.controller.name}手柄已加载SteamVR官方模型(缩放: 1.0,实体渲染模式)")
|
||||
else:
|
||||
@ -363,6 +363,9 @@ class VRControllerVisualizer:
|
||||
trackpad_node.setColor(self.button_colors['trackpad'])
|
||||
trackpad_node.setMaterial(material)
|
||||
|
||||
# 应用渲染模式设置
|
||||
self._apply_render_mode_settings(self.model_node)
|
||||
|
||||
def _create_box_geometry(self, width, length, height):
|
||||
"""创建立方体几何体"""
|
||||
# 创建顶点格式
|
||||
@ -683,8 +686,57 @@ class VRControllerVisualizer:
|
||||
self.ray_node.removeNode()
|
||||
self._create_interaction_ray()
|
||||
|
||||
def _apply_render_mode_settings(self, model_node):
|
||||
"""根据当前渲染模式应用渲染设置
|
||||
|
||||
Args:
|
||||
model_node: 手柄模型节点
|
||||
"""
|
||||
if not model_node:
|
||||
return
|
||||
|
||||
# 检测是否启用RenderPipeline模式
|
||||
is_render_pipeline = False
|
||||
try:
|
||||
# 通过VR管理器获取渲染模式
|
||||
vr_manager = self.controller.vr_manager
|
||||
if hasattr(vr_manager, 'vr_render_mode'):
|
||||
from core.vr_manager import VRRenderMode
|
||||
is_render_pipeline = (vr_manager.vr_render_mode == VRRenderMode.RENDER_PIPELINE and
|
||||
vr_manager.render_pipeline_enabled)
|
||||
except Exception as e:
|
||||
print(f"⚠️ 检测渲染模式失败: {e}")
|
||||
|
||||
if is_render_pipeline:
|
||||
# RenderPipeline模式:使用正常深度测试,添加着色器标签
|
||||
print(f"🎨 {self.controller.name}手柄:应用RenderPipeline渲染模式")
|
||||
|
||||
# 设置着色器标签,使模型通过RenderPipeline的GBuffer渲染
|
||||
model_node.setTag("RenderPipeline", "1")
|
||||
|
||||
# 使用正常的深度测试和深度写入
|
||||
model_node.setDepthTest(True)
|
||||
model_node.setDepthWrite(True)
|
||||
|
||||
# 设置合适的渲染bin(transparent bin用于透明度支持)
|
||||
# 使用默认的opaque bin确保正常渲染
|
||||
model_node.clearBin()
|
||||
|
||||
# 递归设置所有子节点
|
||||
for child in model_node.findAllMatches("**"):
|
||||
child.setTag("RenderPipeline", "1")
|
||||
child.setDepthTest(True)
|
||||
child.setDepthWrite(True)
|
||||
child.clearBin()
|
||||
|
||||
print(f"✅ {self.controller.name}手柄已配置RenderPipeline渲染")
|
||||
else:
|
||||
# 普通模式:使用always-on-top设置
|
||||
print(f"🎨 {self.controller.name}手柄:应用普通渲染模式(always-on-top)")
|
||||
self._set_always_on_top(model_node)
|
||||
|
||||
def _set_always_on_top(self, model_node):
|
||||
"""设置手柄模型始终显示在上层,不被其他物体遮挡"""
|
||||
"""设置手柄模型始终显示在上层,不被其他物体遮挡(仅普通渲染模式)"""
|
||||
if not model_node:
|
||||
return
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user