"""
VR专用渲染Stages

为VR创建简化但完整的渲染管线，支持：
- GBuffer生成（延迟渲染基础）
- 光照计算（复用主Pipeline的LightManager）
- 最终合成（tone mapping + gamma校正）
"""

from panda3d.core import Shader
from RenderPipelineFile.rpcore.render_target import RenderTarget
from RenderPipelineFile.rpcore.globals import Globals
from RenderPipelineFile.rpcore.loader import RPLoader
from RenderPipelineFile.rpcore.util.shader_input_blocks import SimpleInputBlock


def _load_rp_shader(shader_name):
    """
    加载RenderPipeline shader

    Args:
        shader_name: shader文件名（如"apply_lights.frag.glsl"）

    Returns:
        Shader对象
    """
    default_vert = "/$$rp/shader/default_post_process.vert.glsl"
    frag_path = f"/$$rp/shader/{shader_name}"
    shader = RPLoader.load_shader(default_vert, frag_path)
    if shader:
        print(f"   ✅ Shader加载成功: {shader_name}")
    else:
        print(f"   ❌ Shader加载失败: {shader_name}")
    return shader


class VRGBufferStage:
    """VR GBuffer阶段 - 为单个VR眼睛创建GBuffer"""

    def __init__(self, name, pipeline):
        """
        初始化VR GBuffer Stage

        Args:
            name: stage名称（如"VR_Left_GBuffer"）
            pipeline: RenderPipeline实例引用
        """
        self.name = name
        self.pipeline = pipeline
        self.target = None
        self._camera = None

    def create(self, width, height, vr_camera):
        """
        创建GBuffer渲染目标

        Args:
            width: 渲染宽度
            height: 渲染高度
            vr_camera: VR相机NodePath
        """
        print(f"🎨 创建{self.name} GBuffer: {width}x{height}")

        # 创建RenderTarget
        self.target = RenderTarget(self.name)
        self.target.size = width, height

        # 添加GBuffer纹理附件（与主GBufferStage相同）
        self.target.add_color_attachment(bits=16, alpha=True)  # Data0
        self.target.add_depth_attachment(bits=32)               # Depth
        self.target.add_aux_attachments(bits=16, count=2)      # Data1, Data2

        # 准备渲染（绑定相机）
        self.target.prepare_render(vr_camera)
        self._camera = vr_camera

        # 🌌 关键修复：确保VR相机能看到天空盒
        # RenderPipeline的天空盒在render节点下，使用unsorted bin和shader effects
        if self.target._source_region:
            # 确保DisplayRegion支持所有bin排序
            self.target._source_region.setSort(20)  # 设置合理的sort值
            print(f"   ✓ DisplayRegion sort已设置")

        # 🔑 关键：设置VR相机的initial state为render的state
        # 这样VR相机才能继承RenderPipeline应用在render节点上的所有shader effects（包括天空盒shader）
        if vr_camera and vr_camera.node():
            # 使用Panda3D的内置render节点（通过builtins）
            try:
                from panda3d.core import NodePath
                import builtins
                if hasattr(builtins, 'render'):
                    render = builtins.render
                    vr_camera.node().setInitialState(render.getState())
                    print(f"   ✓ VR相机initial state已设置为render的state")
                else:
                    print(f"   ⚠️ builtins.render不存在，跳过initial state设置")
            except Exception as e:
                print(f"   ⚠️ 设置VR相机initial state失败: {e}")

        # 设置正常的背景色（与主窗口一致的天空色）
        if self.target.internal_buffer:
            buffer = self.target.internal_buffer
            buffer.setClearColorActive(True)
            # 使用主RenderPipeline的天空色（浅蓝色）
            buffer.setClearColor((0.53, 0.81, 0.92, 1.0))  # 天空蓝

            # 同时也设置DisplayRegion的clear
            if hasattr(self.target, '_source_region') and self.target._source_region:
                self.target._source_region.setClearColorActive(True)
                self.target._source_region.setClearColor((0.53, 0.81, 0.92, 1.0))

        print(f"✓ {self.name} GBuffer创建成功")
        return True

    def get_gbuffer_textures(self):
        """
        获取GBuffer纹理字典

        Returns:
            dict: 包含depth, data0, data1, data2的纹理字典
        """
        if not self.target:
            return None

        return {
            "depth": self.target.depth_tex,
            "data0": self.target.color_tex,
            "data1": self.target.aux_tex[0],
            "data2": self.target.aux_tex[1],
        }

    def make_gbuffer_ubo(self):
        """创建GBuffer UBO（与主GBufferStage相同）"""
        # 注意：必须使用固定的"GBuffer"名字，shader期望这个名字
        ubo = SimpleInputBlock("GBuffer")
        ubo.add_input("Depth", self.target.depth_tex)
        ubo.add_input("Data0", self.target.color_tex)
        ubo.add_input("Data1", self.target.aux_tex[0])
        ubo.add_input("Data2", self.target.aux_tex[1])
        return ubo

    def get_internal_buffer(self):
        """获取内部GraphicsOutput"""
        return self.target.internal_buffer if self.target else None

    def cleanup(self):
        """清理资源"""
        if self.target:
            self.target.remove()
            self.target = None
        print(f"✓ {self.name} GBuffer已清理")


class VRLightingStage:
    """VR光照阶段 - 使用主Pipeline的LightManager计算光照"""

    def __init__(self, name, pipeline):
        """
        初始化VR光照Stage

        Args:
            name: stage名称
            pipeline: RenderPipeline实例引用
        """
        self.name = name
        self.pipeline = pipeline
        self.target = None
        self._gbuffer_stage = None
        self._vr_main_scene_data = None

    def create(self, width, height, gbuffer_stage):
        """
        创建光照渲染目标

        Args:
            width: 渲染宽度
            height: 渲染高度
            gbuffer_stage: VRGBufferStage实例（提供GBuffer纹理）
        """
        print(f"💡 创建{self.name} 光照Stage: {width}x{height}")

        self._gbuffer_stage = gbuffer_stage
        self._width = width
        self._height = height

        # 创建光照输出目标
        self.target = RenderTarget(self.name)
        self.target.size = width, height
        self.target.add_color_attachment(bits=16, alpha=True)
        self.target.prepare_buffer()

        # 1. 创建GBuffer UBO（使用SimpleInputBlock）
        gbuffer_ubo = gbuffer_stage.make_gbuffer_ubo()
        gbuffer_ubo.bind_to(self.target)

        # 2. 从主Pipeline获取光照相关inputs
        self._bind_pipeline_inputs()

        # 3. 从主Pipeline获取光照相关pipes
        self._bind_pipeline_pipes()

        # 4. 覆盖VR特定的MainSceneData字段
        self._set_vr_scene_data()

        # 5. 加载光照shader
        self.target.shader = _load_rp_shader("apply_lights.frag.glsl")

        print(f"✓ {self.name} 光照Stage创建成功")
        return True

    def _bind_pipeline_inputs(self):
        """从主Pipeline获取光照相关shader inputs"""
        if not self.pipeline or not self.target:
            return

        stage_mgr = self.pipeline.stage_mgr
        inputs = stage_mgr.inputs

        # 必需的光照inputs
        required_inputs = [
            "AllLightsData",      # 光源数据
            "ShadowSourceData",   # 阴影源数据
            "IESDatasetTex",      # IES光照纹理
            "maxLightIndex",      # 最大光源索引
        ]

        for input_name in required_inputs:
            if input_name in inputs:
                self.target.set_shader_input(input_name, inputs[input_name])
                print(f"   ✓ 绑定input: {input_name}")
            else:
                print(f"   ⚠️ 缺失input: {input_name}")

        # 注意：不绑定MainSceneData InputBlock，因为它会被主Pipeline每帧覆盖
        # 我们会在_set_vr_scene_data()中手动设置所有需要的字段

    def _bind_pipeline_pipes(self):
        """从主Pipeline获取光照相关pipes"""
        if not self.pipeline or not self.target:
            return

        stage_mgr = self.pipeline.stage_mgr
        pipes = stage_mgr.pipes

        # 必需的光照pipes
        required_pipes = [
            "CellIndices",           # 光照剔除cell索引
            "PerCellLights",         # 每个cell的光源列表
            "PerCellLightsCounts",   # 每个cell的光源数量
            "ShadowAtlas",           # 阴影图集
            "ShadowAtlasPCF",        # PCF阴影图集
        ]

        # 可选的pipes
        optional_pipes = [
            "CombinedVelocity",  # 运动矢量（用于调试模式）
        ]

        for pipe_name in required_pipes:
            if pipe_name in pipes:
                pipe_value = pipes[pipe_name]
                if isinstance(pipe_value, (list, tuple)):
                    self.target.set_shader_input(pipe_name, *pipe_value)
                else:
                    self.target.set_shader_input(pipe_name, pipe_value)
                print(f"   ✓ 绑定pipe: {pipe_name}")
            else:
                print(f"   ❌ 缺失必需pipe: {pipe_name}")

        for pipe_name in optional_pipes:
            if pipe_name in pipes:
                pipe_value = pipes[pipe_name]
                if isinstance(pipe_value, (list, tuple)):
                    self.target.set_shader_input(pipe_name, *pipe_value)
                else:
                    self.target.set_shader_input(pipe_name, pipe_value)
                print(f"   ✓ 绑定可选pipe: {pipe_name}")

    def _set_vr_scene_data(self):
        """创建VR专用的MainSceneData UBO（从主Pipeline复制，覆盖VR特定值）"""
        from panda3d.core import LVecBase2i
        from RenderPipelineFile.rpcore.util.shader_input_blocks import GroupedInputBlock
        import math

        # 从主Pipeline的MainSceneData InputBlock获取
        main_input_block = self.pipeline.stage_mgr.input_blocks.get("MainSceneData")
        if not main_input_block:
            print("   ⚠️ 主Pipeline的MainSceneData不存在")
            return

        # 创建VR专用的MainSceneData GroupedInputBlock
        vr_main_scene_data = GroupedInputBlock("MainSceneData")

        # 注册所有字段（与主Pipeline相同的类型）
        field_definitions = [
            ("camera_pos", "vec3"),
            ("view_proj_mat_no_jitter", "mat4"),
            ("last_view_proj_mat_no_jitter", "mat4"),
            ("last_inv_view_proj_mat_no_jitter", "mat4"),
            ("view_mat_z_up", "mat4"),
            ("proj_mat", "mat4"),
            ("inv_proj_mat", "mat4"),
            ("view_mat_billboard", "mat4"),
            ("frame_delta", "float"),
            ("smooth_frame_delta", "float"),
            ("frame_time", "float"),
            ("current_film_offset", "vec2"),
            ("frame_index", "int"),
            ("screen_size", "ivec2"),
            ("native_screen_size", "ivec2"),
            ("lc_tile_count", "ivec2"),
            ("ws_frustum_directions", "mat4"),
            ("vs_frustum_directions", "mat4"),
        ]

        for field_name, field_type in field_definitions:
            vr_main_scene_data.register_pta(field_name, field_type)

        # 复制主Pipeline的所有字段值
        for field_name, _ in field_definitions:
            try:
                value = main_input_block.get_input(field_name)
                vr_main_scene_data.update_input(field_name, value)
            except:
                pass  # 某些字段可能不存在

        # 覆盖VR特定的分辨率字段
        vr_resolution = LVecBase2i(self._width, self._height)
        vr_main_scene_data.update_input("screen_size", vr_resolution)
        vr_main_scene_data.update_input("native_screen_size", vr_resolution)

        # 计算并设置VR的光照剔除tile数量
        tile_size_x = self.pipeline.settings["lighting.culling_grid_size_x"]
        tile_size_y = self.pipeline.settings["lighting.culling_grid_size_y"]
        num_tiles_x = int(math.ceil(self._width / float(tile_size_x)))
        num_tiles_y = int(math.ceil(self._height / float(tile_size_y)))
        vr_tile_count = LVecBase2i(num_tiles_x, num_tiles_y)
        vr_main_scene_data.update_input("lc_tile_count", vr_tile_count)

        # 绑定VR专用的MainSceneData UBO
        vr_main_scene_data.bind_to(self.target)

        # 保存引用以便后续更新
        self._vr_main_scene_data = vr_main_scene_data

        print(f"   ✓ 创建VR专用MainSceneData UBO")
        print(f"   ✓ VR screen_size: {self._width}x{self._height}")
        print(f"   ✓ VR lc_tile_count: {num_tiles_x}x{num_tiles_y}")

    def get_shaded_texture(self):
        """获取光照计算后的纹理"""
        return self.target.color_tex if self.target else None

    def cleanup(self):
        """清理资源"""
        if self.target:
            self.target.remove()
            self.target = None
        print(f"✓ {self.name} 光照Stage已清理")


class VRAmbientStage:
    """VR环境光阶段 - 计算基于图像的照明(IBL)"""

    def __init__(self, name, pipeline):
        """
        初始化VR环境光Stage

        Args:
            name: stage名称
            pipeline: RenderPipeline实例引用
        """
        self.name = name
        self.pipeline = pipeline
        self.target = None
        self._lighting_stage = None
        self._gbuffer_stage = None
        self._vr_main_scene_data = None

    def create(self, width, height, lighting_stage, gbuffer_stage):
        """
        创建环境光渲染目标

        Args:
            width: 渲染宽度
            height: 渲染高度
            lighting_stage: VRLightingStage实例（提供直接光照结果）
            gbuffer_stage: VRGBufferStage实例（提供GBuffer数据）
        """
        print(f"🌍 创建{self.name} 环境光Stage: {width}x{height}")

        self._lighting_stage = lighting_stage
        self._gbuffer_stage = gbuffer_stage
        self._width = width
        self._height = height

        # 创建环境光输出目标
        self.target = RenderTarget(self.name)
        self.target.size = width, height
        self.target.add_color_attachment(bits=16, alpha=True)
        self.target.prepare_buffer()

        # 1. 设置直接光照输入（ShadedScene）
        shaded_tex = lighting_stage.get_shaded_texture()
        if shaded_tex:
            self.target.set_shader_input("ShadedScene", shaded_tex)

        # 2. 绑定GBuffer UBO
        gbuffer_ubo = gbuffer_stage.make_gbuffer_ubo()
        gbuffer_ubo.bind_to(self.target)

        # 3. 从主Pipeline获取环境相关inputs
        self._bind_environment_inputs()

        # 4. 覆盖VR特定的MainSceneData字段
        self._set_vr_scene_data()

        # 5. 加载环境光shader
        self.target.shader = _load_rp_shader("ambient_stage.frag.glsl")

        print(f"✓ {self.name} 环境光Stage创建成功")
        return True

    def _bind_environment_inputs(self):
        """从主Pipeline获取环境相关shader inputs"""
        if not self.pipeline or not self.target:
            return

        stage_mgr = self.pipeline.stage_mgr
        inputs = stage_mgr.inputs
        pipes = stage_mgr.pipes

        # 必需的环境inputs
        required_inputs = [
            "DefaultEnvmap",         # 默认环境立方体贴图
            "PrefilteredBRDF",       # 预计算BRDF查找表
            "PrefilteredMetalBRDF",  # 金属材质BRDF
            "PrefilteredCoatBRDF",   # 涂层材质BRDF
        ]

        for input_name in required_inputs:
            if input_name in inputs:
                self.target.set_shader_input(input_name, inputs[input_name])
                print(f"   ✓ 绑定环境input: {input_name}")
            else:
                print(f"   ⚠️ 缺失环境input: {input_name}")

        # 注意：不绑定MainSceneData InputBlock，因为它会被主Pipeline每帧覆盖
        # 我们会在_set_vr_scene_data()中手动设置所有需要的字段

        # 可选的AO相关pipes（如果启用了AO插件）
        optional_pipes = [
            "AmbientOcclusion",  # 环境光遮蔽
            "SkyAO",             # 天空AO
        ]

        for pipe_name in optional_pipes:
            if pipe_name in pipes:
                pipe_value = pipes[pipe_name]
                if isinstance(pipe_value, (list, tuple)):
                    self.target.set_shader_input(pipe_name, *pipe_value)
                else:
                    self.target.set_shader_input(pipe_name, pipe_value)
                print(f"   ✓ 绑定可选AO pipe: {pipe_name}")

    def _set_vr_scene_data(self):
        """创建VR专用的MainSceneData UBO（从主Pipeline复制，覆盖VR特定值）"""
        from panda3d.core import LVecBase2i
        from RenderPipelineFile.rpcore.util.shader_input_blocks import GroupedInputBlock
        import math

        # 从主Pipeline的MainSceneData InputBlock获取
        main_input_block = self.pipeline.stage_mgr.input_blocks.get("MainSceneData")
        if not main_input_block:
            print("   ⚠️ 主Pipeline的MainSceneData不存在")
            return

        # 创建VR专用的MainSceneData GroupedInputBlock
        vr_main_scene_data = GroupedInputBlock("MainSceneData")

        # 注册所有字段（与主Pipeline相同的类型）
        field_definitions = [
            ("camera_pos", "vec3"),
            ("view_proj_mat_no_jitter", "mat4"),
            ("last_view_proj_mat_no_jitter", "mat4"),
            ("last_inv_view_proj_mat_no_jitter", "mat4"),
            ("view_mat_z_up", "mat4"),
            ("proj_mat", "mat4"),
            ("inv_proj_mat", "mat4"),
            ("view_mat_billboard", "mat4"),
            ("frame_delta", "float"),
            ("smooth_frame_delta", "float"),
            ("frame_time", "float"),
            ("current_film_offset", "vec2"),
            ("frame_index", "int"),
            ("screen_size", "ivec2"),
            ("native_screen_size", "ivec2"),
            ("lc_tile_count", "ivec2"),
            ("ws_frustum_directions", "mat4"),
            ("vs_frustum_directions", "mat4"),
        ]

        for field_name, field_type in field_definitions:
            vr_main_scene_data.register_pta(field_name, field_type)

        # 复制主Pipeline的所有字段值
        for field_name, _ in field_definitions:
            try:
                value = main_input_block.get_input(field_name)
                vr_main_scene_data.update_input(field_name, value)
            except:
                pass  # 某些字段可能不存在

        # 覆盖VR特定的分辨率字段
        vr_resolution = LVecBase2i(self._width, self._height)
        vr_main_scene_data.update_input("screen_size", vr_resolution)
        vr_main_scene_data.update_input("native_screen_size", vr_resolution)

        # 计算并设置VR的光照剔除tile数量
        tile_size_x = self.pipeline.settings["lighting.culling_grid_size_x"]
        tile_size_y = self.pipeline.settings["lighting.culling_grid_size_y"]
        num_tiles_x = int(math.ceil(self._width / float(tile_size_x)))
        num_tiles_y = int(math.ceil(self._height / float(tile_size_y)))
        vr_tile_count = LVecBase2i(num_tiles_x, num_tiles_y)
        vr_main_scene_data.update_input("lc_tile_count", vr_tile_count)

        # 绑定VR专用的MainSceneData UBO
        vr_main_scene_data.bind_to(self.target)

        # 保存引用以便后续更新
        self._vr_main_scene_data = vr_main_scene_data

        print(f"   ✓ 创建VR专用MainSceneData UBO")
        print(f"   ✓ VR screen_size: {self._width}x{self._height}")
        print(f"   ✓ VR lc_tile_count: {num_tiles_x}x{num_tiles_y}")

    def get_ambient_scene_texture(self):
        """获取带环境光的场景纹理"""
        return self.target.color_tex if self.target else None

    def cleanup(self):
        """清理资源"""
        if self.target:
            self.target.remove()
            self.target = None
        print(f"✓ {self.name} 环境光Stage已清理")


class VRFinalStage:
    """VR最终合成阶段 - Tone mapping + Gamma校正"""

    def __init__(self, name, pipeline):
        """
        初始化VR最终合成Stage

        Args:
            name: stage名称
            pipeline: RenderPipeline实例引用
        """
        self.name = name
        self.pipeline = pipeline
        self.target = None
        self._ambient_stage = None
        self._vr_main_scene_data = None

    def create(self, width, height, ambient_stage):
        """
        创建最终合成目标

        Args:
            width: 渲染宽度
            height: 渲染高度
            ambient_stage: VRAmbientStage实例（提供带环境光的场景）
        """
        print(f"🎬 创建{self.name} Final Stage: {width}x{height}")

        self._ambient_stage = ambient_stage
        self._width = width
        self._height = height

        # 创建最终输出目标
        self.target = RenderTarget(self.name)
        self.target.size = width, height
        self.target.add_color_attachment(bits=16, alpha=True)
        self.target.prepare_buffer()

        # 设置带环境光的场景输入
        ambient_scene_tex = ambient_stage.get_ambient_scene_texture()
        if ambient_scene_tex:
            self.target.set_shader_input("ShadedScene", ambient_scene_tex)

        # 设置VR专用的MainSceneData UBO
        self._set_vr_scene_data()

        # 加载最终合成shader（tone mapping + gamma校正）
        self.target.shader = _load_rp_shader("final_stage.frag.glsl")

        print(f"✓ {self.name} Final Stage创建成功")
        return True

    def _set_vr_scene_data(self):
        """创建VR专用的MainSceneData UBO（从主Pipeline复制，覆盖VR特定值）"""
        from panda3d.core import LVecBase2i
        from RenderPipelineFile.rpcore.util.shader_input_blocks import GroupedInputBlock
        import math

        # 从主Pipeline的MainSceneData InputBlock获取
        main_input_block = self.pipeline.stage_mgr.input_blocks.get("MainSceneData")
        if not main_input_block:
            print("   ⚠️ 主Pipeline的MainSceneData不存在")
            return

        # 创建VR专用的MainSceneData GroupedInputBlock
        vr_main_scene_data = GroupedInputBlock("MainSceneData")

        # 注册所有字段（与主Pipeline相同的类型）
        field_definitions = [
            ("camera_pos", "vec3"),
            ("view_proj_mat_no_jitter", "mat4"),
            ("last_view_proj_mat_no_jitter", "mat4"),
            ("last_inv_view_proj_mat_no_jitter", "mat4"),
            ("view_mat_z_up", "mat4"),
            ("proj_mat", "mat4"),
            ("inv_proj_mat", "mat4"),
            ("view_mat_billboard", "mat4"),
            ("frame_delta", "float"),
            ("smooth_frame_delta", "float"),
            ("frame_time", "float"),
            ("current_film_offset", "vec2"),
            ("frame_index", "int"),
            ("screen_size", "ivec2"),
            ("native_screen_size", "ivec2"),
            ("lc_tile_count", "ivec2"),
            ("ws_frustum_directions", "mat4"),
            ("vs_frustum_directions", "mat4"),
        ]

        for field_name, field_type in field_definitions:
            vr_main_scene_data.register_pta(field_name, field_type)

        # 复制主Pipeline的所有字段值
        for field_name, _ in field_definitions:
            try:
                value = main_input_block.get_input(field_name)
                vr_main_scene_data.update_input(field_name, value)
            except:
                pass  # 某些字段可能不存在

        # 覆盖VR特定的分辨率字段
        vr_resolution = LVecBase2i(self._width, self._height)
        vr_main_scene_data.update_input("screen_size", vr_resolution)
        vr_main_scene_data.update_input("native_screen_size", vr_resolution)

        # 计算并设置VR的光照剔除tile数量
        tile_size_x = self.pipeline.settings["lighting.culling_grid_size_x"]
        tile_size_y = self.pipeline.settings["lighting.culling_grid_size_y"]
        num_tiles_x = int(math.ceil(self._width / float(tile_size_x)))
        num_tiles_y = int(math.ceil(self._height / float(tile_size_y)))
        vr_tile_count = LVecBase2i(num_tiles_x, num_tiles_y)
        vr_main_scene_data.update_input("lc_tile_count", vr_tile_count)

        # 绑定VR专用的MainSceneData UBO
        vr_main_scene_data.bind_to(self.target)

        # 保存引用以便后续更新
        self._vr_main_scene_data = vr_main_scene_data

        print(f"   ✓ 创建VR专用MainSceneData UBO (Final)")
        print(f"   ✓ VR screen_size: {self._width}x{self._height}")
        print(f"   ✓ VR lc_tile_count: {num_tiles_x}x{num_tiles_y}")

    def get_final_texture(self):
        """获取最终输出纹理（用于提交到OpenVR）"""
        return self.target.color_tex if self.target else None

    def get_internal_buffer(self):
        """获取内部GraphicsOutput"""
        return self.target.internal_buffer if self.target else None

    def cleanup(self):
        """清理资源"""
        if self.target:
            self.target.remove()
            self.target = None
        print(f"✓ {self.name} Final Stage已清理")


class VRPipelineController:
    """VR渲染管线控制器 - 管理左右眼的完整渲染管线"""

    def __init__(self, pipeline):
        """
        初始化VR Pipeline控制器

        Args:
            pipeline: 主RenderPipeline实例
        """
        self.pipeline = pipeline

        # 左眼stages
        self.left_gbuffer = None
        self.left_lighting = None
        self.left_ambient = None
        self.left_final = None

        # 右眼stages
        self.right_gbuffer = None
        self.right_lighting = None
        self.right_ambient = None
        self.right_final = None

    def create_eye_pipeline(self, eye_name, width, height, vr_camera):
        """
        为单个眼睛创建完整的渲染管线

        Args:
            eye_name: "Left" 或 "Right"
            width: 渲染宽度
            height: 渲染高度
            vr_camera: VR相机NodePath

        Returns:
            tuple: (gbuffer_stage, lighting_stage, ambient_stage, final_stage)
        """
        print(f"\n🚀 创建VR {eye_name}眼渲染管线")

        # 1. 创建GBuffer Stage
        gbuffer = VRGBufferStage(f"VR_{eye_name}_GBuffer", self.pipeline)
        if not gbuffer.create(width, height, vr_camera):
            return None, None, None, None

        # 2. 创建光照Stage（直接光照）
        lighting = VRLightingStage(f"VR_{eye_name}_Lighting", self.pipeline)
        if not lighting.create(width, height, gbuffer):
            gbuffer.cleanup()
            return None, None, None, None

        # 3. 创建环境光Stage（IBL）
        ambient = VRAmbientStage(f"VR_{eye_name}_Ambient", self.pipeline)
        if not ambient.create(width, height, lighting, gbuffer):
            lighting.cleanup()
            gbuffer.cleanup()
            return None, None, None, None

        # 4. 创建最终合成Stage（tone mapping + gamma）
        final = VRFinalStage(f"VR_{eye_name}_Final", self.pipeline)
        if not final.create(width, height, ambient):
            ambient.cleanup()
            lighting.cleanup()
            gbuffer.cleanup()
            return None, None, None, None

        print(f"✅ VR {eye_name}眼渲染管线创建成功\n")
        return gbuffer, lighting, ambient, final

    def create_stereo_pipeline(self, width, height, left_camera, right_camera):
        """
        创建立体渲染管线（左右眼）- 完整版本

        Args:
            width: 每个眼睛的渲染宽度
            height: 每个眼睛的渲染高度
            left_camera: 左眼相机NodePath
            right_camera: 右眼相机NodePath

        Returns:
            bool: 创建是否成功
        """
        print("=" * 60)
        print("🎯 开始创建VR立体渲染管线（完整版）")
        print("=" * 60)

        # 创建左眼完整管线
        result = self.create_eye_pipeline("Left", width, height, left_camera)
        if not all(result):
            print("❌ 左眼渲染管线创建失败")
            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):
            print("❌ 右眼渲染管线创建失败")
            self.cleanup_left()
            return False
        self.right_gbuffer, self.right_lighting, self.right_ambient, self.right_final = result

        print("\n" + "=" * 60)
        print("✅ VR立体渲染管线创建成功！")
        print("   管线流程: GBuffer → Lighting → Ambient → Final")
        print("=" * 60)
        return True

    def get_left_textures(self):
        """获取左眼的所有纹理"""
        if not self.left_final:
            return None

        return {
            "final": self.left_final.get_final_texture(),
            "gbuffer": self.left_gbuffer.get_gbuffer_textures() if self.left_gbuffer else None
        }

    def get_right_textures(self):
        """获取右眼的所有纹理"""
        if not self.right_final:
            return None

        return {
            "final": self.right_final.get_final_texture(),
            "gbuffer": self.right_gbuffer.get_gbuffer_textures() if self.right_gbuffer else None
        }

    def get_left_buffer(self):
        """获取左眼Final stage的内部buffer（用于设置DrawCallback）"""
        return self.left_final.get_internal_buffer() if self.left_final else None

    def get_right_buffer(self):
        """获取右眼Final stage的内部buffer（用于设置DrawCallback）"""
        return self.right_final.get_internal_buffer() if self.right_final else None

    def cleanup_left(self):
        """清理左眼资源"""
        if self.left_final:
            self.left_final.cleanup()
            self.left_final = None
        if self.left_ambient:
            self.left_ambient.cleanup()
            self.left_ambient = None
        if self.left_lighting:
            self.left_lighting.cleanup()
            self.left_lighting = None
        if self.left_gbuffer:
            self.left_gbuffer.cleanup()
            self.left_gbuffer = None

    def cleanup_right(self):
        """清理右眼资源"""
        if self.right_final:
            self.right_final.cleanup()
            self.right_final = None
        if self.right_ambient:
            self.right_ambient.cleanup()
            self.right_ambient = None
        if self.right_lighting:
            self.right_lighting.cleanup()
            self.right_lighting = None
        if self.right_gbuffer:
            self.right_gbuffer.cleanup()
            self.right_gbuffer = None

    def cleanup_all(self):
        """清理所有VR渲染资源"""
        print("\n🧹 清理VR渲染管线...")
        self.cleanup_left()
        self.cleanup_right()
        print("✓ VR渲染管线已清理\n")
