Qualcomm_Snapdragon_VR_SDK SvrEye脚本简介(1)

从本文开始,介绍Unity版本的Qcom VR SDK中另一个比较重要的脚本SvrEye。

在之前的系列中讲到,SvrEye脚本是在程序运行后SvrManager动态添加到左右眼物体上的。具体SvrEye代码如下,后面章节中将具体介绍SvrEye中的属性和方法的作用。


    public static List Instances = new List();

    public enum eSide
    {
        Left = 1,
        Right = 2,
        Both = 3,
        [HideInInspector]
        Count = Both
    };

    public enum eType
    {
        RenderTexture = 0,
        StandardTexture = 1,
        EglTexture = 2,
    };

    public delegate void OnPostRenderCallback();
    public OnPostRenderCallback OnPostRenderListener;

    public delegate void OnPreRenderCallback();
    public OnPreRenderCallback OnPreRenderListener;

    [Tooltip("Layer depth stack")]
    public int layerDepth = 0;
    [Tooltip("Image display transform")]
    public Camera imageCamera;
    [Tooltip("Image type: 0/Camera render target, 1/Texture 2d, 2/External egl")]
    public eType imageType = eType.RenderTexture;
    [Tooltip("Image texture used when ImageType is StandardTexture")]
    public Texture imageTexture;
    [Tooltip("Image transform for scale, rotation and position (optional)")]
    public Transform imageTransform;
    [Tooltip("Image display region (camera clip space)")]
    public Vector4 clipLowerLeft = new Vector4(-1, -1, 0, 1);
    public Vector4 clipUpperLeft = new Vector4(-1, 1, 0, 1);
    public Vector4 clipUpperRight = new Vector4(1, 1, 0, 1);
    public Vector4 clipLowerRight = new Vector4(1, -1, 0, 1);
    [Tooltip("Image source region (texture uv space)")]
    public Vector2 uvLowerLeft = new Vector2(0, 0);
    public Vector2 uvUpperLeft = new Vector2(0, 1);
    public Vector2 uvUpperRight = new Vector2(1, 1);
    public Vector2 uvLowerRight = new Vector2(1, 0);
    [Tooltip("Render target scale factor")]
    public float resolutionScaleFactor = 1.0f;
    [Tooltip("Side mask")]
    public eSide side = eSide.Both;

    private float fovMargin = 0f;
    private RenderTextureFormat format = RenderTextureFormat.Default;
    private Vector2 resolution = new Vector2(1024.0f, 1024.0f);
    private int antiAliasing = 1;
    private int depth = 24;
    private int frustumType = 0;
    private const int bufferCount = 3;
    private RenderTexture[] eyeTextures = new RenderTexture[bufferCount];
    private int[] eyeTextureIds = new int[bufferCount];
    private int currentTextureIndex = 0;
    private Camera[] mainCameras = null;
    private bool dirty = false;
    private Coroutine recreateBuffersCoroutine = null;

    public int CompareTo(SvrEye that)
    {
        return this.layerDepth.CompareTo(that.layerDepth);
    }

    public float FovMargin
    {
        get { return fovMargin; }
        set { fovMargin = value; }
    }

    public int FrustumType
    {
        get { return frustumType; }
        set { frustumType = value; }
    }

    public void SetImage(Texture2D texture)
    {
        imageTexture = texture;
        InitializeBuffers();
    }

    public eType ImageType
    {
        get { return imageType; }
        set { imageType = value; }
    }

    public eSide Side
    {
        get { return side; }
        set { side = value; }
    }

    public RenderTextureFormat Format
    {
        get { return format; }
        set { SetDirty(format != value); format = value; }
    }
	
    public int AntiAliasing
    {
        get { return antiAliasing; }
        set { SetDirty(antiAliasing != value); antiAliasing = value; }
    }
	
    public int Depth
    {
        get { return depth; }
        set { SetDirty(depth != value); depth = value; }
    }
	
    public Vector2 Resolution
    {
        get { return resolution; }
        set { SetDirty(!Mathf.Approximately(resolution.x, value.x) || !Mathf.Approximately(resolution.y, value.y)); resolution = value; }
    }
	
    public float ResolutionScaleFactor
    {
        get { return resolutionScaleFactor; }
        set { SetDirty(!Mathf.Approximately(resolutionScaleFactor, value)); resolutionScaleFactor = value; }
    }
	
    void SetDirty(bool value)
    {
        dirty = dirty == true ? true : value;
    }

    public int TextureId
    {
        get { return eyeTextureIds[currentTextureIndex]; }
        set { eyeTextureIds[currentTextureIndex] = value; }
    }
    public Texture TexturePtr
    {
        get { return (imageTexture != null ? imageTexture : (Texture)eyeTextures[currentTextureIndex]); }
    }

    void Awake()
    {
        Instances.Add(this);
        AcquireComponents();
        InitializeCoords();
    }

    void OnDestroy()
    {
        Instances.Remove(this);
    }

    void AcquireComponents()
    {
        if (imageCamera == null) imageCamera = gameObject.GetComponent();
        Debug.Assert(imageCamera != null, "ImageCamera object required");
        mainCameras = imageCamera.GetComponentsInChildren();
    }


    void Start()
    {
        //Initialize(); Called by SvrManager.InitializeEyes()
    }

    void LateUpdate()
    {
        UpdateCoords();
    }

    public void Initialize()
    {
        InitializeBuffers();
        InitializeCameras();
    }

    void InitializeBuffers()
    {
        for (int i = 0; i < bufferCount; ++i)
        {
            if (eyeTextures[i] != null)
                eyeTextures[i].Release();
            switch(imageType)
            {
                case eType.RenderTexture:
                    eyeTextures[i] = new RenderTexture((int)(resolution.x * resolutionScaleFactor), (int)(resolution.y * resolutionScaleFactor), depth, format);
                    eyeTextures[i].antiAliasing = antiAliasing;
                    eyeTextures[i].Create();
                    eyeTextureIds[i] = eyeTextures[i].GetNativeTexturePtr().ToInt32();
                    Debug.Log("Create Render Texture with ID: " + eyeTextureIds[i] + " Width: " + eyeTextures[i].width + " Height: " + eyeTextures[i].height + " AA: " + eyeTextures[i].antiAliasing);
                    break;

                case eType.StandardTexture:
                    if (imageTexture) eyeTextureIds[i] = imageTexture.GetNativeTexturePtr().ToInt32();
                    break;

                case eType.EglTexture:
                    eyeTextureIds[i] = 0;
                    break;
            }
        }
        dirty = false;
    }

    void InitializeCameras()
    {
        ...
    }

    void InitializeCoords()
    {
       ...
    }

    void UpdateCoords()
    {
        if (imageTransform == null)
            return;

        var viewCamera = mainCameras[0];
        if (viewCamera == null)
            return;

        var extents = 0.5f * Vector3.one;
        var center = Vector3.zero;

        var worldLowerLeft = new Vector4(center.x - extents.x, center.y - extents.y, 0, 1);
        var worldUpperLeft = new Vector4(center.x - extents.x, center.y + extents.y, 0, 1);
        var worldUpperRight = new Vector4(center.x + extents.x, center.y + extents.y, 0, 1);
        var worldLowerRight = new Vector4(center.x + extents.x, center.y - extents.y, 0, 1);

		Matrix4x4 MVP = viewCamera.projectionMatrix * viewCamera.worldToCameraMatrix * imageTransform.localToWorldMatrix;

        clipLowerLeft = MVP * worldLowerLeft;
        clipUpperLeft = MVP * worldUpperLeft;
        clipUpperRight = MVP * worldUpperRight;
        clipLowerRight = MVP * worldLowerRight;
    }

    void OnPreRender()
    {
        ...
    }

    void SwapBuffers()
    {
        if (imageType != eType.RenderTexture) return;

        currentTextureIndex = ++currentTextureIndex % bufferCount;
        var targetTexture = eyeTextures[currentTextureIndex];
        if (targetTexture == null) return;

        for (int i = 0; i < mainCameras.Length; i++)
        {
            mainCameras[i].targetTexture = targetTexture;
        }
        targetTexture.DiscardContents();
    }

    void OnPostRender()
    {
        RecreateBuffersIfDirty();
        if (OnPostRenderListener != null)
        {
            OnPostRenderListener();
        }
    }
	
    void RecreateBuffersIfDirty()
    {
        if (dirty)
        {
            if (recreateBuffersCoroutine != null)
            {
                StopCoroutine(recreateBuffersCoroutine);
                recreateBuffersCoroutine = null;
            }

            recreateBuffersCoroutine = StartCoroutine(RecreateBuffersDeferred());
            dirty = false;
        }
    }
	
    IEnumerator RecreateBuffersDeferred()
    {
        int i = 0;
        while (i < bufferCount)
        {
            int index = currentTextureIndex - 1;
            index = index >= 0 ? index : bufferCount - 1;

            if (eyeTextures[index] != null)
                eyeTextures[index].Release();

            switch (imageType)
            {
                case eType.RenderTexture:
                    eyeTextures[index] = new RenderTexture((int)(resolution.x * resolutionScaleFactor), (int)(resolution.y * resolutionScaleFactor), depth, format);
                    eyeTextures[index].antiAliasing = antiAliasing;
                    eyeTextures[index].Create();
                    eyeTextureIds[index] = eyeTextures[index].GetNativeTexturePtr().ToInt32();
                    Debug.Log("Re-create Render Texture with ID: " + eyeTextureIds[index] + " Width: " + eyeTextures[index].width + " Height: " + eyeTextures[index].height + " AA: " + eyeTextures[index].antiAliasing);
                    break;

                case eType.StandardTexture:
                    if (imageTexture) eyeTextureIds[index] = imageTexture.GetNativeTexturePtr().ToInt32();
                    break;

                case eType.EglTexture:
                    eyeTextureIds[index] = 0;
                    break;
            }

            int prevTextureIndex = currentTextureIndex;
            yield return new WaitUntil(() => currentTextureIndex != prevTextureIndex);

            i++;
        }

        yield break;
    }


你可能感兴趣的:(Qualcomm_Snapdragon_VR_SDK SvrEye脚本简介(1))