/// <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())); }
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)); }
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(); }
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); }