//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- /// <summary> /// Initializes a new instance of the <see cref="ObjectMotionBlur"/> class. /// </summary> /// <param name="graphicsService">The graphics service.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="graphicsService"/> is <see langword="null"/>. /// </exception> public ObjectMotionBlur(IGraphicsService graphicsService) : base(graphicsService) { _effect = GraphicsService.Content.Load <Effect>("DigitalRune/PostProcessing/ObjectMotionBlur"); _viewportSizeParameter = _effect.Parameters["ViewportSize"]; _sourceTextureParameter = _effect.Parameters["SourceTexture"]; _numberOfSamplesParameter = _effect.Parameters["NumberOfSamples"]; _velocityTextureParameter = _effect.Parameters["VelocityTexture"]; _velocityTexture2Parameter = _effect.Parameters["VelocityTexture2"]; _maxBlurRadiusParameter = _effect.Parameters["MaxBlurRadius"]; _sourceSizeParameter = _effect.Parameters["SourceSize"]; _gBuffer0Parameter = _effect.Parameters["GBuffer0"]; _jitterTextureParameter = _effect.Parameters["JitterTexture"]; _softZExtentParameter = _effect.Parameters["SoftZExtent"]; _singlePass = _effect.CurrentTechnique.Passes["Single"]; _dualPass = _effect.CurrentTechnique.Passes["Dual"]; _downsampleMaxParameter = _effect.CurrentTechnique.Passes["DownsampleMax"]; _downsampleMaxFromFloatBufferParameter = _effect.CurrentTechnique.Passes["DownsampleMaxFromFloatBuffer"]; _neighborMaxPass = _effect.CurrentTechnique.Passes["NeighborMax"]; _softEdgePass = _effect.CurrentTechnique.Passes["SoftEdge"]; _jitterTexture = NoiseHelper.GetGrainTexture(GraphicsService, 128); NumberOfSamples = 9; MaxBlurRadius = 20; }
private EffectParameterBinding CreateJitterMapBinding <T>(Effect effect, EffectParameter parameter, IDictionary <string, object> opaqueData) where T : Texture { var jitterMap = NoiseHelper.GetGrainTexture(_graphicsService, NoiseHelper.DefaultJitterMapWidth); return(new ConstParameterBinding <T>(effect, parameter, jitterMap as T)); }
public CloudMapRenderer(IGraphicsService graphicsService) { if (graphicsService == null) { throw new ArgumentNullException("graphicsService"); } if (graphicsService.GraphicsDevice.GraphicsProfile == GraphicsProfile.Reach) { throw new NotSupportedException("The CloudMapRenderer does not support the Reach profile."); } // One 512x512 noise texture is used for all layers. Each layer which does not have // a user defined texture uses a part of this texture. _noiseTexture = NoiseHelper.GetGrainTexture(graphicsService, 512); _effect = graphicsService.Content.Load <Effect>("DigitalRune/Sky/CloudLayer"); _parameterViewportSize = _effect.Parameters["ViewportSize"]; _parameterTexture0Parameters = _effect.Parameters["Texture0Parameters"]; _parameterTexture1Parameters = _effect.Parameters["Texture1Parameters"]; _parameterLerp = _effect.Parameters["LerpParameter"]; _parameterTextures = new EffectParameter[LayeredCloudMap.NumberOfTextures]; _parameterDensities = new EffectParameter[LayeredCloudMap.NumberOfTextures]; _parameterMatrices = new EffectParameter[LayeredCloudMap.NumberOfTextures]; for (int i = 0; i < LayeredCloudMap.NumberOfTextures; i++) { _parameterTextures[i] = _effect.Parameters["NoiseTexture" + i]; _parameterDensities[i] = _effect.Parameters["Density" + i]; _parameterMatrices[i] = _effect.Parameters["Matrix" + i]; } _parameterCoverage = _effect.Parameters["Coverage"]; _parameterDensity = _effect.Parameters["Density"]; _passLerp = _effect.Techniques[0].Passes["Lerp"]; _passDensity = _effect.Techniques[0].Passes["Density"]; }
public override void Update(GameTime gameTime) { Random random = new Random(1234567); // The debug renderer stores all draw commands. In this sample we recreate // the draw jobs each frame. --> Clear draw jobs of last frame. _debugRenderer.Clear(); // The DebugRenderer can draw stuff "in" the scene (enabled z test) or "over" // the scene (disabled z test). // Draw some points and line "in" and "over" the scene. for (int i = 0; i < 10; i++) { var position = new Vector3F(-6, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawPoint(position, Color.Green, false); } for (int i = 0; i < 10; i++) { var position = new Vector3F(-4, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawPoint(position, Color.Yellow, true); } for (int i = 0; i < 10; i++) { var start = new Vector3F(-2, 0, -3) + random.NextVector3F(-0.5f, 0.5f); var end = new Vector3F(-2, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawLine(start, end, Color.Green, false); } for (int i = 0; i < 10; i++) { var start = new Vector3F(0, 0, -3) + random.NextVector3F(-0.5f, 0.5f); var end = new Vector3F(0, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawLine(start, end, Color.Yellow, true); } // Text without a specified position is drawn at a default position. _debugRenderer.DefaultTextPosition = new Vector2F(10, 100); _debugRenderer.DrawText("White objects are positioned in screen space."); _debugRenderer.DrawText("Yellow objects are positioned in world space. Depth test disabled."); _debugRenderer.DrawText("Other objects are positioned in world space. Depth test enabled."); // Text can also be drawn in world space coordinates or in screen space coordinates. _debugRenderer.DrawText("WorldSpacePosition (0, 0, 0)", new Vector3F(0, 0, 0), Color.Green, false); _debugRenderer.DrawText("WorldSpacePosition (0, 0, -1)", new Vector3F(0, 0, -1), Color.Yellow, true); _debugRenderer.DrawText("ScreenPosition (600, 40)", new Vector2F(600, 40), Color.White); _debugRenderer.DrawText("ScreenPosition (640, 360)", new Vector2F(640, 360), Color.White); // It is often useful to copy textures to the screen for debugging. _debugRenderer.DrawTexture(NoiseHelper.GetGrainTexture(GraphicsService, 128), new Rectangle(1000, 10, 128, 128)); // Axes can be drawn to display poses (positions and orientations). _debugRenderer.DrawAxes(new Pose(new Vector3F(0, 0, 0)), 1, true); // Axis-aligned bounding boxes (AABB) _debugRenderer.DrawAabb(new Aabb(new Vector3F(-0.5f), new Vector3F(0.5f)), new Pose(new Vector3F(2, 0, -3)), Color.Green, false); _debugRenderer.DrawAabb(new Aabb(new Vector3F(-0.5f), new Vector3F(0.5f)), new Pose(new Vector3F(4, 0, -3)), Color.Yellow, true); // Box shapes var orientation = random.NextQuaternionF(); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-6, 0, -5), orientation), new Color(255, 0, 0, 100), false, false); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-6, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-4, 0, -5), orientation), Color.Yellow, true, true); // View volumes (frustums) var viewVolume = new PerspectiveViewVolume(1, 2, 0.1f, 1f); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(-2, 0, -5), orientation), new Color(0, 255, 0, 100), false, false); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(-2, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(0, 0, -5), orientation), Color.Yellow, true, true); // Spheres _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(2, 0, -5), orientation), new Color(0, 0, 255, 100), false, false); _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(2, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(4, 0, -5), orientation), Color.Yellow, true, true); // Capsules _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-6, 0, -7), orientation), new Color(255, 255, 0, 100), false, false); _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-6, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-4, 0, -7), orientation), Color.Yellow, true, true); // Cylinders _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(-2, 0, -7), orientation), new Color(255, 0, 255, 100), false, false); _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(-2, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(0, 0, -7), orientation), Color.Yellow, true, true); // Cones _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(2, 0, -7), orientation), new Color(0, 255, 255, 100), false, false); _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(2, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(4, 0, -7), orientation), Color.Yellow, true, true); // The debug renderer can draw any IGeometricObjects, like SceneNodes, RigidBodies, etc. _debugRenderer.DrawObject(_geometricObject, Color.Brown, false, false); _debugRenderer.DrawObject(_geometricObject, Color.Yellow, true, true); // The debug renderer can also an XNA model (without materials). _debugRenderer.DrawModel(_xnaModel, new Pose(new Vector3F(0, 2, -2), orientation), new Vector3F(1, 2, 1), new Color(128, 255, 64, 100), false, false); _debugRenderer.DrawModel(_xnaModel, new Pose(new Vector3F(0, 2, -2), orientation), new Vector3F(1, 2, 1), Color.LightCyan, true, false); // Draw a DigitalRune model. _debugRenderer.DrawModel(_modelNode, Color.Peru, true, false); // Draw the bounding shapes of the meshes in this model. foreach (var node in _modelNode.GetSubtree()) { _debugRenderer.DrawObject(node, Color.PeachPuff, true, false); } }
public override void Render(IList <SceneNode> nodes, RenderContext context, RenderOrder order) { if (nodes == null) { throw new ArgumentNullException("nodes"); } if (context == null) { throw new ArgumentNullException("context"); } int numberOfNodes = nodes.Count; if (numberOfNodes == 0) { return; } context.Validate(_effect); context.ThrowIfCameraMissing(); var graphicsDevice = _effect.GraphicsDevice; var savedRenderState = new RenderStateSnapshot(graphicsDevice); graphicsDevice.DepthStencilState = DepthStencilState.None; graphicsDevice.RasterizerState = RasterizerState.CullNone; var cameraNode = context.CameraNode; _parameterViewInverse.SetValue(cameraNode.PoseWorld); _parameterGBuffer0.SetValue(context.GBuffer0); Viewport viewport = context.Viewport; _parameterParameters0.SetValue(new Vector2(viewport.Width, viewport.Height)); if (_jitterMap == null) { _jitterMap = NoiseHelper.GetGrainTexture(context.GraphicsService, NoiseHelper.DefaultJitterMapWidth); } _parameterJitterMap.SetValue(_jitterMap); for (int i = 0; i < numberOfNodes; i++) { var lightNode = nodes[i] as LightNode; if (lightNode == null) { continue; } var shadow = lightNode.Shadow as StandardShadow; if (shadow == null) { continue; } if (shadow.ShadowMap == null || shadow.ShadowMask == null) { continue; } // The effect must only render in a specific channel. // Do not change blend state if the correct write channels is already set, e.g. if this // shadow is part of a CompositeShadow, the correct blend state is already set. if ((int)graphicsDevice.BlendState.ColorWriteChannels != (1 << shadow.ShadowMaskChannel)) { graphicsDevice.BlendState = GraphicsHelper.BlendStateWriteSingleChannel[shadow.ShadowMaskChannel]; } _parameterParameters1.SetValue(new Vector4( shadow.Near, shadow.Far, shadow.EffectiveDepthBias, shadow.EffectiveNormalOffset)); // If we use a subset of the Poisson kernel, we have to normalize the scale. int numberOfSamples = Math.Min(shadow.NumberOfSamples, PoissonKernel.Length); float filterRadius = shadow.FilterRadius; if (numberOfSamples > 0) { filterRadius /= PoissonKernel[numberOfSamples - 1].Length(); } _parameterParameters2.SetValue(new Vector3( shadow.ShadowMap.Width, filterRadius, // The StandardShadow.JitterResolution is the number of texels per world unit. // In the shader the parameter JitterResolution contains the division by the jitter map size. shadow.JitterResolution / _jitterMap.Width)); _parameterLightPosition.SetValue((Vector3)cameraNode.PoseWorld.ToLocalPosition(lightNode.PoseWorld.Position)); Matrix cameraViewToShadowView = cameraNode.PoseWorld * shadow.View; _parameterShadowView.SetValue(cameraViewToShadowView); _parameterShadowMatrix.SetValue(cameraViewToShadowView * shadow.Projection); _parameterShadowMap.SetValue(shadow.ShadowMap); var rectangle = GraphicsHelper.GetViewportRectangle(cameraNode, viewport, lightNode); Vector2F texCoordTopLeft = new Vector2F(rectangle.Left / (float)viewport.Width, rectangle.Top / (float)viewport.Height); Vector2F texCoordBottomRight = new Vector2F(rectangle.Right / (float)viewport.Width, rectangle.Bottom / (float)viewport.Height); GraphicsHelper.GetFrustumFarCorners(cameraNode.Camera.Projection, texCoordTopLeft, texCoordBottomRight, _frustumFarCorners); _parameterFrustumCorners.SetValue(_frustumFarCorners); var pass = GetPass(numberOfSamples); if (numberOfSamples > 0) { if (_lastNumberOfSamples != numberOfSamples) { // Create an array with the first n samples and the rest set to 0. _lastNumberOfSamples = numberOfSamples; for (int j = 0; j < numberOfSamples; j++) { _samples[j].X = PoissonKernel[j].X; _samples[j].Y = PoissonKernel[j].Y; _samples[j].Z = 1.0f / numberOfSamples; // Note [HelmutG]: I have tried weights decreasing with distance but that did not // look better. } // Set the rest to zero. for (int j = numberOfSamples; j < _samples.Length; j++) { _samples[j] = Vector3.Zero; } _parameterSamples.SetValue(_samples); } else if (i == 0) { // Apply offsets in the first loop. _parameterSamples.SetValue(_samples); } } pass.Apply(); graphicsDevice.DrawQuad(rectangle); } _parameterGBuffer0.SetValue((Texture2D)null); _parameterJitterMap.SetValue((Texture2D)null); _parameterShadowMap.SetValue((Texture2D)null); savedRenderState.Restore(); }
public override void Render(IList <SceneNode> nodes, RenderContext context, RenderOrder order) { if (nodes == null) { throw new ArgumentNullException("nodes"); } if (context == null) { throw new ArgumentNullException("context"); } int numberOfNodes = nodes.Count; if (numberOfNodes == 0) { return; } context.Validate(_effect); context.ThrowIfCameraMissing(); var graphicsDevice = _effect.GraphicsDevice; var savedRenderState = new RenderStateSnapshot(graphicsDevice); graphicsDevice.DepthStencilState = DepthStencilState.None; graphicsDevice.RasterizerState = RasterizerState.CullNone; // Set camera properties. var cameraNode = context.CameraNode; var cameraPose = cameraNode.PoseWorld; Matrix viewInverse = cameraPose; _parameterViewInverse.SetValue(viewInverse); _parameterGBuffer0.SetValue(context.GBuffer0); Viewport viewport = context.Viewport; _parameterParameters0.SetValue(new Vector2(viewport.Width, viewport.Height)); // Set jitter map. if (_jitterMap == null) { _jitterMap = NoiseHelper.GetGrainTexture(context.GraphicsService, NoiseHelper.DefaultJitterMapWidth); } _parameterJitterMap.SetValue(_jitterMap); float cameraFar = context.CameraNode.Camera.Projection.Far; for (int i = 0; i < numberOfNodes; i++) { var lightNode = nodes[i] as LightNode; if (lightNode == null) { continue; } var shadow = lightNode.Shadow as CascadedShadow; if (shadow == null) { continue; } if (shadow.ShadowMap == null || shadow.ShadowMask == null) { continue; } // The effect must only render in a specific channel. // Do not change blend state if the correct write channels is already set, e.g. if this // shadow is part of a CompositeShadow, the correct blend state is already set. if ((int)graphicsDevice.BlendState.ColorWriteChannels != (1 << shadow.ShadowMaskChannel)) { graphicsDevice.BlendState = GraphicsHelper.BlendStateWriteSingleChannel[shadow.ShadowMaskChannel]; } _parameterParameters1.SetValue(new Vector4( shadow.FadeOutRange, shadow.Distances[shadow.NumberOfCascades - 1], shadow.VisualizeCascades ? 1 : 0, shadow.ShadowFog)); float filterRadius = shadow.FilterRadius; // If we use a subset of the Poisson kernel, we have to normalize the scale. int numberOfSamples = Math.Min(shadow.NumberOfSamples, StandardShadowMaskRenderer.PoissonKernel.Length); // Not all shader passes support cascade visualization. Use a similar pass instead. if (shadow.VisualizeCascades) { if (numberOfSamples < 0) { numberOfSamples = 4; } else if (numberOfSamples == 0) { numberOfSamples = 1; filterRadius = 0; } } // The best dithered CSM supports max 22 samples. if (shadow.CascadeSelection == ShadowCascadeSelection.BestDithered && numberOfSamples > 22) { numberOfSamples = 22; } if (numberOfSamples > 0) { filterRadius /= StandardShadowMaskRenderer.PoissonKernel[numberOfSamples - 1].Length(); } _parameterParameters2.SetValue(new Vector4( shadow.ShadowMap.Width, shadow.ShadowMap.Height, filterRadius, // The StandardShadow.JitterResolution is the number of texels per world unit. // In the shader the parameter JitterResolution contains the division by the jitter map size. shadow.JitterResolution / _jitterMap.Width)); // Split distances. if (_parameterDistances != null) { // Set not used entries to large values. Vector4 distances = shadow.Distances; for (int j = shadow.NumberOfCascades; j < 4; j++) { distances[j] = 10 * cameraFar; } _parameterDistances.SetValue((Vector4)distances); } Debug.Assert(shadow.ViewProjections.Length == 4); for (int j = 0; j < _matrices.Length; j++) { _matrices[j] = viewInverse * shadow.ViewProjections[j]; } _parameterShadowMatrices.SetValue(_matrices); _parameterDepthBias.SetValue((Vector4)shadow.EffectiveDepthBias); _parameterNormalOffset.SetValue((Vector4)shadow.EffectiveNormalOffset); Vector3 lightBackwardWorld = lightNode.PoseWorld.Orientation.GetColumn(2); _parameterLightDirection.SetValue((Vector3)cameraPose.ToLocalDirection(lightBackwardWorld)); _parameterNumberOfCascades.SetValue(shadow.NumberOfCascades); _parameterShadowMap.SetValue(shadow.ShadowMap); var rectangle = GraphicsHelper.GetViewportRectangle(cameraNode, viewport, lightNode); Vector2F texCoordTopLeft = new Vector2F(rectangle.Left / (float)viewport.Width, rectangle.Top / (float)viewport.Height); Vector2F texCoordBottomRight = new Vector2F(rectangle.Right / (float)viewport.Width, rectangle.Bottom / (float)viewport.Height); GraphicsHelper.GetFrustumFarCorners(cameraNode.Camera.Projection, texCoordTopLeft, texCoordBottomRight, _frustumFarCorners); _parameterFrustumCorners.SetValue(_frustumFarCorners); var pass = GetPass(numberOfSamples, shadow.CascadeSelection, shadow.VisualizeCascades); if (numberOfSamples > 0) { if (_lastNumberOfSamples != numberOfSamples) { // Create an array with the first n samples and the rest set to 0. _lastNumberOfSamples = numberOfSamples; for (int j = 0; j < numberOfSamples; j++) { _samples[j].Y = StandardShadowMaskRenderer.PoissonKernel[j].Y; _samples[j].X = StandardShadowMaskRenderer.PoissonKernel[j].X; _samples[j].Z = 1.0f / numberOfSamples; } // Set the rest to zero. for (int j = numberOfSamples; j < _samples.Length; j++) { _samples[j] = Vector3.Zero; } _parameterSamples.SetValue(_samples); } else if (i == 0) { // Apply offsets in the first loop. _parameterSamples.SetValue(_samples); } } pass.Apply(); graphicsDevice.DrawQuad(rectangle); } _parameterGBuffer0.SetValue((Texture2D)null); _parameterJitterMap.SetValue((Texture2D)null); _parameterShadowMap.SetValue((Texture2D)null); savedRenderState.Restore(); }