Guest User

Untitled

a guest
Jul 18th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.81 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Graphics;
  5. using nulltech.Cameras;
  6. using nulltech.Sampling;
  7. using nulltech.Services;
  8. using MathHelper = Microsoft.Xna.Framework.MathHelper;
  9.  
  10. namespace nulltech.Illumination.AO
  11. {
  12.     public class AlchemyAmbientOcclusion : AmbientOcclusion
  13.     {
  14.         private readonly Effect _blurEffect;
  15.         private readonly EngineServices _services;
  16.         private int _aoSampleCount = 12;
  17.         private RenderTarget2D _aoTarget;
  18.         private float _bias;
  19.         private EffectParameter _biasParam;
  20.         private float _blurDepthThreshold;
  21.         private EffectParameter _blurDepthThresholdParam;
  22.         private EffectParameter _blurInvertViewportParam;
  23.         private Vector2[] _blurOffset;
  24.         private EffectParameter _blurOffsetParam;
  25.         private RenderTarget2D _blurPassTarget;
  26.         private int _blurSampleCount = 25;
  27.         private EffectParameter _blurWeightParam;
  28.         private float _contrast;
  29.         private EffectParameter _contrastParam;
  30.         private float _intensityScale;
  31.         private EffectParameter _intensityScaleParam;
  32.         private EffectParameter _projConstParam;
  33.         private float _radius;
  34.         private EffectParameter _radiusParam;
  35.         private float[] _sampleOffsets;
  36.         private float[] _sampleWeights;
  37.         private Vector2[] _samples;
  38.         private EffectParameter _samplesParam;
  39.  
  40.         public AlchemyAmbientOcclusion(EngineServices services)
  41.             : base(services)
  42.         {
  43.             _services = services;
  44.  
  45.             AOEffect = services.ContentManager.Load<Effect>(@"Effects\AO\AlchemyAO");
  46.  
  47.             _blurEffect = services.ContentManager.Load<Effect>(@"Effects\AO\BilateralBlur");
  48.  
  49.             ProcessEffect();
  50.  
  51.             CalculateSamples();
  52.  
  53.             Radius = 0.01f;
  54.  
  55.             Bias = 0.0018f;
  56.  
  57.             BlurRadius = .25f;
  58.  
  59.             IntensityScale = 13f;
  60.             Contrast = 5f;
  61.  
  62.             BlurDepthThreshold = 0.02f;
  63.  
  64.             HalfResolution = false;
  65.  
  66.             GenerateRenderTargets();
  67.  
  68.             CalculateBlurSamples();
  69.         }
  70.  
  71.         public bool HalfResolution { get; set; }
  72.  
  73.         public float Radius
  74.         {
  75.             get { return _radius; }
  76.             set
  77.             {
  78.                 _radius = value;
  79.                 _radiusParam.SetValue(value);
  80.             }
  81.         }
  82.  
  83.         public float BlurRadius { get; set; }
  84.  
  85.         public float BlurDepthThreshold
  86.         {
  87.             get { return _blurDepthThreshold; }
  88.             set
  89.             {
  90.                 _blurDepthThreshold = value;
  91.                 _blurDepthThresholdParam.SetValue(value);
  92.             }
  93.         }
  94.  
  95.         public float IntensityScale
  96.         {
  97.             get { return _intensityScale; }
  98.             set
  99.             {
  100.                 _intensityScale = value;
  101.                 _intensityScaleParam.SetValue(value);
  102.             }
  103.         }
  104.  
  105.         public float Contrast
  106.         {
  107.             get { return _contrast; }
  108.             set
  109.             {
  110.                 _contrast = value;
  111.                 _contrastParam.SetValue(value);
  112.             }
  113.         }
  114.  
  115.         public float Bias
  116.         {
  117.             get { return _bias; }
  118.             set
  119.             {
  120.                 _bias = value;
  121.                 _biasParam.SetValue(value);
  122.             }
  123.         }
  124.  
  125.         private void GenerateRenderTargets()
  126.         {
  127.             PresentationParameters pp = _services.GraphicsDevice.PresentationParameters;
  128.             int width = pp.BackBufferWidth;
  129.             int halfwidth = HalfResolution ? width/2 : width;
  130.             int height = pp.BackBufferHeight;
  131.             int halfheight = HalfResolution ? height/2 : height;
  132.  
  133.             _aoTarget = new RenderTarget2D(GraphicsDevice, halfwidth, halfheight, false, SurfaceFormat.Color,
  134.                                            DepthFormat.None);
  135.             _blurPassTarget = new RenderTarget2D(GraphicsDevice, width, height, false, SurfaceFormat.Color,
  136.                                                  DepthFormat.None);
  137.         }
  138.  
  139.         private void CalculateBlurSamples()
  140.         {
  141.             _sampleWeights = new float[_blurSampleCount];
  142.             _sampleOffsets = new float[_blurSampleCount];
  143.             _blurOffset = new Vector2[_blurSampleCount];
  144.  
  145.             const float theta = 2f;
  146.  
  147.             _sampleWeights[0] = (float) ((1.0/Math.Sqrt(2*Math.PI*theta))*Math.Exp(-(0*(float) 0)/(2*theta*theta)));
  148.             _sampleOffsets[0] = 0;
  149.  
  150.             float minweight = _sampleWeights[0];
  151.  
  152.             for (int i = 0; i < _blurSampleCount/2; i++)
  153.             {
  154.                 float n = (i + 1);
  155.                 var weight = (float) ((1.0/Math.Sqrt(2*Math.PI*theta))*Math.Exp(-(n*n)/(2*theta*theta)));
  156.                 _sampleWeights[i*2 + 1] = weight;
  157.                 _sampleWeights[i*2 + 2] = weight;
  158.  
  159.                 minweight = Math.Min(weight, minweight);
  160.  
  161.                 float sampleOffset = i + 1.5f;
  162.  
  163.                 _sampleOffsets[i*2 + 1] = sampleOffset;
  164.                 _sampleOffsets[i*2 + 2] = -sampleOffset;
  165.             }
  166.  
  167.             for (int i = 0; i < _blurSampleCount; i++)
  168.             {
  169.                 _sampleWeights[i] /= minweight;
  170.             }
  171.  
  172.             _blurWeightParam.SetValue(_sampleWeights);
  173.         }
  174.  
  175.         protected override sealed void ProcessEffect()
  176.         {
  177.             _samplesParam = AOEffect.Parameters["samples"];
  178.             _aoSampleCount = _samplesParam.Elements.Count;
  179.  
  180.             _projConstParam = AOEffect.Parameters["projConst"];
  181.  
  182.             _intensityScaleParam = AOEffect.Parameters["intensityScale"];
  183.             _contrastParam = AOEffect.Parameters["contrast"];
  184.             _biasParam = AOEffect.Parameters["bias"];
  185.             _radiusParam = AOEffect.Parameters["radius"];
  186.  
  187.             _blurWeightParam = _blurEffect.Parameters["blurWeights"];
  188.             _blurOffsetParam = _blurEffect.Parameters["blurOffsets"];
  189.  
  190.             _blurSampleCount = _blurOffsetParam.Elements.Count;
  191.  
  192.             _blurDepthThresholdParam = _blurEffect.Parameters["BlurDepthThreshold"];
  193.             _blurInvertViewportParam = _blurEffect.Parameters["InverseViewportDimensions"];
  194.  
  195.             base.ProcessEffect();
  196.         }
  197.  
  198.         private void CalculateSamples()
  199.         {
  200.             _samples = new Vector2[_aoSampleCount];
  201.  
  202.             List<Vector2> samples = UniformPoissonDiskSampler.SampleCircle(_aoSampleCount, Vector2.Zero, 1.0f, .25f);
  203.  
  204.             for (int i = 0; i < _aoSampleCount; i++)
  205.             {
  206.                 _samples[i] = samples[i];
  207.             }
  208.  
  209.             _samplesParam.SetValue(_samples);
  210.         }
  211.  
  212.         public override void Calculate(CameraEntity camera)
  213.         {
  214.             PresentationParameters pp = GraphicsDevice.PresentationParameters;
  215.             float halffov = camera.ProjectionController.Fov*.5f;
  216.             int ph = pp.BackBufferHeight;
  217.             float ar = camera.ProjectionController.AspectRatio;
  218.             var hftg = (float) Math.Tan(MathHelper.ToRadians(halffov/ar));
  219.             float near = camera.ProjectionController.Near;
  220.             _projConstParam.SetValue(ph/(2*hftg*near));
  221.  
  222.             GenerateCorners(camera);
  223.  
  224.             Vector2 ivp = camera.InverseViewport;
  225.             _blurInvertViewportParam.SetValue(ivp);
  226.  
  227.             GraphicsDevice.SetRenderTarget(_aoTarget);
  228.  
  229.             AOEffect.CurrentTechnique.Passes[0].Apply();
  230.             GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, Vertices, 0, 2);
  231.  
  232.             GraphicsDevice.SetRenderTarget(_blurPassTarget);
  233.  
  234.             for (int i = 0; i < _blurSampleCount; i++)
  235.             {
  236.                 _blurOffset[i].X = _sampleOffsets[i]*ivp.X*BlurRadius;
  237.                 _blurOffset[i].Y = 0;
  238.             }
  239.  
  240.             _blurOffsetParam.SetValue(_blurOffset);
  241.  
  242.             GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
  243.             GraphicsDevice.Textures[0] = _aoTarget;
  244.  
  245.             _blurEffect.CurrentTechnique.Passes[0].Apply();
  246.             GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, Vertices, 0, 2);
  247.         }
  248.  
  249.         public override void Draw(CameraEntity camera)
  250.         {
  251.             Vector2 ivp = camera.InverseViewport;
  252.  
  253.             for (int i = 0; i < _blurSampleCount; i++)
  254.             {
  255.                 _blurOffset[i].X = 0;
  256.                 _blurOffset[i].Y = _sampleOffsets[i]*ivp.Y*BlurRadius;
  257.             }
  258.  
  259.             _blurOffsetParam.SetValue(_blurOffset);
  260.  
  261.             GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
  262.             GraphicsDevice.Textures[0] = _blurPassTarget;
  263.  
  264.             _blurEffect.CurrentTechnique.Passes[0].Apply();
  265.             GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, Vertices, 0, 2);
  266.         }
  267.     }
  268. }
Add Comment
Please, Sign In to add comment