Zion插件分析——ZionRender.cs

发表于2016-10-31
评论0 2.8k浏览
  Zion渲染器,控制渲染流程。和ZionVR一样,也是以单例形式工作,它有一个存放ZionCamera的数组,在渲染协程中将这些相机的位置移动到眼睛的位置,然后看到的场景渲染到各自的共享渲染纹理中去。对于某些设备,在头显失去焦点的时候,暂停画面渲染,画面保持不动(例如Oculus游戏中,摘下头盔,游戏暂停)。

UML类图
 

字段
 · _pauseRendering:是否暂停渲染
 · timeScale:游戏暂停前的timeScale
 · cameras:ZionCamera数组
 · isQuitting:是否正在退出
 · poses:保存3个跟踪设备的索引,分别是头显、左、右控制器
 · tracker:跟踪器,用于更新跟踪设备位置
 · PoseType:TODO 设置姿态
 · behaviour:各平台自己的ZionMonoBehaviour实现对象

属性
 · eye: 当前渲染的是左眼还是右眼
 · instance: 单例,获取时会检测场景中是否存在ZionRender.cs脚本,如果不存在,会新建一个名为[ZionVR]的空对象,在上面添加组件ZionRender
 ·  pauseRendering 是否暂停渲染

静态方法
Add(ZionCamera vrcam)
  如果没有正在退出,就调用instance.AddInternal(vrcam);,添加一个ZionCamera。
Remove(ZionCamera vrcam)
  如果没有正在退出,就调用instance.RemoveInternal(vrcam);,移除传入的ZionCamera。
Top()
  如果没有正在退出,就调用instance.TopInternal();,返回顶层相机(最后渲染的相机)。

构造方法
ZionRender ()
  实例化当前连接设备的MonoBehaviour。

?
1
2
3
4
public ZionRender ()
{
    behaviour = ZionVR.CreateMonoBehaviour ();
}

MonoBehaviour相关方法
OnDestroy()
  调用平台自己的MonoBehaviour实现方法behaviour.OnDestroy ();,并置当前单例为null。
OnApplicationQuit()
  程序退出,调用ZionVR的方法,安全释放资源。

?
1
2
isQuitting = true;
ZionVR.SafeDispose();

OnEnable()
  脚本甫一可用,先实例化ZionVR,得到单例vr,如果实例化成功,那么ZionVR应该已经获知当前连接设备的类型,如果没有连接任何VR设备,那么ZionVR.instance.vrType == EVRType.None,此时直接禁用ZionRender.cs,因为既然没有连接VR设备,就不需要走VR渲染的流程了,直接进去2D模式,使用Unity缺省渲染流程即可。
  接下来,获取平台的追踪器实现类。启动核心渲染协程,回调平台实现后的OnEnable()。

?
1
2
3
StartCoroutine("RenderLoop");
behaviour.OnEnable ();

  将脚本中的OnVRFocus加入到ZionEvent中的委托链。

?
1
ZionEvent.Listen (ZionEvent.VR_FOCUS, OnVRFocus);

OnDisable()
  停止所有协程,回调平台实现的OnDisable ()。

?
1
2
3
StopAllCoroutines();
behaviour.OnDisable ();

  将OnVRFocus从ZionEvent的委托链移除

?
1
ZionEvent.Remove (ZionEvent.VR_FOCUS, OnVRFocus);

Update()
  实时检测设备连接情况,一旦检测到未连接VR设备,禁用自身。更新手柄状态,最后回调平台实现的Update()。

?
1
behaviour.Update ();

FixedUpdate()
  回调平台实现的FixedUpdate()。

?
1
behaviour.FixedUpdate ();

实例方法
AddInternal(ZionCamera vrcam)
  将vrcam添加到脚本中的ZionCamera数组,但是不是直接添加,要根据相机组件的深度来排序数组。
Camera.depth 深度
  var depth : float
  Description描述
  Camera’s depth in the camera rendering order.
  相机在渲染顺序上的深度。
  Cameras with lower depth are rendered before cameras with higher depth.
  具有较低深度的相机将在较高深度的相机之前渲染。
1、得到vrcam上的相机组件camera。
2、获取目前的ZionCamera数组cameras的长度,用此长度加一,新建一个扩容数组sorted。
3、遍历cameras,一一与vrcam上的相机组件camera对比深度,如果cameras中的相机深度比camera的小,那么直接按同样的索引复制到sorted数组中。如果某相机的深度比camera的大,那么它这个位置就要腾给vrcam,然后剩余的位置就继续复制cameras中的ZionCamera。
4、对比复制完以后,更新当前ZionCamera数组为扩容数组sorted,使当前脚本可用。
RemoveInternal(ZionCamera vrcam)
  将vrcam从ZionCamera数组cameras中移除。由于可能重复添加过,所以先计算数组中vrcam的数量,然后新建一个数组,长度为现在的长度减去这个数量。再按顺序遍历数组,将不是vrcam的ZionCamera复制到新数组中,将当前的cameras更新为新数组。如果最后得到的数组为空,就禁用当前脚本。
TopInternal()
  获取顶层(最后渲染)的相机。由于存放的时候我们已经按照相机深度(渲染顺序)排序,所以此时取出cameras的最后一项即可。

?
1
return cameras[cameras.Length - 1];

RenderLoop()
  渲染协程,在每帧的最后调用。流程是
1、如果pauseRendering为true就忽略下面所有操作直接进行下一次流程。
2、获取跟踪设备的姿态,通知ZionEvent更新姿态。
3、执行手动渲染程序,如果是单眼模式,就渲染左眼,如果是双眼模式,渲染完左眼还要渲染右眼。

RenderEye(ZionVR vr, EEyeType eye)
  手动渲染。一次只能渲染一只眼睛,取眼睛的位置时要注意。ZionVR中两只眼睛的存放数组,下标从0开始。但是EEyeType的定义里,

?
1
2
3
4
5
6
public enum EEyeType
{
    Left = 1,
    Right = 2,
    Both = 3,
}

  所以,转成ZionVR的眼睛索引时,要减去一。
  遍历cameras,逐个相机渲染,排在前面的深度小,先渲染。将相机的位置移动到眼睛的位置,然后把此时相机看到的场景渲染到共享渲染纹理上去,然后执行相机渲染。最后恢复相机位置。

?
1
2
3
var camera = c.GetComponent();
camera.targetTexture = c.GetRenderTexture(eye, camera.hdr);
camera.Render();

GetCurPoses()
  获取所有跟踪器的位置,返回数组。
GetCurPose(uint index)
  获取单个追踪器的位置
OnVRFocus(params object[] args)
  action,实现暂停游戏逻辑,传入false时暂停。

?
1
2
timeScale = Time.timeScale;//保存暂停前的timeScale
Time.timeScale = 0.0f;


腾讯GAD游戏程序交流群:484290331Gad游戏开发核心用户群

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引