Beispiel #1
0
    private void CreatePortalCamera(Camera currentCamera, Camera.StereoscopicEye eye, out Camera portalCamera, ref RenderTexture portalTexture)
    {
        portalCamera = null;

        // Create the render texture (if needed)
        if (!portalTexture || m_OldReflectionTextureSize != m_TextureSize)                        // if it doesn't exist or the size has changed
        {
            if (portalTexture)                                                                    // if it does exist
            {
                DestroyImmediate(portalTexture);                                                  // destroy it first
            }
            portalTexture              = new RenderTexture(m_TextureSize, m_TextureSize, 24);     // <<<< make buffer size 24??
            portalTexture.name         = "__MirrorReflection" + eye.ToString() + GetInstanceID(); // create the name of the object
            portalTexture.isPowerOfTwo = true;                                                    // https://docs.unity3d.com/Manual/Textures.html: Non power of two texture assets can be scaled up at import time using the Non Power of 2 option in the advanced texture type in the import settings. Unity will scale texture contents as requested, and in the game they will behave just like any other texture, so they can still be compressed and very fast to load.
            portalTexture.hideFlags    = HideFlags.DontSave;                                      // The object will not be saved to the Scene. It will not be destroyed when a new Scene is loaded.

            portalTexture.antiAliasing = 4;                                                       // < <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ResourceIntensive but pretty

            m_OldReflectionTextureSize = m_TextureSize;                                           // save the old texture size
        }

        // Create camera with the render texture
        if (!m_PortalCameras.TryGetValue(currentCamera, out portalCamera))                                                                                             // if it does not yet exist in the dictionary, create it. If it does, assign it. (catch both not-in-dictionary and in-dictionary-but-deleted-GO)
        {
            GameObject go = new GameObject("Mirror Reflection Camera id" + GetInstanceID() + " for " + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox)); // create the new game object
            portalCamera                    = go.GetComponent <Camera>();
            portalCamera.enabled            = false;
            portalCamera.transform.position = transform.position;
            portalCamera.transform.rotation = transform.rotation;
            portalCamera.tag                = "PortalCam";    // Tag it as a portal camera so it doesn't participate in the additional CameraRender function
            //portalCamera.gameObject.AddComponent<FlareLayer>(); // Adds a flare layer to make Lens Flares appear in the image?? disabled for now
            go.hideFlags = HideFlags.DontSave;                // The object will not be saved to the Scene. It will not be destroyed when a new Scene is loaded.
            m_PortalCameras.Add(currentCamera, portalCamera); // add the newly created camera to the dictionary
        }
    }
    // On-demand create any objects we need
    private void CreateMirrorObjects(Camera currentCamera, Camera.StereoscopicEye eye, out Camera reflectionCamera, ref RenderTexture reflectionTexture)
    {
        reflectionCamera = null;


        // Reflection render texture
        if (!reflectionTexture || m_OldReflectionTextureSize != m_TextureSize)
        {
            if (reflectionTexture)
            {
                DestroyImmediate(reflectionTexture);
            }
            reflectionTexture              = new RenderTexture(m_TextureSize, m_TextureSize, 16);
            reflectionTexture.name         = "__MirrorReflection" + eye.ToString() + GetInstanceID();
            reflectionTexture.isPowerOfTwo = true;
            reflectionTexture.hideFlags    = HideFlags.DontSave;
            m_OldReflectionTextureSize     = m_TextureSize;
        }

        // Camera for reflection
        if (!m_ReflectionCameras.TryGetValue(currentCamera, out reflectionCamera)) // catch both not-in-dictionary and in-dictionary-but-deleted-GO
        {
            GameObject go = new GameObject("Mirror Reflection Camera id" + GetInstanceID() + " for " + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox));
            reflectionCamera                    = go.GetComponent <Camera>();
            reflectionCamera.enabled            = false;
            reflectionCamera.transform.position = transform.position;
            reflectionCamera.transform.rotation = transform.rotation;
            reflectionCamera.gameObject.AddComponent <FlareLayer>();
            go.hideFlags = HideFlags.DontSave;
            m_ReflectionCameras.Add(currentCamera, reflectionCamera);
        }
    }
    private void RenderCamera(Camera cam, Renderer rend, Camera.StereoscopicEye eye, ref RenderTexture reflectionTexture)
    {
        Camera reflectionCamera;

        CreateMirrorObjects(cam, eye, out reflectionCamera, ref reflectionTexture);

        // find out the reflection plane: position and normal in world space
        Vector3 pos    = transform.position;
        Vector3 normal = transform.up;

        // Optionally disable pixel lights for reflection
        int oldPixelLightCount = QualitySettings.pixelLightCount;

        if (m_DisablePixelLights)
        {
            QualitySettings.pixelLightCount = 0;
        }

        CopyCameraProperties(cam, reflectionCamera);

        // Render reflection
        // Reflect camera around reflection plane
        float   d = -Vector3.Dot(normal, pos) - m_ClipPlaneOffset;
        Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);

        Matrix4x4 reflection = Matrix4x4.zero;

        CalculateReflectionMatrix(ref reflection, reflectionPlane);

        Vector3   oldEyePos;
        Matrix4x4 worldToCameraMatrix;

        if (cam.stereoEnabled)
        {
            worldToCameraMatrix = cam.GetStereoViewMatrix(eye) * reflection;
            Vector3 eyeOffset;
            if (eye == Camera.StereoscopicEye.Left)
            {
                eyeOffset = InputTracking.GetLocalPosition(XRNode.LeftEye);
            }
            else
            {
                eyeOffset = InputTracking.GetLocalPosition(XRNode.RightEye);
            }
            eyeOffset.z = 0.0f;
            oldEyePos   = cam.transform.position + cam.transform.TransformVector(eyeOffset);
        }
        else
        {
            worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
            oldEyePos           = cam.transform.position;
        }

        Vector3 newEyePos = reflection.MultiplyPoint(oldEyePos);

        reflectionCamera.transform.position = newEyePos;

        reflectionCamera.worldToCameraMatrix = worldToCameraMatrix;

        // Setup oblique projection matrix so that near plane is our reflection
        // plane. This way we clip everything below/above it for free.
        Vector4 clipPlane = CameraSpacePlane(worldToCameraMatrix, pos, normal, 1.0f);

        Matrix4x4 projectionMatrix;



        //if (cam.stereoEnabled) projectionMatrix = HMDMatrix4x4ToMatrix4x4(cam.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left));
        //else
        //if (cam.stereoEnabled)
        //    projectionMatrix = HMDMatrix4x4ToMatrix4x4(SteamVR.instance.hmd.GetProjectionMatrix((Valve.VR.EVREye)eye, cam.nearClipPlane, cam.farClipPlane));
        //else
        if (cam.stereoEnabled)
        {
            projectionMatrix = cam.GetStereoProjectionMatrix(eye);
        }
        else
        {
            projectionMatrix = cam.projectionMatrix;
        }
        //projectionMatrix = cam.CalculateObliqueMatrix(clipPlane);
        MakeProjectionMatrixOblique(ref projectionMatrix, clipPlane);

        reflectionCamera.projectionMatrix = projectionMatrix;
        reflectionCamera.cullingMask      = m_ReflectLayers.value;
        reflectionCamera.targetTexture    = reflectionTexture;
        GL.invertCulling = true;
        //Vector3 euler = cam.transform.eulerAngles;
        //reflectionCamera.transform.eulerAngles = new Vector3(0, euler.y, euler.z);
        reflectionCamera.transform.rotation = cam.transform.rotation;
        reflectionCamera.Render();
        //reflectionCamera.transform.position = oldEyePos;
        GL.invertCulling = false;
        Material[] materials = rend.sharedMaterials;
        string     property  = "_ReflectionTex" + eye.ToString();

        foreach (Material mat in materials)
        {
            if (mat.HasProperty(property))
            {
                mat.SetTexture(property, reflectionTexture);
            }
        }

        // Restore pixel light count
        if (m_DisablePixelLights)
        {
            QualitySettings.pixelLightCount = oldPixelLightCount;
        }

        s_InsideRendering = false;
    }
Beispiel #4
0
    private void RenderCamera(Camera camera, Renderer rend, Camera.StereoscopicEye eye, ref RenderTexture portalTexture, ScriptableRenderContext SRC)
    {
        // Create the camera that will render the reflection
        Camera portalCamera;

        CreatePortalCamera(camera, eye, out portalCamera, ref portalTexture);
        CopyCameraProperties(camera, portalCamera); // Copy the properties of the (player) camera

        // find out the reflection plane: position and normal in world space
        Vector3 pos    = transform.position;                                //portalRenderPlane.transform.forward;//
        Vector3 normal = transform.TransformDirection(projectionDirection); // Alex: This is done because sometimes the object reflection direction does not align with what was the default (transform.forward), in this way, the user can specify this.
        //normal.Normalize(); // Alex: normalize in case someone enters a non-normalized vector. Turned off for now because it is a fun effect :P

        // Optionally disable pixel lights for reflection
        int oldPixelLightCount = QualitySettings.pixelLightCount;

        if (m_DisablePixelLights)
        {
            QualitySettings.pixelLightCount = 0;
        }

        // Reflect camera around reflection plane
        float   d = -Vector3.Dot(normal, pos) - m_ClipPlaneOffset;
        Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);

        Matrix4x4 reflection = Matrix4x4.identity;

        CalculateReflectionMatrix(ref reflection, reflectionPlane);

        // Calculate the Eye offsets
        Vector3   oldEyePos;
        Matrix4x4 worldToCameraMatrix;

        if (camera.stereoEnabled)
        {
            Vector3 eyeOffset;
            worldToCameraMatrix = camera.GetStereoViewMatrix(eye);

            InputTracking.GetNodeStates(nodeStates);
            XRNodeState leftEyeState  = findNode(nodeStates, XRNode.LeftEye);
            XRNodeState rightEyeState = findNode(nodeStates, XRNode.RightEye);

            if (eye == Camera.StereoscopicEye.Left)
            {
                leftEyeState.TryGetPosition(out eyeOffset); //eyeOffset = InputTracking.GetLocalPosition(XRNode.LeftEye); //<< Deprecated
            }
            else
            {
                rightEyeState.TryGetPosition(out eyeOffset); //eyeOffset = InputTracking.GetLocalPosition(XRNode.RightEye); //<< Deprecated
            }
            eyeOffset.z = 0.0f;
            oldEyePos   = camera.transform.position + camera.transform.TransformVector(eyeOffset);
        }
        else
        {
            worldToCameraMatrix = camera.worldToCameraMatrix;
            oldEyePos           = camera.transform.position;
        }

        // >>>Transform Camera<<<
        portalCamera.projectionMatrix = camera.projectionMatrix; // Match matrices <<<
        Vector3 newEyePos = reflection.MultiplyPoint(oldEyePos);

        portalCamera.transform.position = newEyePos;

        portalCamera.worldToCameraMatrix = worldToCameraMatrix * reflection;



        // Setup oblique projection matrix so that near plane is our reflection plane. This way we clip everything below/above it for free.
        Vector4 clipPlane = CameraSpacePlane(worldToCameraMatrix * reflection, pos, normal, 1.0f);

        Matrix4x4 projectionMatrix;

        if (camera.stereoEnabled)
        {
            projectionMatrix = camera.GetStereoProjectionMatrix(eye);
        }
        else
        {
            projectionMatrix = camera.projectionMatrix;
        }

        MakeProjectionMatrixOblique(ref projectionMatrix, clipPlane);

        portalCamera.projectionMatrix = projectionMatrix;
        portalCamera.cullingMask      = m_LayerMask.value; // Set culling mask <<<<
        portalCamera.targetTexture    = portalTexture;     // Set the target texture <<<

        GL.invertCulling = true;

        portalCamera.transform.rotation = camera.transform.rotation;

        UniversalRenderPipeline.RenderSingleCamera(SRC, portalCamera); // URP Version of: portalCamera.Render();

        GL.invertCulling = false;

        // Assign the rendertexture to the material
        Material[] materials = rend.sharedMaterials; // Why only get the shared materials?
        string     property  = "_ReflectionTex" + eye.ToString();

        foreach (Material mat in materials)
        {
            if (mat.HasProperty(property))
            {
                mat.SetTexture(property, portalTexture);
            }
        }

        // Restore pixel light count
        if (m_DisablePixelLights)
        {
            QualitySettings.pixelLightCount = oldPixelLightCount;
        }

        s_InsideRendering = false;
    }