Search Unity

[Solved] Right Eye Rendering Issues for VR Portal / Mirror Effect

Discussion in 'VR' started by krougeau, Oct 14, 2018.

  1. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    456
    I'm making use of an altered version of this code to create a "looking glass" portal. It's working fine in Unity 2018.1, but updating the project to 2018.2 breaks the portal effect. I've looked over the script and shader code in both installations & it doesn't look like Unity updated any code (nothing has changed), so there must be something going on elsewhere that's affecting it. I've poked, prodded, and scratched my head about it for days now and haven't gotten anywhere, so I thought I'd ask here for assistance.

    One thing that does occur to me after comparing the two versions side by side is that 2018.1 didn't have the ability to show the Left/Right/Both eyes in the Game view, while 2018.2 does. Not sure what difference that'd make or why, but it's the best lead I've got so far.

    Here's a screenshot of the Left and Right eye views, as well as my altered code (below). As you can see, the Left Eye is fine, but the Right Eye doesn't render correctly. Both eyes work fine in 2018.1, however, and there has been no change in the code. If you've any ideas or suggestions, I'd certainly appreciate your input!




    Mirror.cs:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine.Rendering;
    5.  
    6. public class Mirror : MonoBehaviour {
    7.  
    8.     public MirrorCamera portalCamera;
    9.     private Material _portalMaterial;
    10.  
    11.     private void Awake() {
    12.         _portalMaterial = GetComponent<MeshRenderer>().sharedMaterial;
    13.     }
    14.  
    15.     private void OnWillRenderObject() {
    16.         portalCamera.RenderIntoMaterial(_portalMaterial);
    17.     }
    18. }

    MirrorCamera.cs:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.XR;
    3. using System.Collections;
    4.  
    5. public class MirrorCamera : MonoBehaviour {
    6.    
    7.     public Transform CameraRig;
    8.     public Camera PlayerCamera;
    9.     public Transform MirrorCameraParent;
    10.     public Transform ReflectionTransform;
    11.     public int TextureSize = 1024;
    12.     public Camera VrEye;
    13.     public GameObject VrRig;
    14.     public bool RenderAsMirror = false;
    15.     Camera cameraForPortal;
    16.     RenderTexture leftEyeRenderTexture;
    17.     RenderTexture rightEyeRenderTexture;
    18.     Vector3 mirrorMatrixScale = new Vector3 (-1f, 1f, 1f);
    19.     Vector3 reflectionRotation = new Vector3 (0f, 180f, 0f);
    20.     Vector3 eyeOffset;
    21.  
    22.     protected void Awake() {
    23.         cameraForPortal = GetComponent<Camera>();
    24.         cameraForPortal.enabled = false;
    25.  
    26.         if (RenderAsMirror) {
    27.             leftEyeRenderTexture = new RenderTexture (Screen.width, Screen.height, 24);
    28.             rightEyeRenderTexture = new RenderTexture (Screen.width, Screen.height, 24);
    29.         }
    30.         else {
    31.             leftEyeRenderTexture = new RenderTexture (TextureSize, TextureSize, 24);
    32.             rightEyeRenderTexture = new RenderTexture (TextureSize, TextureSize, 24);
    33.         }
    34.  
    35.         int aa = QualitySettings.antiAliasing == 0 ? 1 : QualitySettings.antiAliasing;
    36.         leftEyeRenderTexture.antiAliasing = aa;
    37.         rightEyeRenderTexture.antiAliasing = aa;
    38.     }  
    39.  
    40.     public void RenderIntoMaterial(Material material) {
    41.         if (Camera.current == VrEye) {          
    42.             if (RenderAsMirror) {              
    43.                 ReflectionTransform.localPosition = Vector3.zero;
    44.                 ReflectionTransform.localRotation = Quaternion.identity;
    45.                 MirrorCameraParent.position = CameraRig.position;
    46.                 MirrorCameraParent.rotation = CameraRig.rotation;
    47.                 ReflectionTransform.localEulerAngles = reflectionRotation;
    48.  
    49.                 Vector3 centerAnchorPosition = MirrorCameraParent.localPosition;
    50.                 centerAnchorPosition.x *= -1;
    51.                 Vector3 centerAnchorRotation = -MirrorCameraParent.localEulerAngles;
    52.                 centerAnchorRotation.x *= -1;
    53.                 MirrorCameraParent.localPosition = centerAnchorPosition;
    54.                 MirrorCameraParent.localEulerAngles = centerAnchorRotation;
    55.             }
    56.  
    57.            transform.localRotation = VrEye.transform.localRotation;
    58.  
    59.             if (RenderAsMirror) {
    60.                 GL.invertCulling = true;
    61.             }
    62.             // left eye
    63.             eyeOffset = InputTracking.GetLocalPosition(XRNode.LeftEye);
    64.             eyeOffset.z = 0.0f;
    65.             transform.localPosition = VrEye.transform.localPosition + VrEye.transform.TransformVector (eyeOffset);
    66.  
    67.             if (RenderAsMirror)
    68.             {
    69.                cameraForPortal.projectionMatrix = VrEye.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);
    70.  
    71.             } else {
    72.                 cameraForPortal.projectionMatrix = VrEye.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);
    73.             }
    74.  
    75.             cameraForPortal.targetTexture = leftEyeRenderTexture;
    76.             cameraForPortal.Render();
    77.             material.SetTexture("_LeftEyeTexture", leftEyeRenderTexture);
    78.  
    79.             // right eye
    80.             eyeOffset = InputTracking.GetLocalPosition(XRNode.RightEye);
    81.             eyeOffset.z = 0.0f;
    82.             transform.localPosition = VrEye.transform.localPosition + VrEye.transform.TransformVector (eyeOffset);
    83.  
    84.             if (RenderAsMirror)
    85.             {
    86.                 cameraForPortal.projectionMatrix = VrEye.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);
    87.             } else {
    88.                 cameraForPortal.projectionMatrix = VrEye.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);
    89.             }
    90.  
    91.             cameraForPortal.targetTexture = rightEyeRenderTexture;
    92.             cameraForPortal.Render();
    93.             material.SetTexture("_RightEyeTexture", rightEyeRenderTexture);
    94.  
    95.             if (RenderAsMirror) {
    96.                 GL.invertCulling = false;
    97.             }
    98.         }
    99.     }
    100. }
    And finally, the shader code:
    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. Shader "MirrorShader" {
    4.     Properties{
    5.         _LeftEyeTexture("Left Eye Texture", 2D) = "white" {}
    6.         _RightEyeTexture("Right Eye Texture", 2D) = "white" {}
    7.     }
    8.  
    9.     SubShader{
    10.         Tags{ "RenderType" = "Opaque" }
    11.         LOD 100
    12.  
    13.         Pass
    14.         {
    15.             CGPROGRAM
    16.             #pragma vertex vert
    17.             #pragma fragment frag
    18.             #pragma target 3.0
    19.  
    20.             #pragma multi_compile __ STEREO_RENDER
    21.  
    22.             #include "UnityCG.cginc"
    23.  
    24.             struct appdata
    25.             {
    26.                 float4 vertex : POSITION;
    27.                 float2 uv:TEXCOORD0;
    28.             };
    29.  
    30.             struct v2f
    31.             {
    32.                 float2 uv : TEXCOORD0;
    33.             };
    34.  
    35.             sampler2D _LeftEyeTexture;
    36.             sampler2D _RightEyeTexture;
    37.  
    38.             v2f vert(appdata v, out float4 outpos : SV_POSITION)
    39.             {
    40.                 v2f o;
    41.                 outpos = UnityObjectToClipPos(v.vertex);
    42.  
    43.                 o.uv = v.uv;
    44.                 return o;
    45.             }
    46.  
    47.             fixed4 frag(v2f i, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
    48.             {
    49.                 float2 sUV = screenPos.xy / _ScreenParams.xy;
    50.  
    51.                 fixed4 col = fixed4(0.0, 0.0, 0.0, 0.0);
    52.                 if (unity_CameraProjection[0][2] < 0)
    53.                 {
    54.                     col = tex2D(_LeftEyeTexture, sUV);
    55.                 }
    56.                 else {
    57.                     col = tex2D(_RightEyeTexture, sUV);
    58.                 }
    59.  
    60.                 return col;
    61.             }
    62.             ENDCG
    63.         }
    64.     }
    65.  
    66.     Fallback "Diffuse"
    67. }
     
    plmx likes this.
  2. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    456
    *facepalm* Not sure when in the mix I switched it, but it looks like I must have changed to Single Pass from Multi Pass stereo rendering at some point in development. Switched back & things work as expected. Have to look around now and see what else is broken, as I figure there must have been a reason I changed it in the first place. Feeling like a dumbass, but relieved that it's working and I can move on.
     
    Last edited: Oct 16, 2018
  3. stevenwanhk

    stevenwanhk

    Joined:
    Jul 20, 2016
    Posts:
    113
    So do you mean this mirror plugin does not support single pass?
     
    krougeau likes this.
  4. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    456
    That does seem to be the case, yes.