ResetProjectionMatrix() public method

Make the projection reflect normal camera's parameters.

public ResetProjectionMatrix ( ) : void
return void
コード例 #1
0
 // callback to be called before any culling
 public void PreCullAdjustFOV(Camera cam)
 {
     if (cam == thisCamera)
     {
         cam.fieldOfView = 70;
         //These are needed for the FOV change to take effect.
         cam.ResetWorldToCameraMatrix();
         cam.ResetProjectionMatrix();
     }
 }
コード例 #2
0
 static public int ResetProjectionMatrix(IntPtr l)
 {
     try{
         UnityEngine.Camera self = (UnityEngine.Camera)checkSelf(l);
         self.ResetProjectionMatrix();
         return(0);
     }
     catch (Exception e) {
         LuaDLL.luaL_error(l, e.ToString());
         return(0);
     }
 }
コード例 #3
0
 static public int ResetProjectionMatrix(IntPtr l)
 {
     try {
         UnityEngine.Camera self = (UnityEngine.Camera)checkSelf(l);
         self.ResetProjectionMatrix();
         pushValue(l, true);
         return(1);
     }
     catch (Exception e) {
         return(error(l, e));
     }
 }
コード例 #4
0
        private void SetupCamera()
        {
            camSensor.ResetWorldToCameraMatrix();
            camSensor.ResetProjectionMatrix();

            camSensor.allowHDR  = true;
            camSensor.allowMSAA = true;
            camSensor.allowDynamicResolution = true;
            camSensor.useOcclusionCulling    = true;

            camSensor.stereoTargetEye = StereoTargetEyeMask.None;

            camSensor.orthographic  = false;
            camSensor.nearClipPlane = (float)GetParameters().clip.near;
            camSensor.farClipPlane  = (float)GetParameters().clip.far;
            camSensor.cullingMask   = LayerMask.GetMask("Default");

            var targetRT = new RenderTexture(GetParameters().image_width, GetParameters().image_height, targetRTdepth, targetRTformat, targetRTrwmode)
            {
                name              = targetRTname,
                dimension         = UnityEngine.Rendering.TextureDimension.Tex2D,
                antiAliasing      = 1,
                useMipMap         = false,
                useDynamicScale   = false,
                wrapMode          = TextureWrapMode.Clamp,
                filterMode        = FilterMode.Bilinear,
                enableRandomWrite = true
            };

            camSensor.targetTexture = targetRT;

            var camHFov = (float)GetParameters().horizontal_fov *Mathf.Rad2Deg;
            var camVFov = DeviceHelper.HorizontalToVerticalFOV(camHFov, camSensor.aspect);

            camSensor.fieldOfView = camVFov;

            // Invert projection matrix for cloisim msg
            var projMatrix   = DeviceHelper.MakeCustomProjectionMatrix(camHFov, camVFov, camSensor.nearClipPlane, camSensor.farClipPlane);
            var invertMatrix = Matrix4x4.Scale(new Vector3(1, -1, 1));

            camSensor.projectionMatrix = projMatrix * invertMatrix;

            universalCamData.enabled = false;
            universalCamData.renderPostProcessing = true;
            camSensor.enabled = false;

            RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
            RenderPipelineManager.endCameraRendering   += OnEndCameraRendering;

            camSensor.hideFlags |= HideFlags.NotEditable;

            camImageData = new CameraImageData(GetParameters().image_width, GetParameters().image_height, GetParameters().image_format);
        }
コード例 #5
0
	private static void SetScissorRect( Camera cam, Rect r )
	{		
		if ( r.x < 0 )
		{
			r.width += r.x;
			r.x = 0;
		}
		
		if ( r.y < 0 )
		{
			r.height += r.y;
			r.y = 0;
		}
		
		r.width = Mathf.Min( 1 - r.x, r.width );
		r.height = Mathf.Min( 1 - r.y, r.height );			
//		print( r );
			 
		cam.rect = new Rect (0,0,1,1);
		cam.ResetProjectionMatrix ();
		Matrix4x4 m = cam.projectionMatrix;
//		print( cam.projectionMatrix );
//		print( Mathf.Rad2Deg * Mathf.Atan( 1 / cam.projectionMatrix[ 0 ] ) * 2 );
		cam.rect = r;
//		cam.projectionMatrix = m;
//		print( cam.projectionMatrix );		
//		print( Mathf.Rad2Deg * Mathf.Atan( 1 / cam.projectionMatrix[ 0 ] ) * 2 );
//		print( cam.fieldOfView );
//		print( Mathf.Tan( cam.projectionMatrix[ 1, 1 ] ) * 2 );
//		cam.pixelRect = new Rect( 0, 0, Screen.width / 2, Screen.height );
		Matrix4x4 m1 = Matrix4x4.TRS( new Vector3( r.x, r.y, 0 ), Quaternion.identity, new Vector3( r.width, r.height, 1 ) );
//		Matrix4x4 m1 = Matrix4x4.TRS( Vector3.zero, Quaternion.identity, new Vector3( r.width, r.height, 1 ) );
//		Matrix4x4 m2 = m1.inverse;
//		print( m2 );
		Matrix4x4 m2 = Matrix4x4.TRS (new Vector3 ( ( 1/r.width - 1), ( 1/r.height - 1 ), 0), Quaternion.identity, new Vector3 (1/r.width, 1/r.height, 1));
		Matrix4x4 m3 = Matrix4x4.TRS( new Vector3( -r.x  * 2 / r.width, -r.y * 2 / r.height, 0 ), Quaternion.identity, Vector3.one );
//		m2[ 0, 3 ] = r.x;
//		m2[ 1, 3 ] = r.y;
//		print( m3 );
//		print( cam.projectionMatrix );
		cam.projectionMatrix = m3 * m2 * m; 
//		print( cam.projectionMatrix );		
	}	
コード例 #6
0
        private void SetupCamera()
        {
            cam.ResetWorldToCameraMatrix();
            cam.ResetProjectionMatrix();

            cam.allowHDR        = true;
            cam.allowMSAA       = false;
            cam.targetDisplay   = 0;
            cam.stereoTargetEye = StereoTargetEyeMask.None;

            cam.orthographic  = false;
            cam.nearClipPlane = (float)parameters.clip.near;
            cam.farClipPlane  = (float)parameters.clip.far;
            cam.cullingMask   = LayerMask.GetMask("Default");

            var targetRT = new RenderTexture(parameters.image_width, parameters.image_height, targetRTdepth, targetRTformat, targetRTrwmode)
            {
                name            = targetRTname,
                dimension       = UnityEngine.Rendering.TextureDimension.Tex2D,
                antiAliasing    = 1,
                useMipMap       = false,
                useDynamicScale = false,
                wrapMode        = TextureWrapMode.Clamp,
                filterMode      = FilterMode.Bilinear,
            };

            cam.targetTexture = targetRT;

            var camHFov = (float)parameters.horizontal_fov * Mathf.Rad2Deg;
            var camVFov = DeviceHelper.HorizontalToVerticalFOV(camHFov, cam.aspect);

            cam.fieldOfView = camVFov;

            // Invert projection matrix for gazebo msg
            var projMatrix   = DeviceHelper.MakeCustomProjectionMatrix(camHFov, camVFov, cam.nearClipPlane, cam.farClipPlane);
            var invertMatrix = Matrix4x4.Scale(new Vector3(1, -1, 1));

            cam.projectionMatrix = projMatrix * invertMatrix;
            cam.enabled          = false;
            // cam.hideFlags |= HideFlags.NotEditable;

            camData.AllocateTexture(parameters.image_width, parameters.image_height, parameters.image_format);
        }
コード例 #7
0
    /**
     * The goal is to subdivide the original projection into smaller off-centered projections
     * based on row and col counts. The original projection is calculated based on fov, nearclip and aspect ratio.
     *
     * The easiest way is to specify the true aspect ratio of the final rig say 16x9
     * And divide that equally by the number of rows and columns specified.
     * It is up to the user to ensure that the number of rows and cols actually represent the aspect ratio
     *
     * The calculation:
     *
     * Given T, L= -T*aspect
     * Given cameraIndex = i
     *
     * w=(R-L)/c, h=(T-B)/r
     * x=i%c, y=floor(i/c)
     *
     * t=T-(y*h), b=t-h, l=L+(x*w), r=l+w
     *
     * For PowerWall, the rows and columns determine how the offcenter are calculated.
     * Each quad is 2 units width and height. So a center quad is
     *        -----------1,1
     *        |           |
     *        |           |
     *        |           |
     *      -1,-1----------
     *
     * Margins for WALLs are added in during the computation of the projection matrix.
     *
     *
     * For CAVE, we could have odd and even number of screens.
     * For odd we could position screen 0 as center 31024 or 01234 or -2,-1,0,1,2
     * For even screens, we could force a center screen. 0,1 or -1,0,1,2
     *
     * sides != screens. You can have 3 screens showing parts of a 8 sided simulation
     * This gives you a 45deg angel between the screens
     *
     * Or you could have a 3 screens with 4 sided simulation which means the screen are at 90deg with each other.
     *
     * Formula to convert camera index to rig index the arrangement is 31024
     * f(odd n)  = ceil(n/2)
     * f(even n) = -n/2
     * f(n) = (1-2*(n&1))*ceil(n*0.5);
     * i = 0, h = 0
     * i = 1, h = 1
     * i = 2, h = -1
     * i = 3, h = 2
     * i = 4, h = -2
     * i = 5, h = 3
     * i = 6, h = -3
     * i = 7, h = 4
     * i = 8, h = -4
     *
     *
     * A sky or floor is only applicable for caves with 4 walls, as the screen can only be a square or rectangle.
     * If we are doing sky or floor, we could still calculate the vertical fov for cave walls first.
     * For a room with 4 walls and/or 1 sky and/or 1 floor, the fov for the sky or floor is simply
     * (360 - (2*fovVert)) / 2
     * = 180 - fovVert
     *
     *          180-
     *       \fovVert /
     *        \      /
     *         \    /
     *          \  /
     *   fovVert \/  fovVert (for cave walls)
     *           /\
     *          /  \
     *         /    \
     *        /      \
     *       /  180-  \
     *        fovVert
     *
     * After computing the fov, we will rotate the camera to face the floor or sky.
     * For floor and sky, the aspect ratios are 1, as all 4 walls around them will have the same length.
     * Margins for CAVEs are subtracted from the horizontal and vertical field of views during calculation of
     * values for the projection matrix.
     *
     */
    public void SetupCamera(Camera camera, int cameraIndex)
    {
        // the index relative to this rig. Support multi-rig per scene
        cameraIndex -= cameraIndexOffset;
        // reset this incase we were wall once
        camera.ResetProjectionMatrix();

        // this must be reset
        camera.transform.localRotation = Quaternion.identity;

        if (clusterType == ClusterType.Cave)
        {
            camera.transform.localEulerAngles = CalculateRotationForCaveNode (cameraIndex);
        }

        float left = 0.0f, right = 0.0f, bottom = 0.0f, top = 0.0f;
        CalculateCameraProjectionFrustum(cameraIndex, ref left, ref right, ref bottom, ref top);
        camera.projectionMatrix = PerspectiveOffCenter( left, right, bottom, top, nearClip, farClip);
        camera.nearClipPlane = nearClip;
        camera.farClipPlane = farClip;
    }
コード例 #8
0
ファイル: Portal.cs プロジェクト: mmandel/8Nights2
        /**
         * This will render the slave camera to a texture as it would be seen by the given camera.
         * Render results are placed in {result}. Pass this to AppearAsPreviouslyRendered to apply the rendered
         * texture to our current model/appearance.
         */
        internal void RenderSlaveCamera(Camera cam, RenderedFrame result)
        {
            //skip if not on or ready
            if (!enabled || !GetComponent<Renderer>() || !GetComponent<Renderer>().sharedMaterial || !GetComponent<Renderer>().enabled || !destination || !cam)
            return;

            CameraInfo trackingInfo = null;
            if (!cameraInfo.TryGetValue(cam, out trackingInfo)) {
            //Not actually being tracked? Just use a temp. Generally shouldn't happen.
            trackingInfo = new CameraInfo();
            }

            Vector3 entryFaceDirection = transform.rotation * entryFace;

            var isBehind = Vector3.Dot(transform.position - cam.transform.position, entryFaceDirection) >= 0;
            var isReallyNear = PortalMath.DistanceFromPointToPlane(transform.forward, transform.position, cam.transform.position) <= cam.nearClipPlane;

            //Depending on where we've been and are, we might or might not want to render. Keep reading.
            if (isReallyNear) {
            if (isBehind) {
                //we are just behind the portal
                if (trackingInfo.nearFront) {
                    //We were in front of it earlier and can we can still see the portal (the portal mesh has more geometry behind the front plane),
                    //Render.
                    //(If we're going to teleport something, we'll usually do it just after this frame.)
                } else {
                    //We weren't just in front of the portal. Perhaps we teleported in from somewhere or walked up to a portal that's
                    //invisible from behind while looking backwards.
                    //Don't render.
                    return;
                }
            } else {
                //We are in front of the portal (and rather close to boot).
                //Render.

                //Also set the "I was close to the front of the portal" flag so we know to keep rendering if we move behind it.
                trackingInfo.nearFront = true;
            }
            } else {
            //We are not close.

            //Reset this flag.
            trackingInfo.nearFront = false;

            if (isBehind) {
                //Don't render
                return;
            } else {
                //Render.
            }
            }

            //Note that, if we don't (try to) render the portal for a frame or so the tracking information will be deleted.
            //This covers the corner case where you are behind the portal with it rendering, then teleport away and back.
            //Without clearing the nearFront flag while we're away, we would incorrectly show the inside of the portal if we jumped back.

            //If we have a two-sided portal on the other end as our destination, the opposite face on the destination portal can sometimes
            //block the view as we look through.
            //Therefore, if we are the destination of the currently rendering portal, don't render at all.
            if (lastRecursivePortal && lastRecursivePortal.destination == this.transform) {
            return;
            }

            //Stop rendering if we are too recursively deep.
            if (currentPortalDepth + 1 > renderOptions.maximumPortalDepth) {
            result.renderOpaque = true;
            return;
            }

            #if UNITY_EDITOR
            if (!Application.isPlaying && currentPortalDepth + 1 > 1) {
            //don't render more than one deep in the editor (todo: make this configurable)
            result.renderOpaque = true;
            return;
            }
            #endif

            currentPortalDepth++;

            var lastLastRecursiveCamera = lastRecursiveCamera;
            var lastLastRecursivePortal = lastRecursivePortal;
            lastRecursiveCamera = cam;
            lastRecursivePortal = this;

            try {

            var camInfo = CreateCameraObjects(cam);

            var portalCamera = camInfo.portalCamera;

            UpdateCameraModes(cam, portalCamera);

            //Move the render target camera to where we'll be rendering from.
            TeleportRelativeToDestination(cam.transform, portalCamera.transform);

            //get the portal's plane
            var pos = destination.transform.position;
            var normal = destination.transform.rotation * exitFace;

            if (renderOptions.useOblique) {
                /*
                Normally, when you do a projection, the near and far (clipping) planes are perpendicular to the camera.

                They don't have to be, however, and here we take advantage of this fact to cull unwanted geometry.

                Here we set up an oblique projection matrix so that near clipping plane coincides with our portal plane.
                (Then shim it a bit, to avoid z-fighting.)
                This way the z-buffer will automatically clip out everything between the camera and portal.
                You'll only see things beyond the destination portal.
                 */
                Vector4 clipPlane = PortalMath.CameraSpacePlane(portalCamera, pos, normal, 1.0f, renderOptions.clipPlaneOffset);

                Matrix4x4 projection;
                if (currentPortalDepth > 1) {
                    //If we have a regular projection matrix we can just go ahead and turn it into an oblique matrix.
                    //But if we started with an oblique matrix (as happens when a portal renders a portal), re-obliquifying it
                    //messes up the far clipping plane.
                    //Instead, start with a fresh matrix for the camera and tweak that.

                    //Note that we don't want to modify the src camera's matrix, just get a copy of what its normal matrix would be.
                    //(Too bad Unity doesn't have an API to just fetch it.)
                    //Also note: If we do this to a scene camera inside the Unity Editor (even though we put it back) the scene cameras might FREAK OUT.
                    //(That's not a concern, however, because we only do this to slave cameras we generated.)
                    var origMatrix = cam.projectionMatrix;//backup
                    cam.ResetProjectionMatrix();
                    projection = cam.projectionMatrix;//get what we need
                    cam.projectionMatrix = origMatrix;//leave the original camera unmodified
                } else {
                    projection = cam.projectionMatrix;
                }

                //how far is the camera on this side from the portal entrance?
                var cameraDistanceFromPortal = PortalMath.DistanceFromPointToPlane(transform.forward, transform.position, cam.transform.position);
                if (cameraDistanceFromPortal < cam.nearClipPlane * 3) {
                    //When the camera's this close, the math we're using to construct the oblique matrix tends to break down and construct a matrix
                    //with a far plane that intersects the original frustum.

                    //If we're this close, we'll rely on the empty space that should be behind the portal actually being empty and just use a
                    //regular near plan on our frustum.
                } else {
                    if (portalCamera.orthographic)
                        PortalMath.CalculateOrthographicObliqueMatrix(ref projection, clipPlane);
                    else
                        PortalMath.CalculatePerspectiveObliqueMatrix(ref projection, clipPlane);
                }

                //we don't use the normal near clip plane, but still need to tell culling algorithms about where we're looking
                //Never mind, occlusion culling is broken in Unity. //portalCamera.nearClipPlane = PortalMath.DistanceFromPointToPlane(destination.forward, destination.position, portalCamera.transform.position);//Vector3.Distance(portalCamera.transform.position, destination.transform.position);

                portalCamera.projectionMatrix = projection;
            }

            var renderTexture = result.CreateTexture(renderOptions, cam);

            portalCamera.cullingMask = renderOptions.renderLayers.value;
            portalCamera.targetTexture = renderTexture;
            portalCamera.Render();
            // Debug.Log("portal texture (after render) is " + this+ "-"+camInfo.portalTexture.GetInstanceID());

            camInfo.renderedLastFrame = true;
            } finally {
            currentPortalDepth--;
            lastRecursiveCamera = lastLastRecursiveCamera;
            lastRecursivePortal = lastLastRecursivePortal;
            }
        }
コード例 #9
0
 public void OnPostRender(Camera camera)
 {
     if (temporal.UseTemporal())
         camera.ResetProjectionMatrix();
 }
コード例 #10
0
ファイル: SMAA.cs プロジェクト: mittens/demos_unity
 public void OnPostRender(Camera camera)
 {
     if (temporal.enabled)
         camera.ResetProjectionMatrix();
 }
コード例 #11
0
 protected void UpdateCamera(Camera camera, RenderTexture rt)
 {
     camera.targetTexture = rt;
     camera.ResetAspect();
     camera.ResetProjectionMatrix();
 }
コード例 #12
0
        private void Render(IViewport viewport, u.Camera uCamera, int cullingLayer, float timestamp)
        {
            uCamera.ResetProjectionMatrix();
            var view = viewport.View;

            foreach (var layer in view.Layers.Take(1))
            {
                var camera    = layer.Camera;
                var aScene    = layer.VisibleScene;
                var viewFrame = camera.GetGlobalFrame();

                if (!(camera is IFromUnityCamera))
                {
                    uCamera.transform.localPosition = viewFrame.Eye.ToUnity();
                    uCamera.transform.localRotation = Quaternion.RotationToFrame(viewFrame.Right, viewFrame.Up).ToUnity();
                    var projProps = camera.GetProjectionProps();
                    uCamera.nearClipPlane = projProps.ZNear;
                    uCamera.farClipPlane  = projProps.ZFar;
                    switch (projProps.Type)
                    {
                    case CameraProjectionType.Perspective:
                    {
                        uCamera.orthographic = false;
                        uCamera.fieldOfView  = u.Mathf.Rad2Deg * projProps.Fov;
                        break;
                    }

                    case CameraProjectionType.Orthographic:
                    {
                        uCamera.orthographic     = true;
                        uCamera.orthographicSize = projProps.Scale;
                        break;
                    }

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                // todo: restore background colors and implement skyboxes

                var lightPos = viewFrame.Eye + 0.5f * viewFrame.Right + 0.5f * viewFrame.Up;

                foreach (var uStandardMaterial in standardMaterialCache.EnumerateAll())
                {
                    uStandardMaterial.SetVector("_CameraPosition", camera.GetEye().ToUnity());
                    uStandardMaterial.SetVector("_LightPosition", lightPos.ToUnity4());
                }

                foreach (var visualObject in globalObjectService.VisualObjects.transform.OfType <u.GameObject>())
                {
                    visualObject.layer = DisabledLayer;
                }

                var sceneRoot = aScene.Root;
                foreach (var node in sceneRoot.EnumerateSceneNodesDeep())
                {
                    var visualAspect = node.SearchComponent <IVisualComponent>();
                    if (visualAspect == null)
                    {
                        continue;
                    }
                    // todo: use explicit closure
                    var nodeCache = node.CacheContainer.GetOrAddCache(() => new UcWorldNodeVisualCache(di, node));
                    nodeCache.PrepareUnityObjectsForRendering(cullingLayer);
                }
            }
        }
コード例 #13
0
ファイル: ProjectionMatrix.cs プロジェクト: Jonas90/iss
    void OnPreCull()
    {
        cam = camera;

        // update screen (if defined)
        // this must be called manually to ensure the correct order of execution
        if (screen != null)
        {
            screen.UpdateCorners();
        }
        else
        {
            cam.ResetProjectionMatrix();
        }

        // calculate off-center projection
        if (projectionMode == ProjectionMode.Async || ProjectionMode == ProjectionMode.ObliqueAsync)
        {
            NearPlane plane = CalculateNearPlane(screen, camera, transform);
            mp = PerspectiveOffCenter(plane);
        }

        // choose the correct projection matrix
        switch (projectionMode)
        {
            case ProjectionMode.Standard:
                cam.ResetProjectionMatrix();
                break;
            case ProjectionMode.Oblique:
                cam.projectionMatrix = bimberMatrix * origProjMatrix;
                break;
            case ProjectionMode.Async:
                cam.projectionMatrix = mp;
                break;
            case ProjectionMode.ObliqueAsync:
                cam.projectionMatrix = bimberMatrix * mp;
                break;
        }
    }
コード例 #14
0
ファイル: CameraFX.cs プロジェクト: HexHash/LegacyRust
 internal static void ApplyTransitionAlterations(Camera camera, CameraFX fx, bool useFX)
 {
     Matrix4x4G matrix4x4G;
     Matrix4x4G matrix4x4G1;
     if (!useFX)
     {
         camera.ExtractCameraMatrixWorldToCamera(out matrix4x4G);
         camera.ExtractCameraMatrixProjection(out matrix4x4G1);
         int num = CameraFX.g_trans.Update(ref matrix4x4G, ref matrix4x4G1);
         if ((num & 1) == 1)
         {
             camera.ResetWorldToCameraMatrix();
             camera.worldToCameraMatrix = matrix4x4G.f;
         }
         if ((num & 2) == 2)
         {
             camera.ResetProjectionMatrix();
             camera.projectionMatrix = matrix4x4G1.f;
         }
     }
     else
     {
         int num1 = CameraFX.g_trans.Update(ref fx.worldToCameraMatrix, ref fx.projectionMatrix);
         if ((num1 & 1) == 1)
         {
             camera.worldToCameraMatrix = fx.worldToCameraMatrix.f;
             Matrix4x4G.Inverse(ref fx.worldToCameraMatrix, out fx.cameraToWorldMatrix);
         }
         if ((num1 & 2) == 2)
         {
             camera.projectionMatrix = fx.projectionMatrix.f;
         }
     }
 }
コード例 #15
0
	public void SetScissorRect( Camera cam, Rect r )
	{		
		if ( r.x < 0 )
		{
			r.width += r.x;
			r.x = 0;
		}
		
		if ( r.y < 0 )
		{
			r.height += r.y;
			r.y = 0;
		}
		
		r.width = Mathf.Min( 1 - r.x, r.width );
		r.height = Mathf.Min( 1 - r.y, r.height );			
		cam.rect = new Rect (0,0,1,1);
		cam.ResetProjectionMatrix ();
		Matrix4x4 m = cam.projectionMatrix;
		cam.rect = r;
		//Matrix4x4 m1 = Matrix4x4.TRS( new Vector3( r.x, r.y, 0 ), Quaternion.identity, new Vector3( r.width, r.height, 1 ) );
		Matrix4x4 m2 = Matrix4x4.TRS (new Vector3 ( ( 1/r.width - 1), ( 1/r.height - 1 ), 0), Quaternion.identity, new Vector3 (1/r.width, 1/r.height, 1));
		Matrix4x4 m3 = Matrix4x4.TRS( new Vector3( -r.x  * 2 / r.width, -r.y * 2 / r.height, 0 ), Quaternion.identity, Vector3.one );
		cam.projectionMatrix = m3 * m2 * m; 
	}