StarSky 星图渲染模式与 DRO 相机系统依赖关系说明

1. 结论

StarSky 星图渲染模式涉及一些 DRO 项目中已经存在的相机相关内容,但涉及范围不是“重写或替换 DRO 相机系统”,而是“在 DRO 现有相机体系上追加星图渲染能力”。

具体分为两类:

  1. StarSky InfiniteDirection 模式与 DRO 现有相机系统有直接依赖。

    • 它会枚举运行时所有可用的 CameraType.Game 相机。

    • 它会给每个符合条件的相机挂载 CommandBuffer

    • 它会在开启窗口补偿时调用 CameraConfigLoader.TryGetCameraWindowStarSizeCompensation(...),读取 DRO 相机窗口的 RenderTexture 与 UI 显示尺寸。

    • 因此它直接依赖 DRO 已有的相机窗口创建、窗口相机管理和 RenderTexture 显示结构。

  2. StarSky WorldSphere 模式与 DRO 相机系统只有间接关系。

    • 它把星点作为普通世界空间 Mesh 渲染,不通过 CameraConfigLoader 查找相机窗口。

    • 它可以把星空球中心放到 Camera.main、当前相机目标、地球、太阳或场景对象中心。

    • 因此它依赖 DRO 的场景中心/当前目标体系,但不直接依赖 DRO 的相机窗口列表。

Assets/StarSky/** 这个 StarSky 包主体本身是独立的。它的 StarSky.Runtime.asmdef 没有引用 DRO 业务程序集。真正把 StarSky 接入 DRO 相机和 UI 的,是 Assets/NoloSpace/Scripts/NoloVR/** 下的接入层脚本。

2. 相关代码范围

2.1 StarSky 独立包

这些代码提供星表读取、星点生成、Shader 和独立 Demo,不直接依赖 DRO 相机窗口:

文件作用与 DRO 相机关系
Assets/StarSky/Runtime/StarSky.Runtime.asmdefStarSky 运行时程序集定义。references 为空,说明运行时包不依赖 DRO 程序集。无直接依赖
Assets/StarSky/Runtime/Visualization/GaiaSkySphereRenderer.cs读取 Gaia 星表,构建星点 Mesh,支持 WorldSphereInfiniteDirection 两种投影。只使用 Unity 基础渲染对象,不识别 DRO 相机窗口
Assets/StarSky/Runtime/Visualization/Shaders/StarSkyInfiniteDirectionBillboard.shader无限远方向星点 Shader,按当前相机矩阵把方向投影到屏幕。使用 Unity 当前相机矩阵和屏幕参数,不知道 DRO 相机结构
Assets/StarSky/Runtime/Visualization/Shaders/StarSkyAdditiveStarBillboard.shader世界球面星点 Shader。普通 MeshRenderer 渲染
Assets/StarSky/Runtime/Visualization/StarRenderCameraController.csStarSky Demo 用相机控制器。Demo/独立验证用,不接入 DRO 相机窗口

2.2 DRO 接入层

这些代码把 StarSky 接入 DRO 的天空盒 UI、场景渲染和相机窗口:

文件作用与相机系统关系
Assets/NoloSpace/Scripts/NoloVR/SkyboxAttributeController.cs在天空盒选择器中加入 StarSky InfiniteDirectionStarSky WorldSphere,选择时启用 StarSky。入口层,不直接访问相机,但决定是否启用会访问相机的渲染模式
Assets/NoloSpace/Scripts/NoloVR/VectorStarSkyManager.csDRO 中 StarSky 的总控;创建 VectorStarSky 节点,配置 GaiaSkySphereRendererStarSkyInfiniteDirectionRenderer间接依赖相机;InfiniteDirection 时配置逐相机渲染器,WorldSphere 时可用 Camera.main 作为中心
Assets/NoloSpace/Scripts/NoloVR/StarSkyInfiniteDirectionRenderer.csInfiniteDirection 模式的逐相机 CommandBuffer 渲染器。直接依赖所有活动 Game Camera,并可调用 CameraConfigLoader
Assets/NoloSpace/Scripts/NoloVR/StarSkySettingsPanelController.csStarSky 控制面板,提供亮度、星点大小、窗口补偿、中心模式等 UI。通过 VectorStarSkyManager.SetCameraWindowStarSizeCompensation(...) 开关相机窗口补偿
Assets/NoloSpace/Scripts/NoloVR/CameraConfigLoader.csDRO 原有相机窗口加载器,本次增加 TryGetCameraWindowStarSizeCompensation(...)StarSky 使用它查询相机窗口与 RenderTexture 尺寸关系
Assets/NoloSpace/Prefabs/天空盒子UI预设.prefab天空盒 UI 预设,Selector 中显式加入两项 StarSky 模式。UI 入口配置
Assets/NoloSpace/Scripts/NoloVR/SettingsManager.cs生成天空盒设置 UI,并把场景 SkyboxRenderer 传入 SkyboxAttributeControllerStarSky UI 入口的上游

3. 入口依赖链

StarSky 在 DRO 中不是场景里固定写死的单一对象,而是从设置面板的天空盒选项进入。

关键代码位置:

4. InfiniteDirection 模式的相机依赖

InfiniteDirection 是和 DRO 相机系统耦合最明确的部分。

4.1 逐相机 CommandBuffer

StarSkyInfiniteDirectionRenderer 在运行时每帧同步相机列表:

相关代码:

这意味着:

4.2 相机状态影响绘制内容

StarSkyInfiniteDirectionRenderer 会根据相机视锥剔除不需要绘制的星点 Mesh 面:

相关代码:

所以相机的这些属性会影响 StarSky:

4.3 对 DRO 相机窗口尺寸的依赖

窗口补偿链路如下:

关键代码:

这里直接涉及 DRO 已有相机系统中的对象:

DRO 相机对象被 StarSky 使用的字段/结构用途
CameraConfigLoader.Instance单例和 loadedCameras 字典找到当前 Unity Camera 对应的 DRO 相机窗口实例
CameraConfigLoader.CameraInstance.CameraUnity Camera匹配当前正在绘制的相机
CameraConfigLoader.CameraInstance.RenderTexture渲染纹理宽高作为相机真实输出像素尺寸
CameraWindow.RenderRTUI RawImage 或同类显示控件取得窗口中实际显示区域
RenderRT.rectTransform.rect.sizeUI 显示尺寸计算显示像素大小
Canvas.scaleFactorUI 缩放把 UI 尺寸换算到显示像素
Camera.targetTextureRenderTexture 绑定判断该相机是否是窗口输出相机

如果目标工程删除或改造了 CameraConfigLoaderCameraWindow.RenderRT 或窗口显示结构,InfiniteDirection 的窗口补偿功能就需要同步改写。否则可以关闭补偿,StarSky 仍可通过 CommandBuffer 渲染,只是窗口内星点大小可能不符合期望。

4.4 相机窗口创建路径

DRO 的窗口相机由 CameraConfigLoader 动态创建:

关键代码:

StarSky 不负责创建这些相机,只是在这些相机存在后为它们追加星图绘制命令。

5. WorldSphere 模式的相机关系

WorldSphere 模式不是逐相机 CommandBuffer 渲染,而是普通 MeshRenderer 渲染。

相关代码:

WorldSphere 与相机相关的主要点是中心模式:

CenterMode代码行为与相机关系
MainCamera返回 Camera.main.transform.position直接使用主相机位置
CurrentCameraTarget返回 orbitVectorMath.cameraTarget.transform.position依赖 DRO 主相机目标体系
ScenarioObjects返回 CelestialBodyManager.Instance.ScenarioObjects.position跟随场景对象根
EarthCelestialBodyManager.instantiatedBodies 查找 earth不直接依赖相机
SunBarycenterCelestialBodyManager.instantiatedBodies 查找 sun不直接依赖相机

关键代码:

因此 WorldSphere 可以被 DRO 相机看到,但它不需要 CameraConfigLoader 的相机窗口表。它的风险点更多是世界坐标、层级、cullingMask 和中心跟随策略,而不是窗口补偿。

6. StarSky 与传统天空盒/CommandBuffer 的关系

DRO 项目本来已有 SkyboxRenderer,它也会用 CommandBuffer 渲染天空盒。

StarSky 启用时,VectorStarSkyManager 会停用传统 SkyboxRenderer

退出 StarSky 时再恢复:

关键代码:

这说明 StarSky 与已有天空盒渲染系统是互斥启用关系,避免两个天空背景同时通过 CommandBuffer 叠加。

7. 工程依赖图

SettingsManager

SkyboxAttributeController

StarSkySettingsPanelController

VectorStarSkyManager

GaiaSkySphereRenderer
StarSky.Runtime

StarSkyInfiniteDirectionRenderer

SkyboxRenderer
legacy skybox

CelestialBodyManager / orbitVectorMath / Camera.main
WorldSphere center

GaiaCatalog / GaiaStarPropagator / JulianDateTT

Generated star meshes

Camera.allCameras

Unity Camera
Main Camera and DRO window cameras

CommandBuffer per Camera

StarSkyInfiniteDirectionBillboard.shader

CameraConfigLoader.TryGetCameraWindowStarSizeCompensation

CameraConfigLoader.loadedCameras

CameraInstance.Camera

CameraInstance.RenderTexture

CameraWindow.RenderRT.rectTransform

Canvas.scaleFactor

8. 依赖方向总结

8.1 编译/程序集方向

说明:

8.2 运行时方向

StarSky 不主动生成 DRO 相机,不修改 CameraConfigLoader 的加载流程,也不改变 CameraWindow 的生命周期。

9. 是否“涉及 DRO 已经存在的相机相关内容”

答案是:涉及,但范围明确。

相机相关内容是否涉及说明
主相机 Camera.mainWorldSphere 中心可跟随主相机;InfiniteDirection 枚举所有 Game Camera 时也会覆盖主相机
DRO 动态相机窗口CameraConfigLoader 创建的窗口相机会被 Camera.allCameras 捕获并挂 CommandBuffer
CameraConfigLoader.loadedCameras仅在开启窗口星点大小补偿时使用
CameraWindow.RenderRT仅用于计算窗口显示尺寸补偿
RenderTexture判断窗口相机、计算输出像素与 UI 显示像素比例
CameraConfigLoader.LoadCameras() 流程间接涉及StarSky 不调用它,但依赖其已创建的相机实例
CameraAttributeController搜索结果未发现 StarSky 直接调用它
CameraFrustumRenderer与 DRO 相机窗口自身功能有关,StarSky 不直接调用
ProFlareBatch / 光晕相机配置CameraConfigLoader 同时创建它,但 StarSky 没有直接依赖
OrbitCamera间接涉及WorldSphere 可跟随当前相机目标体系,但不直接引用 OrbitCamera 类型
SkyboxRendererStarSky 启用时会关闭传统天空盒 CommandBuffer renderer,退出时恢复

10. 维护和迁移注意事项

  1. 如果只迁移 Assets/StarSky/**,可以跑 StarSky Demo,但不会自动接入 DRO 天空盒 UI 和相机窗口。

  2. 如果要让 DRO 主界面能选择 StarSky,必须同时迁移或合并:

    • Assets/NoloSpace/Scripts/NoloVR/VectorStarSkyManager.cs

    • Assets/NoloSpace/Scripts/NoloVR/StarSkyInfiniteDirectionRenderer.cs

    • Assets/NoloSpace/Scripts/NoloVR/StarSkySettingsPanelController.cs

    • Assets/NoloSpace/Scripts/NoloVR/SkyboxAttributeController.cs 中 StarSky 相关逻辑

    • Assets/NoloSpace/Prefabs/天空盒子UI预设.prefab 中的两个 StarSky Selector 项

  3. 如果要让 DRO 相机窗口内星点大小稳定,还必须合并:

    • Assets/NoloSpace/Scripts/NoloVR/CameraConfigLoader.cs:348-396

    • 也就是 TryGetCameraWindowStarSizeCompensation(...) 方法。

  4. 如果目标工程相机窗口结构不同,不能直接照搬窗口补偿方法。需要把以下逻辑改成目标工程自己的窗口结构:

    • 如何从 Unity Camera 找到业务相机实例。

    • 如何拿到该相机的 RenderTexture

    • 如何拿到窗口中显示这个 RenderTexture 的 UI 矩形。

    • 如何换算 Canvas 缩放后的显示像素尺寸。

  5. 如果不需要窗口补偿,可以关闭 compensateCameraWindowStarSize。关闭后:

    • InfiniteDirection 仍会给窗口相机绘制星图。

    • 但当 RenderTexture 分辨率和 UI 显示尺寸差异很大时,窗口里星点可能偏大或偏小。

  6. 如果目标工程相机不在 CameraType.Game,或使用正交相机,当前 StarSkyInfiniteDirectionRenderer.ShouldRenderCamera(...) 会跳过这些相机。

  7. 如果目标工程对相机 cullingMask 或 layer 有特殊限制,需要检查 VectorStarSkyManager.ApplyLayerToGeneratedChildren()CameraConfigLoader 中窗口相机的 cullingMask。InfiniteDirection 通过 CommandBuffer 绘制,受材质和相机事件影响更大;WorldSphere 作为 MeshRenderer 更受 layer/cullingMask 影响。

  8. StarSky 启用时会关闭已有 SkyboxRenderer,这是为了避免传统天空盒和 StarSky 同时绘制。若目标工程有多个自定义天空背景 renderer,需要确认它们是否都应该被 DisableLegacySkyboxCommandRenderers() 管理。

11. 最小结论

StarSky 的核心星表和 Mesh 生成代码不依赖 DRO 原有相机系统;DRO 接入层依赖 StarSky。

但在 DRO 的实际星图渲染模式中,StarSky InfiniteDirection 明确涉及并依赖 DRO 已有相机窗口系统:它逐相机添加 CommandBuffer,并通过 CameraConfigLoader 查询窗口相机的 RenderTexture 与 UI 显示尺寸,给星点屏幕大小做补偿。

StarSky WorldSphere 则更像普通场景物体渲染,只在中心跟随策略上间接使用 Camera.main 或 DRO 当前相机目标体系,不依赖 CameraConfigLoader 的窗口相机列表。