Beispiel #1
0
        protected override void DrawCore(RenderContext contextParameters)
        {
            var input  = GetInput(0);
            var output = GetOutput(0) ?? input;

            if (input == null)
            {
                return;
            }

            // Downscale to 1/2
            var halfSize             = input.Size.Down2();
            var halfSizeRenderTarget = NewScopedRenderTarget2D(halfSize.Width, halfSize.Height, input.Format);

            Scaler.SetInput(input);
            Scaler.SetOutput(halfSizeRenderTarget);
            Scaler.Draw(contextParameters, "Downsize to 0.5");

            // Work on a blurred bright map
            var blurredBright = NewScopedRenderTarget2D(halfSizeRenderTarget.Description);

            blur.Radius = 8;
            blur.SetInput(halfSizeRenderTarget);
            blur.SetOutput(blurredBright);
            blur.Draw(contextParameters);

            // Draws a few artifacts
            var flareRenderTargetInitial = NewScopedRenderTarget2D(halfSizeRenderTarget.Description);
            var flareRenderTarget        = NewScopedRenderTarget2D(halfSizeRenderTarget.Description);

            flareArtifactEffect.Parameters.Set(FlareArtifactKeys.Count, ZoomOffsetsDistortions.Length);
            flareArtifactEffect.Parameters.Set(FlareArtifactShaderKeys.ZoomOffsetsDistortions, ZoomOffsetsDistortions);
            flareArtifactEffect.Parameters.Set(FlareArtifactShaderKeys.AberrationStrength, ColorAberrationStrength);
            flareArtifactEffect.Parameters.Set(FlareArtifactShaderKeys.ColorAberrations, ColorAberrations);
            flareArtifactEffect.Parameters.Set(FlareArtifactShaderKeys.Amount, Amount * 0.0005f);
            flareArtifactEffect.SetInput(0, blurredBright);
            flareArtifactEffect.SetOutput(flareRenderTargetInitial);
            flareArtifactEffect.Draw(contextParameters);

            // Replicates the artifacts around
            flareReplicateEffect.Parameters.Set(FlareReplicateKeys.Amount, Amount * 0.0005f);
            flareReplicateEffect.Parameters.Set(FlareReplicateKeys.HaloFactor, Amount * 0.0005f * HaloFactor);
            flareReplicateEffect.SetInput(0, flareRenderTargetInitial);
            flareReplicateEffect.SetInput(1, blurredBright);
            flareReplicateEffect.SetOutput(flareRenderTarget);
            flareReplicateEffect.Draw(contextParameters);

            // Adds the result to the scene
            GraphicsDevice.SetBlendState(GraphicsDevice.BlendStates.Additive);
            Scaler.SetInput(flareRenderTarget);
            Scaler.SetOutput(output);
            Scaler.Draw(contextParameters);
            GraphicsDevice.SetBlendState(GraphicsDevice.BlendStates.Default);
        }
Beispiel #2
0
        protected override void DrawCore(RenderContext context)
        {
            var input  = GetSafeInput(0);
            var output = GetSafeOutput(0);

            // Render the luminance to a power-of-two target, so we preserve energy on downscaling
            var startWidth      = Math.Max(1, Math.Min(MathUtil.NextPowerOfTwo(input.Size.Width), MathUtil.NextPowerOfTwo(input.Size.Height)) / 2);
            var startSize       = new Size3(startWidth, startWidth, 1);
            var blurTextureSize = startSize.Down2(UpscaleCount);

            Texture outputTextureDown = null;

            if (blurTextureSize.Width != 1 && blurTextureSize.Height != 1)
            {
                outputTextureDown = NewScopedRenderTarget2D(blurTextureSize.Width, blurTextureSize.Height, luminanceFormat, 1);
            }

            var luminanceMap = NewScopedRenderTarget2D(startSize.Width, startSize.Height, luminanceFormat, 1);

            // Calculate the first luminance map
            luminanceLogEffect.SetInput(input);
            luminanceLogEffect.SetOutput(luminanceMap);
            luminanceLogEffect.Draw(context);

            // Downscales luminance up to BlurTexture (optional) and 1x1
            multiScaler.SetInput(luminanceMap);
            if (outputTextureDown == null)
            {
                multiScaler.SetOutput(luminance1x1);
            }
            else
            {
                multiScaler.SetOutput(outputTextureDown, luminance1x1);
            }
            multiScaler.Draw();

            // If we have an output texture
            if (outputTextureDown != null)
            {
                // Blur x2 the intermediate output texture
                blur.SetInput(outputTextureDown);
                blur.SetOutput(outputTextureDown);
                blur.Draw(context);
                blur.Draw(context);

                // Upscale from intermediate to output
                multiScaler.SetInput(outputTextureDown);
                multiScaler.SetOutput(output);
                multiScaler.Draw(context);
            }
            else
            {
                // TODO: Workaround to that the output filled with 1x1
                Scaler.SetInput(luminance1x1);
                Scaler.SetOutput(output);
                Scaler.Draw(context);
            }

            // Calculate average luminance only if needed
            if (EnableAverageLuminanceReadback)
            {
                readback.SetInput(luminance1x1);
                readback.Draw();
                var rawLogValue = readback.Result[0];
                AverageLuminance = (float)Math.Pow(2.0, rawLogValue);

                // In case AvergaeLuminance go crazy because of halp float/infinity precision, some code to save the values here:
                //if (float.IsInfinity(AverageLuminance))
                //{
                //    using (var stream = new FileStream("luminance_input.dds", FileMode.Create, FileAccess.Write))
                //    {
                //        input.Save(stream, ImageFileType.Dds);
                //    }
                //    using (var stream = new FileStream("luminance.dds", FileMode.Create, FileAccess.Write))
                //    {
                //        luminanceMap.Save(stream, ImageFileType.Dds);
                //    }
                //}
            }
        }
Beispiel #3
0
        protected override void DrawCore(RenderDrawContext contextParameters)
        {
            var input  = GetInput(0);
            var output = GetOutput(0) ?? input;

            if (input == null || StreakCount == 0 || IterationCount == 0)
            {
                return;
            }

            // Downscale to 1 / 4
            var halfSize             = input.Size.Down2();
            var halfSizeRenderTarget = NewScopedRenderTarget2D(halfSize.Width, halfSize.Height, input.Format);

            Scaler.SetInput(input);
            Scaler.SetOutput(halfSizeRenderTarget);
            Scaler.Draw(contextParameters, "Downsize to 0.5");

            var fourthSize             = halfSize.Down2();
            var fourthSizeRenderTarget = NewScopedRenderTarget2D(fourthSize.Width, fourthSize.Height, input.Format);

            Scaler.SetInput(halfSizeRenderTarget);
            Scaler.SetOutput(fourthSizeRenderTarget);
            Scaler.Draw(contextParameters, "Downsize to 0.25");

            var originalDownsize = fourthSizeRenderTarget;

            // Put all the streaks in an accumulation buffer
            var accumulationBuffer = NewScopedRenderTarget2D(fourthSizeRenderTarget.Description);

            // 2 scratch textures to ping-pong between
            var scratchTextureA = NewScopedRenderTarget2D(fourthSizeRenderTarget.Description);
            var scratchTextureB = NewScopedRenderTarget2D(fourthSizeRenderTarget.Description);
            var writeToScratchA = true;

            Vector2 direction;
            Texture currentInput = null, currentOutput = null;

            Vector3 colorAberration;

            colorAberration.X = (float)MathUtil.Lerp(1.0, ColorAberrationCoefficients.X, ColorAberrationStrength);
            colorAberration.Y = (float)MathUtil.Lerp(1.0, ColorAberrationCoefficients.Y, ColorAberrationStrength);
            colorAberration.Z = (float)MathUtil.Lerp(1.0, ColorAberrationCoefficients.Z, ColorAberrationStrength);

            lightStreakEffect.Parameters.Set(LightStreakShaderKeys.ColorAberrationCoefficients, colorAberration);

            for (int streak = 0; streak < StreakCount; streak++)
            {
                // Treats one streak

                // Direction vector
                float angle = MathUtil.DegreesToRadians(Phase) + streak * MathUtil.TwoPi / StreakCount;
                direction.X = (float)Math.Cos(angle);
                direction.Y = (float)Math.Sin(angle);

                // Extends the length recursively
                for (int level = 0; level < IterationCount; level++)
                {
                    // Calculates weights and attenuation factors for all the taps
                    float totalWeight = 0;
                    float passLength  = (float)Math.Pow(TapsPerIteration, level);
                    for (int i = 0; i < TapsPerIteration; i++)
                    {
                        tapOffsetsWeights[i].X = i * passLength;
                        tapOffsetsWeights[i].Y = (float)Math.Pow(MathUtil.Lerp(0.7f, 1.0f, Attenuation), i * passLength);
                        totalWeight           += tapOffsetsWeights[i].Y;
                    }
                    // Normalizes the weights
                    for (int i = 0; i < TapsPerIteration; i++)
                    {
                        tapOffsetsWeights[i].Y /= totalWeight;
                    }

                    currentInput = writeToScratchA ? scratchTextureB : scratchTextureA;
                    if (level == 0)
                    {
                        currentInput = originalDownsize;
                    }
                    currentOutput = writeToScratchA ? scratchTextureA : scratchTextureB;

                    lightStreakEffect.Parameters.Set(LightStreakKeys.Count, TapsPerIteration);
                    lightStreakEffect.Parameters.Set(LightStreakKeys.AnamorphicCount, AnamorphicOffsetsWeights.Length);
                    lightStreakEffect.Parameters.Set(LightStreakShaderKeys.TapOffsetsWeights, tapOffsetsWeights);
                    lightStreakEffect.Parameters.Set(LightStreakShaderKeys.AnamorphicOffsetsWeight, AnamorphicOffsetsWeights);
                    lightStreakEffect.Parameters.Set(LightStreakShaderKeys.Direction, direction);
                    lightStreakEffect.SetInput(0, currentInput);
                    lightStreakEffect.SetOutput(currentOutput);
                    lightStreakEffect.Draw(contextParameters, lightStreakDebugStrings[(streak * IterationCount) + level]);

                    writeToScratchA = !writeToScratchA;
                }

                // Writes this streak to the accumulation buffer
                if (streak > 0)
                {
                    combiner.BlendState = BlendStates.Additive;
                }

                combiner.SetInput(0, currentOutput);
                combiner.Factors[0] = (1f / StreakCount) * 0.2f * Amount;
                combiner.SetOutput(accumulationBuffer);
                ((RendererBase)combiner).Draw(contextParameters);
                combiner.BlendState = BlendStates.Default;
            }

            // All the light streaks have been drawn to the accumulation buffer.
            // Upscales and blurs the accumulation buffer.
            var accumulationUpscaled = NewScopedRenderTarget2D(halfSizeRenderTarget.Description);

            Scaler.SetInput(accumulationBuffer);
            Scaler.SetOutput(accumulationUpscaled);
            ((RendererBase)Scaler).Draw(contextParameters);

            blur.Radius = 3;
            blur.SetInput(accumulationUpscaled);
            blur.SetOutput(accumulationUpscaled);
            ((RendererBase)blur).Draw(contextParameters);

            // Adds the result to the original color buffer.
            Scaler.BlendState = BlendStates.Additive;
            Scaler.SetInput(accumulationUpscaled);
            Scaler.SetOutput(output);
            ((RendererBase)Scaler).Draw(contextParameters);
            Scaler.BlendState = BlendStates.Default;
        }
Beispiel #4
0
        protected override void DrawCore(RenderDrawContext context)
        {
            var input  = GetInput(0);
            var output = GetOutput(0) ?? input;

            if (input == null)
            {
                return;
            }

            // If afterimage is active, add some persistence to the brightness
            if (afterimage.Enabled)
            {
                var persistenceBrightness = NewScopedRenderTarget2D(input.Description);
                afterimage.SetInput(0, input);
                afterimage.SetOutput(persistenceBrightness);
                ((RendererBase)afterimage).Draw(context);
                input = persistenceBrightness;
            }

            // A distortion can be applied to the bloom effect to simulate anamorphic lenses
            if (Distortion.X > 1f || Distortion.Y > 1f)
            {
                int distortedWidth  = (int)Math.Max(1, input.Description.Width / Distortion.X);
                int distortedHeight = (int)Math.Max(1, input.Description.Height / Distortion.Y);
                var anamorphicInput = NewScopedRenderTarget2D(distortedWidth, distortedHeight, input.Format);
                Scaler.SetInput(input);
                Scaler.SetOutput(anamorphicInput);
                Scaler.Draw(context, "Anamorphic distortion");
                input = anamorphicInput;
            }

            // ----------------------------------------
            // Downscale / 4
            // ----------------------------------------
            const int DownScaleBasis    = 1;
            var       nextSize          = input.Size.Down2(DownScaleBasis);
            var       inputTextureDown4 = NewScopedRenderTarget2D(nextSize.Width, nextSize.Height, input.Format);

            Scaler.SetInput(input);
            Scaler.SetOutput(inputTextureDown4);
            Scaler.Draw(context, "Down/4");

            var blurTexture = inputTextureDown4;

            // TODO: Support automatic additional downscales based on a quality parameter instead
            // Additional downscales
            if (DownScale > 0)
            {
                nextSize    = nextSize.Down2(DownScale);
                blurTexture = NewScopedRenderTarget2D(nextSize.Width, nextSize.Height, input.Format);

                multiScaler.SetInput(inputTextureDown4);
                multiScaler.SetOutput(blurTexture);
                ((RendererBase)multiScaler).Draw(context);
            }

            // Max blur size no more than 1/4 of input size
            var inputMaxBlurRadiusInPixels = 0.25 * Math.Max(input.Width, input.Height) * Math.Pow(2, -DownScaleBasis - DownScale);

            blur.Radius     = Math.Max(1, (int)MathUtil.Lerp(1, inputMaxBlurRadiusInPixels, Math.Max(0, Radius / 100.0f)));
            blur.SigmaRatio = Math.Max(1.0f, SigmaRatio);
            blur.SetInput(blurTexture);
            blur.SetOutput(blurTexture);
            ((RendererBase)blur).Draw(context);

            // TODO: Support automatic additional downscales
            if (DownScale > 0)
            {
                multiScaler.SetInput(blurTexture);
                multiScaler.SetOutput(inputTextureDown4);
                ((RendererBase)multiScaler).Draw(context);
            }

            // Copy the input texture to the output
            if (ShowOnlyMip || ShowOnlyBloom)
            {
                context.CommandList.Clear(output, Color.Black);
            }

            // Switch to additive
            Scaler.BlendState = BlendStates.Additive;

            Scaler.Color = new Color4(Amount);
            Scaler.SetInput(inputTextureDown4);
            Scaler.SetOutput(output);
            ((RendererBase)Scaler).Draw(context);
            Scaler.Reset();

            Scaler.BlendState = BlendStates.Default;
        }