高级渲染添加

This commit is contained in:
Rowland 2025-10-10 16:10:55 +08:00
parent a8e27a56e9
commit 83fcb3ced4
5 changed files with 203 additions and 38 deletions

View File

@ -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
}

View File

@ -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()

View File

@ -567,16 +567,21 @@ 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模式创建失败回退到普通渲染模式")
# 🔧 关键修复:统一初始化流程
# 如果目标模式是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
if not self._create_vr_buffers():
print("❌ 创建VR渲染缓冲区失败")
return False
use_deferred_pipeline_switch = True
else:
print(f"🎨 VR渲染模式: {self.vr_render_mode.value}")
# 创建VR渲染缓冲区 - 始终用普通模式初始化
if not self._create_vr_buffers():
print("❌ 创建VR渲染缓冲区失败")
return False
@ -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,7 +760,7 @@ class VRManager(DirectObject):
return False
# 准备左眼纹理并缓存ID
if self.vr_left_texture:
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()
@ -751,7 +774,7 @@ class VRManager(DirectObject):
return False
# 准备右眼纹理并缓存ID
if self.vr_right_texture:
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()
@ -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}")
# 保存配置

View File

@ -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):

View File

@ -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