/// <inheritdoc/>
        protected override Matrix44F ComputeProjection()
        {
            var projection = Matrix44F.CreatePerspectiveOffCenter(Left, Right, Bottom, Top, Near, Far);

            if (_nearClipPlane.HasValue)
            {
                Vector4F clipPlane = new Vector4F(_nearClipPlane.Value.Normal, -_nearClipPlane.Value.DistanceFromOrigin);

                // Calculate the clip-space corner point opposite the clipping plane as
                // (-sign(clipPlane.x), -sign(clipPlane.y), 1, 1) and transform it into
                // camera space by multiplying it by the inverse of the projection matrix.
                Vector4F q;
                q.X = (-Math.Sign(clipPlane.X) + projection.M02) / projection.M00;
                q.Y = (-Math.Sign(clipPlane.Y) + projection.M12) / projection.M11;
                q.Z = -1.0f;
                q.W = (1.0f + projection.M22) / projection.M23;

                // Calculate the scaled plane vector
                Vector4F c = clipPlane * (1.0f / Vector4F.Dot(clipPlane, q));

                // Replace the third row of the projection matrix
                projection.M20 = c.X;
                projection.M21 = c.Y;
                projection.M22 = c.Z;
                projection.M23 = c.W;
            }

            return(projection);
        }
        public void SetProjectionOffCenterTest()
        {
            PerspectiveProjection projection = new PerspectiveProjection();

            projection.SetOffCenter(0, 4, 1, 4, 2, 10);

            PerspectiveProjection projection2 = new PerspectiveProjection();

            projection2.SetOffCenter(0, 4, 1, 4);
            projection2.Near = 2;
            projection2.Far  = 10;

            Matrix44F expected = Matrix44F.CreatePerspectiveOffCenter(0, 4, 1, 4, 2, 10);

            Assert.IsTrue(Matrix44F.AreNumericallyEqual(expected, projection));
            Assert.IsTrue(Matrix44F.AreNumericallyEqual(expected, projection2.ToMatrix44F()));
        }
예제 #3
0
        public void SetProjectionTest()
        {
            Matrix44F projectionMatrix = Matrix44F.CreateOrthographicOffCenter(1, 4, 2, 5, 6, 11);
            OrthographicProjection orthographicProjection = new OrthographicProjection();

            orthographicProjection.Set(projectionMatrix);
            CameraInstance cameraInstance = new CameraInstance(new Camera(orthographicProjection));

            Assert.AreEqual(Vector3F.Zero, cameraInstance.PoseWorld.Position);
            Assert.AreEqual(Matrix33F.Identity, cameraInstance.PoseWorld.Orientation);
            Assert.That(Numeric.AreEqual(3, cameraInstance.Camera.Projection.Width));
            Assert.That(Numeric.AreEqual(3, cameraInstance.Camera.Projection.Height));
            Assert.That(Numeric.AreEqual(1f, cameraInstance.Camera.Projection.AspectRatio));
            Assert.That(Numeric.AreEqual(6, cameraInstance.Camera.Projection.Near));
            Assert.That(Numeric.AreEqual(11, cameraInstance.Camera.Projection.Far));
            Assert.That(Numeric.AreEqual(1, cameraInstance.Camera.Projection.Left));
            Assert.That(Numeric.AreEqual(4, cameraInstance.Camera.Projection.Right));
            Assert.That(Numeric.AreEqual(2, cameraInstance.Camera.Projection.Bottom));
            Assert.That(Numeric.AreEqual(5, cameraInstance.Camera.Projection.Top));
            Assert.That(Numeric.AreEqual(5, cameraInstance.Camera.Projection.Depth));
            Assert.That(Matrix44F.AreNumericallyEqual(orthographicProjection, cameraInstance.Camera.Projection));
            Assert.That(Matrix44F.AreNumericallyEqual(orthographicProjection.Inverse, cameraInstance.Camera.Projection.Inverse));
            Assert.IsNotNull(cameraInstance.BoundingShape);

            PerspectiveProjection perspectiveProjection = new PerspectiveProjection();

            perspectiveProjection.Inverse = Matrix44F.CreatePerspectiveOffCenter(1, 5, 2, 5, 1, 10).Inverse;
            cameraInstance = new CameraInstance(new Camera(perspectiveProjection));

            Assert.AreEqual(Vector3F.Zero, cameraInstance.PoseWorld.Position);
            Assert.AreEqual(Matrix33F.Identity, cameraInstance.PoseWorld.Orientation);
            Assert.That(Numeric.AreEqual(MathHelper.ToRadians(33.690067f), cameraInstance.Camera.Projection.FieldOfViewX));
            Assert.That(Numeric.AreEqual(MathHelper.ToRadians(15.255119f), cameraInstance.Camera.Projection.FieldOfViewY));
            Assert.That(Numeric.AreEqual(4, cameraInstance.Camera.Projection.Width));
            Assert.That(Numeric.AreEqual(3, cameraInstance.Camera.Projection.Height));
            Assert.That(Numeric.AreEqual(4.0f / 3.0f, cameraInstance.Camera.Projection.AspectRatio));
            Assert.That(Numeric.AreEqual(1, cameraInstance.Camera.Projection.Left));
            Assert.That(Numeric.AreEqual(5, cameraInstance.Camera.Projection.Right));
            Assert.That(Numeric.AreEqual(2, cameraInstance.Camera.Projection.Bottom));
            Assert.That(Numeric.AreEqual(5, cameraInstance.Camera.Projection.Top));
            Assert.That(Numeric.AreEqual(1, cameraInstance.Camera.Projection.Near));
            Assert.That(Numeric.AreEqual(10, cameraInstance.Camera.Projection.Far));
            Assert.That(Numeric.AreEqual(9, cameraInstance.Camera.Projection.Depth));
            Assert.IsNotNull(cameraInstance.BoundingShape);
        }
        public void PerspectiveOffCenterTest()
        {
            Vector3F       position       = new Vector3F(1, 2, 3);
            QuaternionF    orientation    = QuaternionF.CreateRotation(new Vector3F(2, 3, 6), 0.123f);
            CameraInstance cameraInstance = new CameraInstance(new Camera(new PerspectiveProjection()))
            {
                PoseLocal = new Pose(position, orientation),
            };

            ((PerspectiveProjection)cameraInstance.Camera.Projection).SetOffCenter(1, 5, 2, 5, 1, 10);

            Matrix44F projection = Matrix44F.CreatePerspectiveOffCenter(1, 5, 2, 5, 1, 10);

            Assert.AreEqual(position, cameraInstance.PoseWorld.Position);
            Assert.AreEqual(orientation.ToRotationMatrix33(), cameraInstance.PoseWorld.Orientation);
            Assert.IsTrue(Numeric.AreEqual(MathHelper.ToRadians(33.690067f), cameraInstance.Camera.Projection.FieldOfViewX));
            Assert.IsTrue(Numeric.AreEqual(MathHelper.ToRadians(15.255119f), cameraInstance.Camera.Projection.FieldOfViewY));
            Assert.AreEqual(4.0f / 3.0f, cameraInstance.Camera.Projection.AspectRatio);
            Assert.AreEqual(4, cameraInstance.Camera.Projection.Width);
            Assert.AreEqual(3, cameraInstance.Camera.Projection.Height);
            Assert.AreEqual(1, cameraInstance.Camera.Projection.Left);
            Assert.AreEqual(5, cameraInstance.Camera.Projection.Right);
            Assert.AreEqual(2, cameraInstance.Camera.Projection.Bottom);
            Assert.AreEqual(5, cameraInstance.Camera.Projection.Top);
            Assert.AreEqual(1, cameraInstance.Camera.Projection.Near);
            Assert.AreEqual(10, cameraInstance.Camera.Projection.Far);
            Assert.AreEqual(9, cameraInstance.Camera.Projection.Depth);
            Assert.IsTrue(Matrix44F.AreNumericallyEqual(projection, cameraInstance.Camera.Projection));
            Assert.IsTrue(Matrix44F.AreNumericallyEqual(projection.Inverse, cameraInstance.Camera.Projection.Inverse));
            Assert.IsNotNull(cameraInstance.BoundingShape);

            // Test shape using collision detection. Remove rotation to simplify test.
            cameraInstance.PoseWorld = new Pose(cameraInstance.PoseWorld.Position);
            CollisionDetection collisionDetection = new CollisionDetection();
            var             point = new PointShape();
            CollisionObject pointCollisionObject  = new CollisionObject(new GeometricObject(point));
            CollisionObject cameraCollisionObject = new CollisionObject(cameraInstance);

            point.Position = position + new Vector3F(3, 3, -1);
            Assert.IsTrue(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(30, 30, -10);
            Assert.IsTrue(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(3, 3, -0.9f);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(30, 30, -10.1f);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));

            point.Position = position + new Vector3F(1, 2, -1);
            Assert.IsTrue(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(0.9f, 2, -1);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(1, 1.9f, -1);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(5, 5, -1);
            Assert.IsTrue(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(5.1f, 5, -1);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(5, 5.1f, -1);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));

            point.Position = position + new Vector3F(10, 20, -10);
            Assert.IsTrue(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(9.9f, 20, -10);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(10, 19.9f, -10);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(50, 50, -10);
            Assert.IsTrue(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(50.1f, 50, -10);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
            point.Position = position + new Vector3F(50, 50.1f, -10);
            Assert.IsFalse(collisionDetection.HaveContact(pointCollisionObject, cameraCollisionObject));
        }
예제 #5
0
        private void Render(RenderContext context, Vector4F color, Texture2D colorTexture, bool preserveColor)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            context.Validate(_effect);
            context.ThrowIfCameraMissing();
            context.ThrowIfGBuffer0Missing();

            var graphicsDevice   = _effect.GraphicsDevice;
            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            graphicsDevice.DepthStencilState = GraphicsHelper.DepthStencilStateAlways;
            graphicsDevice.RasterizerState   = RasterizerState.CullNone;

            if (preserveColor)
            {
                graphicsDevice.BlendState = GraphicsHelper.BlendStateNoColorWrite;
            }
            else
            {
                graphicsDevice.BlendState = BlendState.Opaque;
            }

            if (colorTexture != null)
            {
                if (TextureHelper.IsFloatingPointFormat(colorTexture.Format))
                {
                    graphicsDevice.SamplerStates[1] = SamplerState.PointClamp;
                }
                else
                {
                    graphicsDevice.SamplerStates[1] = SamplerState.LinearClamp;
                }
            }

            var   projection       = context.CameraNode.Camera.Projection;
            bool  isPerspective    = projection is PerspectiveProjection;
            float near             = projection.Near * NearBias;
            float far              = projection.Far * FarBias;
            var   biasedProjection = isPerspective
                               ? Matrix44F.CreatePerspectiveOffCenter(
                projection.Left, projection.Right,
                projection.Bottom, projection.Top,
                near, far)
                               : Matrix44F.CreateOrthographicOffCenter(
                projection.Left, projection.Right,
                projection.Bottom, projection.Top,
                near, far);

            var viewport = graphicsDevice.Viewport;

            _parameterViewportSize.SetValue(new Vector2(viewport.Width, viewport.Height));
            _parameterProjection.SetValue((Matrix)biasedProjection);
            _parameterCameraFar.SetValue(projection.Far);
            _parameterGBuffer0.SetValue(context.GBuffer0);
            _parameterColor.SetValue((Vector4)color);
            _parameterSourceTexture.SetValue(colorTexture);

            _effect.CurrentTechnique = isPerspective ? _techniquePerspective : _techniqueOrthographic;
            _effect.CurrentTechnique.Passes[(colorTexture == null) ? 0 : 1].Apply();

            graphicsDevice.DrawFullScreenQuad();

            graphicsDevice.ResetTextures();

            savedRenderState.Restore();
        }
예제 #6
0
        protected override void OnProcess(RenderContext context)
        {
            var graphicsDevice = GraphicsService.GraphicsDevice;

            // Set the render target - but only if no kind of alpha blending is currently set.
            // If alpha-blending is set, then we have to assume that the render target is already
            // set - everything else does not make sense.
            if (graphicsDevice.BlendState.ColorDestinationBlend == Blend.Zero &&
                graphicsDevice.BlendState.AlphaDestinationBlend == Blend.Zero)
            {
                graphicsDevice.SetRenderTarget(context.RenderTarget);
                graphicsDevice.Viewport = context.Viewport;
            }

            Projection projection = null;

            if (RebuildZBuffer || Mode == UpsamplingMode.NearestDepth)
            {
                context.ThrowIfCameraMissing();
                projection = context.CameraNode.Camera.Projection;
            }

            var sourceTexture = context.SourceTexture;

            _parameterSourceTexture.SetValue(sourceTexture);
            _parameterSourceSize.SetValue(new Vector2(sourceTexture.Width, sourceTexture.Height));

            var viewport = context.Viewport;

            _parameterTargetSize.SetValue(new Vector2(viewport.Width, viewport.Height));

            if (Mode == UpsamplingMode.Bilateral)
            {
                _parameterDepthSensitivity.SetValue(DepthSensitivity);
            }
            else if (Mode == UpsamplingMode.NearestDepth)
            {
                _parameterDepthThreshold.SetValue(DepthThreshold / projection.Far);
            }

            int techniqueIndex = (int)Mode;
            int passIndex      = 0;

            if (context.SceneTexture != null)
            {
                _parameterSceneTexture.SetValue(context.SceneTexture);
                passIndex |= 1;
            }

            if (RebuildZBuffer)
            {
                passIndex |= 2;

                float  nearBias = 1;
                float  farBias  = 0.995f;
                object obj;
                context.Data.TryGetValue(RenderContextKeys.RebuildZBufferRenderer, out obj);
                var rebuildZBufferRenderer = obj as RebuildZBufferRenderer;
                if (rebuildZBufferRenderer != null)
                {
                    nearBias = rebuildZBufferRenderer.NearBias;
                    farBias  = rebuildZBufferRenderer.FarBias;
                }

                // Compute biased projection for restoring the z-buffer.
                var biasedProjection = Matrix44F.CreatePerspectiveOffCenter(
                    projection.Left,
                    projection.Right,
                    projection.Bottom,
                    projection.Top,
                    projection.Near * nearBias,
                    projection.Far * farBias);
                _parameterProjection.SetValue((Matrix)biasedProjection);
                _parameterCameraFar.SetValue(projection.Far);

                // PostProcessor.ProcessInternal sets the DepthStencilState to None.
                // --> Enable depth writes.
                graphicsDevice.DepthStencilState = GraphicsHelper.DepthStencilStateAlways;
            }

            if (RebuildZBuffer || Mode >= UpsamplingMode.Bilateral)
            {
                context.ThrowIfGBuffer0Missing();
                _parameterDepthBuffer.SetValue(context.GBuffer0);
            }

            if (Mode >= UpsamplingMode.Bilateral)
            {
                // Render at half resolution into off-screen buffer.
                object dummy;
                context.Data.TryGetValue(RenderContextKeys.DepthBufferHalf, out dummy);
                var depthBufferHalf = dummy as Texture2D;
                if (depthBufferHalf == null)
                {
                    string message = "Downsampled depth buffer is not set in render context. (The downsampled "
                                     + "depth buffer (half width and height) is required by the UpsampleFilter."
                                     + "It needs to be stored in RenderContext.Data[RenderContextKeys.DepthBufferHalf].)";
                    throw new GraphicsException(message);
                }

                _parameterDepthBufferLow.SetValue(depthBufferHalf);
            }

            _effect.CurrentTechnique = _effect.Techniques[techniqueIndex];
            _effect.CurrentTechnique.Passes[passIndex].Apply();

            graphicsDevice.DrawFullScreenQuad();

            _parameterSourceTexture.SetValue((Texture2D)null);
            _parameterSceneTexture.SetValue((Texture2D)null);
            _parameterDepthBuffer.SetValue((Texture2D)null);
            _parameterDepthBufferLow.SetValue((Texture2D)null);
        }