예제 #1
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);
                //    }
                //}
            }
        }
예제 #2
0
파일: Bloom.cs 프로젝트: sonicviz/xenko
        protected override void DrawCore(RenderContext 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);
                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);
                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);
            blur.Draw(context);

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

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

            // Switch to additive
            GraphicsDevice.SetBlendState(GraphicsDevice.BlendStates.Additive);

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

            GraphicsDevice.SetBlendState(GraphicsDevice.BlendStates.Default);
        }