Example #1
0
 public void Mutate()
 {
     for (int i = 0; i < _jobsLength; i++)
     {
         if (SimpleRNG.GetUniform() < _mutationRate)
         {
             int r    = SimpleRNG.Next(0, _jobsLength);
             int temp = JobGenes[i];
             JobGenes[i] = JobGenes[r];
             JobGenes[r] = temp;
             // Mutate the delay time
             r = SimpleRNG.Next(0, _modesLength);
             double mutatedDelay = 0;
             //mutatedDelay = SimpleRNG.GetExponential(_delayMean);
             mutatedDelay = SimpleRNG.GetNormal(TimeGenes[r], 1.0);
             //mutatedDelay = _rand.NextDouble() * _delayMean;
             if (mutatedDelay < 0.0)
             {
                 mutatedDelay = 0.0;
             }
             TimeGenes[r] = mutatedDelay;
         }
     }
     //Mutate the Mode vector:
     for (int i = 0; i < _modesLength; i++)
     {
         if (SimpleRNG.GetUniform() < _mutationRate)
         {
             ModeGenes[i] = SimpleRNG.Next(0, _numberOfModes);
         }
     }
 }
Example #2
0
        void    BuildNoiseTextures()
        {
            PixelsBuffer Content   = new PixelsBuffer(NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * 4);
            PixelsBuffer Content4D = new PixelsBuffer(NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * 16);

            SimpleRNG.SetSeed(521288629, 362436069);

            float4 V = float4.Zero;

            using (BinaryWriter W = Content.OpenStreamWrite()) {
                using (BinaryWriter W2 = Content4D.OpenStreamWrite()) {
                    for (int Z = 0; Z < NOISE_SIZE; Z++)
                    {
                        for (int Y = 0; Y < NOISE_SIZE; Y++)
                        {
                            for (int X = 0; X < NOISE_SIZE; X++)
                            {
                                V.Set((float)SimpleRNG.GetUniform(), (float)SimpleRNG.GetUniform(), (float)SimpleRNG.GetUniform(), (float)SimpleRNG.GetUniform());
                                W.Write(V.x);
                                W2.Write(V.x);
                                W2.Write(V.y);
                                W2.Write(V.z);
                                W2.Write(V.w);
                            }
                        }
                    }
                }
            }

            m_Tex_Noise   = new Texture3D(m_Device, NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, 1, ImageUtility.PIXEL_FORMAT.R8, ImageUtility.COMPONENT_FORMAT.UNORM, false, false, new PixelsBuffer[] { Content });
            m_Tex_Noise4D = new Texture3D(m_Device, NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, 1, ImageUtility.PIXEL_FORMAT.RGBA8, ImageUtility.COMPONENT_FORMAT.UNORM, false, false, new PixelsBuffer[] { Content4D });
        }
Example #3
0
            public void RandomInit()
            {
                List <int> randarray = new List <int>();

                for (int i = 0; i < _jobsLength; i++)
                {
                    randarray.Add(i);
                }
                for (int i = 0; i < _jobsLength; i++)
                {
                    int r = SimpleRNG.Next(0, _jobsLength - i);
                    JobGenes[i] = randarray[r];
                    randarray.RemoveAt(r);
                }
                for (int i = 0; i < _timesLength; i++)
                {
                    if (SimpleRNG.GetUniform() < _delayRate)
                    {
                        TimeGenes[i] = SimpleRNG.GetExponential(_delayMean);
                    }
                    else
                    {
                        TimeGenes[i] = 0.0;
                    }
                    ModeGenes[i] = SimpleRNG.Next(0, _numberOfModes);
                }

                fitness = -1;
            }
Example #4
0
        private double  GetTheta()
        {
            double x     = SimpleRNG.GetUniform();
            int    index = Math.Min(m_UniformRandom2Angle.Length - 1, (int)Math.Floor(x * m_UniformRandom2Angle.Length));
            double value = m_UniformRandom2Angle[index];

            return(value);
        }
Example #5
0
        /// <summary>
        /// Generates blue noise distribution by randomly swapping pixels in the texture to reach lowest possible score and minimize a specific energy function
        /// </summary>
        /// <param name="_randomSeed"></param>
        /// <param name="_minEnergyThreshold"></param>
        /// <param name="_maxIterations"></param>
        /// <param name="_standardDeviationImage">Standard deviation for image space. If not sure, use 2.1</param>
        /// <param name="_standardDeviationValue">Standard deviation for value space. If not sure, use 1.0</param>
        /// <param name="_progress"></param>
        public void             Generate(uint _randomSeed, float _minEnergyThreshold, int _maxIterations, float _standardDeviationImage, float _standardDeviationValue, ProgressDelegate _progress)
        {
            m_kernelFactorImage = -1.0 / (_standardDeviationImage * _standardDeviationImage);
            m_kernelFactorValue = -1.0 / (_standardDeviationValue * _standardDeviationValue);

            // Generate initial white noise
            SimpleRNG.SetSeed(_randomSeed);
            for (int Y = 0; Y < m_textureSize; Y++)
            {
                for (int X = 0; X < m_textureSize; X++)
                {
                    m_textures[0][X, Y] = (float)SimpleRNG.GetUniform();
                }
            }

            // Perform iterations
            float bestScore      = ComputeScore(m_textures[0]);
            int   iterationIndex = 0;

            while (iterationIndex < _maxIterations && bestScore > _minEnergyThreshold)
            {
                // Copy source to target array
                Array.Copy(m_textures[0], m_textures[1], m_textureTotalSize);

                // Swap up to N pixels randomly
                for (int swapCount = 0; swapCount < MAX_SWAPPED_ELEMENTS_PER_ITERATION; swapCount++)
                {
                    uint sourceIndex = GetUniformInt(m_textureTotalSize);
                    uint targetIndex = sourceIndex;
                    while (targetIndex == sourceIndex)
                    {
                        targetIndex = GetUniformInt(m_textureTotalSize);                                // Make sure target index differs!
                    }
                    float temp = Get(m_textures[1], sourceIndex);
                    Set(m_textures[1], sourceIndex, Get(m_textures[1], targetIndex));
                    Set(m_textures[1], targetIndex, temp);
                }

                // Compute new score
                float score = ComputeScore(m_textures[1]);
                if (score < bestScore)
                {
                    // New best score! Swap textures...
                    bestScore            = score;
                    float[,]        temp = m_textures[0];
                    m_textures[0]        = m_textures[1];
                    m_textures[1]        = temp;
                }

                iterationIndex++;
                if (_progress != null)
                {
                    _progress(iterationIndex, bestScore, m_textures[0]);                        // Notify!
                }
            }
        }
Example #6
0
        private void    BuildRandomBuffer()
        {
            Reg(m_SB_Random = new StructuredBuffer <float4>(m_Device, RANDOM_TABLE_SIZE, true));
            for (int i = 0; i < RANDOM_TABLE_SIZE; i++)
            {
//				m_SB_Random.m[i] = new float4( (float) SimpleRNG.GetUniform(), (float) SimpleRNG.GetUniform(), (float) SimpleRNG.GetUniform(), (float) SimpleRNG.GetUniform() );
                m_SB_Random.m[i] = new float4((float)SimpleRNG.GetUniform(), (float)SimpleRNG.GetUniform(), (float)SimpleRNG.GetUniform(), -(float)Math.Log(1e-3 + (1.0 - 1e-3) * SimpleRNG.GetUniform()));
            }
            m_SB_Random.Write();
        }
Example #7
0
        private void    GenerateRays(int _raysCount, StructuredBuffer <float3> _target)
        {
            _raysCount = Math.Min(MAX_THREADS, _raysCount);

            // Half-Life 2 basis
            float3[] HL2Basis = new float3[] {
                new float3((float)Math.Sqrt(2.0 / 3.0), 0.0f, (float)Math.Sqrt(1.0 / 3.0)),
                new float3(-(float)Math.Sqrt(1.0 / 6.0), (float)Math.Sqrt(1.0 / 2.0), (float)Math.Sqrt(1.0 / 3.0)),
                new float3(-(float)Math.Sqrt(1.0 / 6.0), -(float)Math.Sqrt(1.0 / 2.0), (float)Math.Sqrt(1.0 / 3.0))
            };

            float centerTheta = (float)Math.Acos(HL2Basis[0].z);

            float[] centerPhi = new float[] {
                (float)Math.Atan2(HL2Basis[0].y, HL2Basis[0].x),
                (float)Math.Atan2(HL2Basis[1].y, HL2Basis[1].x),
                (float)Math.Atan2(HL2Basis[2].y, HL2Basis[2].x),
            };

            for (int rayIndex = 0; rayIndex < _raysCount; rayIndex++)
            {
                double phi = (Math.PI / 3.0) * (2.0 * SimpleRNG.GetUniform() - 1.0);

                // Stratified version
                double theta = (Math.Acos(Math.Sqrt((rayIndex + SimpleRNG.GetUniform()) / _raysCount)));

//              // Don't give a shit version (a.k.a. melonhead version)
// //				double	Theta = Math.Acos( Math.Sqrt(WMath.SimpleRNG.GetUniform() ) );
//              double	Theta = 0.5 * Math.PI * WMath.SimpleRNG.GetUniform();

                theta = Math.Min(0.499f * Math.PI, theta);


                double cosTheta = Math.Cos(theta);
                double sinTheta = Math.Sin(theta);

                double lengthFactor = 1.0 / sinTheta;           // The ray is scaled so we ensure we always walk at least a texel in the texture
                cosTheta *= lengthFactor;
                sinTheta *= lengthFactor;                       // Yeah, yields 1... :)

                _target.m[0 * MAX_THREADS + rayIndex].Set((float)(Math.Cos(centerPhi[0] + phi) * sinTheta),
                                                          (float)(Math.Sin(centerPhi[0] + phi) * sinTheta),
                                                          (float)cosTheta);
                _target.m[1 * MAX_THREADS + rayIndex].Set((float)(Math.Cos(centerPhi[1] + phi) * sinTheta),
                                                          (float)(Math.Sin(centerPhi[1] + phi) * sinTheta),
                                                          (float)cosTheta);
                _target.m[2 * MAX_THREADS + rayIndex].Set((float)(Math.Cos(centerPhi[2] + phi) * sinTheta),
                                                          (float)(Math.Sin(centerPhi[2] + phi) * sinTheta),
                                                          (float)cosTheta);
            }

            _target.Write();
        }
Example #8
0
        private void ShowFlag(string guid, double value)
        {
            var direction = SimpleRNG.GetUniform() > 0.5 ? FlagDirection.Up : FlagDirection.Down;
            var flag      = new Flag {
                Id = guid, Value = value, FlagDirection = direction.ToString()
            };

            foreach (var h in _handlers)
            {
                h.Value(flag);
            }
        }
Example #9
0
        /// <summary>
        /// Set the random turn component of the AI.
        /// </summary>
        private float randTurn()
        {
            float offset      = 2.0f;
            float radius      = 1.0f;
            float maxRotation = MathHelper.Pi / 7.0f;

            currentRotation += (float)(SimpleRNG.GetUniform() * 2 - 1) * maxRotation;

            float width = (float)Math.Sin(currentRotation) * radius;
            float extra = (float)Math.Cos(currentRotation) * radius;

            return((float)Math.Tanh(width / (offset + extra)));
        }
Example #10
0
        public Action StartSparkline(IEnumerable <AddTimeValue> addTimeValues)
        {
            Func <int> tickTime = () => {
                // Convert.ToInt32(Math.Floor(SimpleRNG.GetUniform()*2000));
                return(1000 / 2);
            };

            Func <AddTimeValue, Action> tickGenerator = addTimeValue => {
                var x = 100.0;
                return(() => {
                    while (true)
                    {
                        var newx = x + SimpleRNG.GetNormal() * 2;
                        if (newx < 0.0)
                        {
                            newx = 0.0;
                        }
                        _dispatcher.BeginInvoke((Action)(() => {
                            var guid = addTimeValue(newx);
                            if (SimpleRNG.GetUniform() > 0.75)
                            {
                                ShowFlag(guid, newx);
                            }
                        }));
                        x = newx;
                        Thread.Sleep(tickTime());
                    }
                });
            };

            Func <Action, WaitCallback> toWaitCallback = gen => wc => gen();
            Action start = () => {
                var tickGenerators = addTimeValues.Select(tickGenerator).ToArray();
                foreach (var generateTicks in tickGenerators)
                {
                    ThreadPool.QueueUserWorkItem(toWaitCallback(generateTicks));
                }
            };

            return(start);
        }
Example #11
0
            private int SelectParent()
            {
                int p = 0;

                switch (parentSelection)
                {
                case ParentSelectionOp.FitnessProportional:
                    double totalFitness = 0;
                    for (int i = 0; i < _popsize; i++)
                    {
                        totalFitness += population[i].fitness;
                    }
                    //double r = _rand.NextDouble() * totalFitness;
                    double r            = SimpleRNG.GetUniform() * totalFitness;
                    double runningTotal = population[p].fitness;
                    while (runningTotal > r)
                    {
                        p++;
                        runningTotal += population[p].fitness;
                    }
                    break;

                case ParentSelectionOp.Tournament:
                    int k = _popsize / 10;
                    //p = _rand.Next(_popsize);
                    p = (int)(SimpleRNG.GetUniform() * _popsize);
                    double bestfitness = population[p].fitness;
                    for (int i = 0; i < k; i++)
                    {
                        int px = SimpleRNG.Next(0, _popsize);
                        if (population[px].fitness > bestfitness)
                        {
                            bestfitness = population[px].fitness;
                            p           = px;
                        }
                    }
                    break;
                }

                return(p);
            }
Example #12
0
        void    BuildNoiseTextures()
        {
            PixelsBuffer Content   = new PixelsBuffer(NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * 4);
            PixelsBuffer Content4D = new PixelsBuffer(NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * 16);

            SimpleRNG.SetSeed(521288629, 362436069);

            float4 V = float4.Zero;

            using (BinaryWriter W = Content.OpenStreamWrite()) {
                using (BinaryWriter W2 = Content4D.OpenStreamWrite()) {
                    for (int Z = 0; Z < NOISE_SIZE; Z++)
                    {
                        for (int Y = 0; Y < NOISE_SIZE; Y++)
                        {
                            for (int X = 0; X < NOISE_SIZE; X++)
                            {
                                V.Set((float)SimpleRNG.GetUniform(), (float)SimpleRNG.GetUniform(), (float)SimpleRNG.GetUniform(), (float)SimpleRNG.GetUniform());
                                W.Write(V.x);
                                W2.Write(V.x);
                                W2.Write(V.y);
                                W2.Write(V.z);
                                W2.Write(V.w);
                            }
                        }
                    }
                }
            }

            m_tex_Noise   = new Texture3D(m_device, NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, 1, ImageUtility.PIXEL_FORMAT.R8, ImageUtility.COMPONENT_FORMAT.UNORM, false, false, new PixelsBuffer[] { Content });
            m_tex_Noise4D = new Texture3D(m_device, NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, 1, ImageUtility.PIXEL_FORMAT.RGBA8, ImageUtility.COMPONENT_FORMAT.UNORM, false, false, new PixelsBuffer[] { Content4D });

            // Load blue noise
            using (ImageUtility.ImageFile I = new ImageUtility.ImageFile(new FileInfo("BlueNoise64x64_16bits.png"))) {
                ImageUtility.ImagesMatrix M = new ImageUtility.ImagesMatrix(new ImageUtility.ImageFile[, ] {
                    { I }
                });
                m_tex_BlueNoise = new Texture2D(m_device, M, ImageUtility.COMPONENT_FORMAT.UNORM);
            }
        }
Example #13
0
        private void    Generate_CPU(int _RaysCount)
        {
            try {
                tabControlGenerators.Enabled = false;

                // Half-life basis (Z points outside of the surface, as in normal maps)
                float3[] basis = new float3[] {
                    new float3((float)Math.Sqrt(2.0 / 3.0), 0.0f, (float)Math.Sqrt(1.0 / 3.0)),
                    new float3((float)-Math.Sqrt(1.0 / 6.0), (float)Math.Sqrt(1.0 / 2.0), (float)Math.Sqrt(1.0 / 3.0)),
                    new float3((float)-Math.Sqrt(1.0 / 6.0), (float)-Math.Sqrt(1.0 / 2.0), (float)Math.Sqrt(1.0 / 3.0)),
                };

//              // 1] Compute normal map
//              float3	dX = new float3();
//              float3	dY = new float3();
//              float3	N;
//              float			ddX = floatTrackbarControlPixelSize.Value;
//              float			ddH = floatTrackbarControlHeight.Value;
//              for ( int Y=0; Y < H; Y++ )
//              {
//                  int	Y0 = Math.Max( 0, Y-1 );
//                  int	Y1 = Math.Min( H-1, Y+1 );
//                  for ( int X=0; X < W; X++ )
//                  {
//                      int	X0 = Math.Max( 0, X-1 );
//                      int	X1 = Math.Min( W-1, X+1 );
//
//                      float	Hx0 = m_BitmapSource.ContentXYZ[X0,Y].y;
//                      float	Hx1 = m_BitmapSource.ContentXYZ[X1,Y].y;
//                      float	Hy0 = m_BitmapSource.ContentXYZ[X,Y0].y;
//                      float	Hy1 = m_BitmapSource.ContentXYZ[X,Y1].y;
//
//                      dX.Set( 2.0f * ddX, 0.0f, ddH * (Hx1 - Hx0) );
//                      dY.Set( 0.0f, 2.0f * ddX, ddH * (Hy1 - Hy0) );
//
//                      N = dX.Cross( dY ).Normalized;
//
//                      m_Normal[X,Y] = new float3(
//                          N.Dot( Basis[0] ),
//                          N.Dot( Basis[1] ),
//                          N.Dot( Basis[2] ) );
//                  }
//
//                  // Update and show progress
//                  UpdateProgress( m_Normal, Y, true );
//              }
//              UpdateProgress( m_Normal, H, true );

                float LobeExponent = 4.0f;                  //floatTrackbarControlLobeExponent.Value;

                float PixelSize_mm = 1000.0f / floatTrackbarControlPixelDensity.Value;

                float scale = 0.1f * PixelSize_mm / floatTrackbarControlHeight.Value;                   // Scale factor to apply to pixel distances so they're renormalized in [0,1], our "heights space"...
//						Scale *= floatTrackbarControlZFactor.Value;	// Cheat Z velocity so AO is amplified!

                // 2] Build local rays only once
                int raysCount = integerTrackbarControlRaysCount.Value;
                float3[,]       rays = new float3[3, raysCount];

                // Create orthonormal bases to orient the lobe
                float3 Xr = basis[0].Cross(float3.UnitZ).Normalized;                    // We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3 Yr = Xr.Cross(basis[0]);
                float3 Xg = basis[1].Cross(float3.UnitZ).Normalized;                    // We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3 Yg = Xg.Cross(basis[1]);
                float3 Xb = basis[2].Cross(float3.UnitZ).Normalized;                    // We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3 Yb = Xb.Cross(basis[2]);

                double Exponent = 1.0 / (1.0 + LobeExponent);
                for (int RayIndex = 0; RayIndex < raysCount; RayIndex++)
                {
//                  if ( false ) {
//                      double	Phi = 2.0 * Math.PI * WMath.SimpleRNG.GetUniform();
// //						double	Theta = Math.Acos( Math.Pow( WMath.SimpleRNG.GetUniform(), Exponent ) );
//                      double	Theta = Math.PI / 3.0 * WMath.SimpleRNG.GetUniform();
//
//                      float3	RayLocal = new float3(
//                          (float) (Math.Cos( Phi ) * Math.Sin( Theta )),
//                          (float) (Math.Sin( Phi ) * Math.Sin( Theta )),
//                          (float) Math.Cos( Theta ) );
//
//                      Rays[0,RayIndex] = RayLocal.x * Xr + RayLocal.y * Yr + RayLocal.z * Basis[0];
//                      Rays[1,RayIndex] = RayLocal.x * Xg + RayLocal.y * Yg + RayLocal.z * Basis[1];
//                      Rays[2,RayIndex] = RayLocal.x * Xb + RayLocal.y * Yb + RayLocal.z * Basis[2];
//                  } else
                    {
                        double Phi   = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0);
                        double Theta = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[0, RayIndex] = new float3(
                            (float)(Math.Cos(Phi) * Math.Sin(Theta)),
                            (float)(Math.Sin(Phi) * Math.Sin(Theta)),
                            (float)Math.Cos(Theta));

                        Phi               = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0 + 2.0);
                        Theta             = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[1, RayIndex] = new float3(
                            (float)(Math.Cos(Phi) * Math.Sin(Theta)),
                            (float)(Math.Sin(Phi) * Math.Sin(Theta)),
                            (float)Math.Cos(Theta));

                        Phi               = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0 + 4.0);
                        Theta             = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[2, RayIndex] = new float3(
                            (float)(Math.Cos(Phi) * Math.Sin(Theta)),
                            (float)(Math.Sin(Phi) * Math.Sin(Theta)),
                            (float)Math.Cos(Theta));
                    }

                    rays[0, RayIndex].z *= scale;
                    rays[1, RayIndex].z *= scale;
                    rays[2, RayIndex].z *= scale;
                }

                // 3] Compute directional occlusion
                float4[] scanline = new float4[W];
                float4   gammaRGB = float4.Zero;
                for (uint Y = 0; Y < H; Y++)
                {
                    for (uint X = 0; X < W; X++)
                    {
                        gammaRGB.x = ComputeAO(0, X, Y, scale, rays);
                        gammaRGB.y = ComputeAO(1, X, Y, scale, rays);
                        gammaRGB.z = ComputeAO(2, X, Y, scale, rays);
                        gammaRGB.w = (gammaRGB.x + gammaRGB.y + gammaRGB.z) / 3.0f;
                        m_sRGBProfile.GammaRGB2LinearRGB(gammaRGB, ref scanline[X]);
                    }
                    m_imageResult.WriteScanline(Y, scanline);

                    // Update and show progress
                    UpdateProgress(m_imageResult, Y, true);
                }
                UpdateProgress(m_imageResult, H, true);

//				m_BitmapResult.Save( "eye_generic_01_disp_hl2.png", ImageFormat.Png );
            }
            catch (Exception _e)
            {
                MessageBox("An error occurred during generation:\r\n" + _e.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                tabControlGenerators.Enabled = true;
            }
        }
Example #14
0
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try {
                // Initialize the device
                m_device = new Device();
                m_device.Init(graphPanel.Handle, false, true);

                // Create the render shaders
                try {
                    Shader.WarningAsError = false;

                    m_shader_RenderSphere = new Shader(m_device, new System.IO.FileInfo(@"./Shaders/RenderSphere.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS");
                    m_shader_RenderScene  = new Shader(m_device, new System.IO.FileInfo(@"./Shaders/RenderScene.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS");
                    m_shader_RenderLDR    = new Shader(m_device, new System.IO.FileInfo(@"./Shaders/RenderLDR.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS");
                } catch (Exception _e) {
                    throw new Exception("Failed to compile shader! " + _e.Message);
                }

                // Create CB
                m_CB_Render = new ConstantBuffer <CB_Main>(m_device, 0);

                // Create textures
                LoadHDRImage();

                m_Tex_HDRBuffer = new Texture2D(m_device, (uint)graphPanel.Width, (uint)graphPanel.Height, 2, 1, ImageUtility.PIXEL_FORMAT.RGBA32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, false, null);

                {                       // Build noise texture
                    SimpleRNG.SetSeed(1U);
                    PixelsBuffer content = new PixelsBuffer(256 * 256 * 16);
                    using (System.IO.BinaryWriter W = content.OpenStreamWrite())
                        for (int i = 0; i < 256 * 256; i++)
                        {
                            W.Write((float)SimpleRNG.GetUniform());
                            W.Write((float)SimpleRNG.GetUniform());
                            W.Write((float)SimpleRNG.GetUniform());
                            W.Write((float)SimpleRNG.GetUniform());
                        }
                    m_Tex_Noise = new Texture2D(m_device, 256, 256, 1, 1, ImageUtility.PIXEL_FORMAT.RGBA32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, false, new PixelsBuffer[] { content });
                }

                // Build SH coeffs
                const int ORDERS = 20;
                {
                    const int TABLE_SIZE = 64;

                    // Load A coeffs into a texture array
                    float[,,]       A = new float[TABLE_SIZE, TABLE_SIZE, ORDERS];
//					using ( System.IO.FileStream S = new System.IO.FileInfo( @"ConeTable_cosAO_order20.float" ).OpenRead() )
                    using (System.IO.FileStream S = new System.IO.FileInfo(@"ConeTable_cosTheta_order20.float").OpenRead())
                        using (System.IO.BinaryReader R = new System.IO.BinaryReader(S)) {
                            for (int thetaIndex = 0; thetaIndex < TABLE_SIZE; thetaIndex++)
                            {
                                for (int AOIndex = 0; AOIndex < TABLE_SIZE; AOIndex++)
                                {
                                    for (int order = 0; order < ORDERS; order++)
                                    {
                                        A[thetaIndex, AOIndex, order] = R.ReadSingle();
                                    }
                                }
                            }
                        }

                    PixelsBuffer[] coeffSlices = new PixelsBuffer[5];                           // 5 slices of 4 coeffs each to get our 20 orders
                    for (int sliceIndex = 0; sliceIndex < coeffSlices.Length; sliceIndex++)
                    {
                        PixelsBuffer coeffSlice = new PixelsBuffer(TABLE_SIZE * TABLE_SIZE * 16);
                        coeffSlices[sliceIndex] = coeffSlice;

                        using (System.IO.BinaryWriter W = coeffSlice.OpenStreamWrite()) {
                            for (int thetaIndex = 0; thetaIndex < TABLE_SIZE; thetaIndex++)
                            {
                                for (int AOIndex = 0; AOIndex < TABLE_SIZE; AOIndex++)
                                {
                                    W.Write(A[thetaIndex, AOIndex, 4 * sliceIndex + 0]);
                                    W.Write(A[thetaIndex, AOIndex, 4 * sliceIndex + 1]);
                                    W.Write(A[thetaIndex, AOIndex, 4 * sliceIndex + 2]);
                                    W.Write(A[thetaIndex, AOIndex, 4 * sliceIndex + 3]);
                                }
                            }
                        }
                    }

                    m_Tex_ACoeffs = new Texture2D(m_device, 64, 64, coeffSlices.Length, 1, ImageUtility.PIXEL_FORMAT.RGBA32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, false, coeffSlices);
                }

                {
                    // Load environment coeffs into a constant buffer
                    float3[] coeffs = new float3[ORDERS * ORDERS];
                    using (System.IO.FileStream S = new System.IO.FileInfo(@"Ennis_order20.float3").OpenRead())
                        using (System.IO.BinaryReader R = new System.IO.BinaryReader(S))
                            for (int coeffIndex = 0; coeffIndex < ORDERS * ORDERS; coeffIndex++)
                            {
                                coeffs[coeffIndex].Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle());
                            }

                    // Write into a raw byte[]
                    byte[] rawContent = new byte[400 * 4 * 4];
                    using (System.IO.MemoryStream MS = new System.IO.MemoryStream(rawContent))
                        using (System.IO.BinaryWriter W = new System.IO.BinaryWriter(MS)) {
                            for (int coeffIndex = 0; coeffIndex < ORDERS * ORDERS; coeffIndex++)
                            {
                                W.Write(coeffs[coeffIndex].x);
                                W.Write(coeffs[coeffIndex].y);
                                W.Write(coeffs[coeffIndex].z);
                                W.Write(0.0f);
                            }
                        }
                    m_CB_Coeffs = new RawConstantBuffer(m_device, 1, rawContent.Length);
                    m_CB_Coeffs.UpdateData(rawContent);
                }

                // Create camera + manipulator
                m_camera.CreatePerspectiveCamera(0.5f * (float)Math.PI, (float)graphPanel.Width / graphPanel.Height, 0.01f, 100.0f);
                m_camera.CameraTransformChanged += m_camera_CameraTransformChanged;
                m_cameraManipulator.Attach(graphPanel, m_camera);
                m_cameraManipulator.InitializeCamera(-2.0f * float3.UnitZ, float3.Zero, float3.UnitY);
                m_camera_CameraTransformChanged(null, EventArgs.Empty);

                // Start rendering
                Application.Idle += Application_Idle;
            } catch (Exception _e) {
                MessageBox.Show("Failed to initialize D3D renderer!\r\nReason: " + _e.Message);
            }
        }
Example #15
0
        /// <summary>
        /// Computes up to 20 orders of A coefficients for various AO and angle values
        /// </summary>
        void    NumericalIntegration_20Orders()
        {
            // Generate a bunch of rays with equal probability on the hemisphere
            const int    THETA_SAMPLES = 100;
            const int    SAMPLES_COUNT = 4 * THETA_SAMPLES * THETA_SAMPLES;
            const double dPhi          = 2.0 * Math.PI / (4 * THETA_SAMPLES);

            float3[] directions = new float3[SAMPLES_COUNT];
            for (int Y = 0; Y < THETA_SAMPLES; Y++)
            {
                for (int X = 0; X < 4 * THETA_SAMPLES; X++)
                {
                    double phi   = dPhi * (X + SimpleRNG.GetUniform());
                    double theta = 2.0 * Math.Acos(Math.Sqrt(1.0 - 0.5 * (Y + SimpleRNG.GetUniform()) / THETA_SAMPLES));                                // Uniform sampling on theta
                    directions[4 * THETA_SAMPLES * Y + X].Set((float)(Math.Sin(theta) * Math.Cos(phi)), (float)(Math.Sin(theta) * Math.Sin(phi)), (float)Math.Cos(theta));
                }
            }

            // Compute numerical integration for various sets of angles
            const int TABLE_SIZE = 64;
            const int ORDERS     = 20;

            float3 coneDirection = float3.Zero;

            float[,,]       integratedSHCoeffs = new float[TABLE_SIZE, TABLE_SIZE, ORDERS];

            double[] A = new double[ORDERS];
            for (int thetaIndex = 0; thetaIndex < TABLE_SIZE; thetaIndex++)
            {
                float V = (float)thetaIndex / TABLE_SIZE;
//				float	cosTheta = (float) Math.Cos( 0.5 * Math.PI * V );
                float cosTheta = V;
                coneDirection.x = (float)Math.Sqrt(1.0f - cosTheta * cosTheta);
                coneDirection.z = cosTheta;

                for (int AOIndex = 0; AOIndex < TABLE_SIZE; AOIndex++)
                {
                    float U = (float)AOIndex / TABLE_SIZE;
//					float	cosConeHalfAngle = U;
                    float cosConeHalfAngle = (float)Math.Cos(0.5 * Math.PI * U);

                    Array.Clear(A, 0, ORDERS);
                    for (int sampleIndex = 0; sampleIndex < SAMPLES_COUNT; sampleIndex++)
                    {
                        float3 direction = directions[sampleIndex];
                        if (direction.Dot(coneDirection) < cosConeHalfAngle)
                        {
                            continue;                                   // Sample is outside cone
                        }
                        float u = direction.z;                          // cos(theta_sample)
                        for (int order = 0; order < ORDERS; order++)
                        {
                            A[order] += u * SHFunctions.P0(order, u);
                        }
                    }

                    // Finalize integration
                    for (int order = 0; order < ORDERS; order++)
                    {
                        A[order] *= 2.0 * Math.PI / SAMPLES_COUNT;
                    }
                    for (int order = 0; order < ORDERS; order++)
                    {
                        integratedSHCoeffs[thetaIndex, AOIndex, order] = (float)A[order];
                    }
                }
            }

            // Save table
            using (System.IO.FileStream S = new System.IO.FileInfo(@"ConeTable_cosTheta_order20.float").Create())
                using (System.IO.BinaryWriter W = new System.IO.BinaryWriter(S)) {
                    for (int thetaIndex = 0; thetaIndex < TABLE_SIZE; thetaIndex++)
                    {
                        for (int AOIndex = 0; AOIndex < TABLE_SIZE; AOIndex++)
                        {
                            for (int order = 0; order < ORDERS; order++)
                            {
                                W.Write(integratedSHCoeffs[thetaIndex, AOIndex, order]);
                            }
                        }
                    }
                }
        }
Example #16
0
        private void buttonShoot_Click(object sender, EventArgs e)
        {
            // Clear accumulation
            for (int Y = 0; Y < TEXTURE_SIZE; Y++)
            {
                for (int X = 0; X < TEXTURE_SIZE; X++)
                {
                    m_PhotonsAccumulation[X, Y] = 0.0f;
                }
            }

            float  LightTheta = (float)Math.PI * floatTrackbarControlTheta.Value / 180.0f;
            Vector Light      = new Vector((float)-Math.Sin(LightTheta), 0.0f, (float)Math.Cos(LightTheta));
//			float	Flux = TEXTURE_SIZE*TEXTURE_SIZE / integerTrackbarControlPhotonsCount.Value;
            float Flux = 20000.0f / integerTrackbarControlPhotonsCount.Value;

            float PlaneD     = (float)Math.Cos(IRIS_START_ANGLE);
            float IrisRadius = (float)Math.Sin(IRIS_START_ANGLE);

            // Compute bounds for photon generation
            float BoundX0 = -IrisRadius;
            float BoundX1 = +IrisRadius;

            Vector Ortho = new Vector(Light.z, 0.0f, -Light.x);                 // Vector tangent to the plane where we can measure projected bounds

            float ProjectedBound0 = BoundX0 * Ortho.x + PlaneD * Ortho.z;
            float ProjectedBound1 = BoundX1 * Ortho.x + PlaneD * Ortho.z;

            ProjectedBound1 = Math.Max(ProjectedBound1, Ortho.z);                               // Max with the projected sphere's tangent

            ProjectedBound1 *= 1.1f;

            // We now have a tight rectangle in projected space [-IrisRadius,ProjectedBound0] [IrisRadius,ProjectedBound1]
            //	where we can place random photons that will shoot toward the eye's iris.
            // We still can miss the sphere though...


            // Start shooting
            double MaxThetaRandom = Math.Pow(Math.Sin(IRIS_START_ANGLE), 2.0);
            Vector P            = new Vector();
            Vector N            = new Vector();
            Vector Ray          = new Vector();
            Vector Intersection = new Vector();

            float Eta = 1.00029f / 1.34f;               // n1 / n2

            float fX, fY;
            int   Px, Py;

            for (int PhotonIndex = 0; PhotonIndex < integerTrackbarControlPhotonsCount.Value; PhotonIndex++)
            {
// Wrong as photons are not distributed on the spherical cap
//              double	Phi = 2.0 * Math.PI * SimpleRNG.GetUniform();
//              double	Theta = Math.Asin( Math.Sqrt( MaxThetaRandom * SimpleRNG.GetUniform() ) );
//
//              N.x = (float) (Math.Sin( Theta ) * Math.Cos( Phi ));
//              N.y = (float) (Math.Sin( Theta ) * Math.Sin( Phi ));
//              N.z = (float) Math.Cos( Theta );
//              if ( N.Dot( Light ) < 0.0f )
//                  continue;	// Opposite side of the spherical cap

                // Draw a random position on the light plane and shoot toward the iris
                float x = (float)(ProjectedBound0 + SimpleRNG.GetUniform() * (ProjectedBound1 - ProjectedBound0));
                float y = (float)(IrisRadius * (2.0 * SimpleRNG.GetUniform() - 1.0));

                float SqRadius = x * x + y * y;
                if (SqRadius > 1.0f)
                {
                    continue;                           // Photon will hit outside the sphere (should never happen unless iris is as large as the eye itself)
                }
                float z = (float)Math.Sqrt(1.0 - SqRadius);

                // Recompute normal at intersection
                N.x = x * Ortho.x + z * Light.x;
                N.y = y;
                N.z = x * Ortho.z + z * Light.z;

                if (N.z < PlaneD)
                {
                    continue;                           // We drew a position beneath the iris plane (outside of zone of interest)
                }
                // Refract ray through the surface
                float c1  = -N.Dot(Light);
                float cs2 = 1.0f - Eta * Eta * (1.0f - c1 * c1);
                if (cs2 < 0.0f)
                {
                    continue;                           // Total internal reflection
                }
                cs2   = Eta * c1 - (float)Math.Sqrt(cs2);
                Ray.x = Eta * Light.x + cs2 * N.x;
                Ray.y = Eta * Light.y + cs2 * N.y;
                Ray.z = Eta * Light.z + cs2 * N.z;

                // Compute intersection with plane
                float d = (PlaneD - N.z) / Ray.z;
                if (d < 0.0f)
                {
                    continue;                           // ?
                }
                Intersection.x = N.x + d * Ray.x;
                Intersection.y = N.y + d * Ray.y;
                Intersection.z = N.z + d * Ray.z;

                fX = 0.5f * (1.0f + Intersection.x / IrisRadius);
                fY = 0.5f * (1.0f + Intersection.y / IrisRadius);

                Px = (int)Math.Floor(fX * TEXTURE_SIZE);
                if (Px < 0 || Px >= TEXTURE_SIZE)
                {
                    continue;                           // Out of range??
                }
                Py = (int)Math.Floor(fY * TEXTURE_SIZE);
                if (Py < 0 || Py >= TEXTURE_SIZE)
                {
                    continue;                           // Out of range??
                }
                m_PhotonsAccumulation[Px, Py] += Flux;
            }

            outputPanel1.PhotonsAccumulation = m_PhotonsAccumulation;
        }
Example #17
0
        void    TestTransform1D(double _time)
        {
            // Build the input signal
            Array.Clear(m_signalSource, 0, m_signalSource.Length);
            switch (m_signalType1D)
            {
            case SIGNAL_TYPE.SQUARE:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
                    m_signalSource[i].r = 0.5 * Math.Sin(_time) + ((i + 50.0 * _time) % (SIGNAL_SIZE / 2.0) < (SIGNAL_SIZE / 4.0) ? 0.5 : -0.5);
                }
                break;

            case SIGNAL_TYPE.SINE:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
//						m_signalSource[i].r = Math.Cos( 2.0 * Math.PI * i / SIGNAL_SIZE + _time );
                    m_signalSource[i].r = Math.Cos((4.0 * (1.0 + Math.Sin(_time))) * 2.0 * Math.PI * i / SIGNAL_SIZE);
                }
                break;

            case SIGNAL_TYPE.SAW:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
                    m_signalSource[i].r = 0.5 * Math.Sin(_time) + ((((i + 50.0 * _time) / 128.0) % 1.0) - 0.5);
                }
                break;

            case SIGNAL_TYPE.SINC:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
//						double	a = 4.0 * (1.0 + Math.Sin( _time )) * 2.0 * Math.PI * (1+i) / SIGNAL_SIZE;						// Asymmetrical
                    double a = 4.0 * (1.0 + Math.Sin(_time)) * 2.0 * Math.PI * (i - SIGNAL_SIZE / 2.0) * 2.0 / SIGNAL_SIZE;                             // Symmetrical
                    m_signalSource[i].r = Math.Abs(a) > 0.0 ? Math.Sin(a) / a : 1.0;
                }
                break;

            case SIGNAL_TYPE.RANDOM:
                for (int i = 0; i < SIGNAL_SIZE; i++)
                {
                    m_signalSource[i].r = SimpleRNG.GetUniform();
                }
//						m_signalSource[i].r = SimpleRNG.GetExponential();
//						m_signalSource[i].r = SimpleRNG.GetBeta( 0.5, 1 );
//						m_signalSource[i].r = SimpleRNG.GetGamma( 1.0, 0.1 );
//						m_signalSource[i].r = SimpleRNG.GetCauchy( 0.0, 1.0 );
//						m_signalSource[i].r = SimpleRNG.GetChiSquare( 1.0 );
//						m_signalSource[i].r = SimpleRNG.GetNormal( 0.0, 0.1 );
//						m_signalSource[i].r = SimpleRNG.GetLaplace( 0.0, 0.1 );
//						m_signalSource[i].r = SimpleRNG.GetStudentT( 2.0 );
                break;
            }

            // Transform
            if (m_FFTW_1D != null && checkBoxUseFFTW.Checked)
            {
                m_FFTW_1D.FillInputSpatial((int x, int y, out float r, out float i) => {
                    r = (float)m_signalSource[x].r;
                    i = (float)m_signalSource[x].i;
                });
                m_FFTW_1D.Execute(fftwlib.FFT2D.Normalization.DIMENSIONS_PRODUCT);
                m_FFTW_1D.GetOutput((int x, int y, float r, float i) => {
                    m_spectrum[x].Set(r, i);
                });
            }
            else
            {
//				DFT1D.DFT_Forward( m_signalSource, m_spectrum );
                FFT1D.FFT_Forward(m_signalSource, m_spectrum);
            }

            // Try the GPU version
            m_FFT1D_GPU.FFT_Forward(m_signalSource, m_spectrumGPU);
//			m_FFT1D_GPU.FFT_Forward( m_signalSource, m_spectrum );

            double sumSqDiffR = 0.0;
            double sumSqDiffI = 0.0;

            for (int i = 0; i < m_spectrum.Length; i++)
            {
                Complex diff = m_spectrum[i] - m_spectrumGPU[i];
                sumSqDiffR += diff.r * diff.r;
                sumSqDiffI += diff.i * diff.i;
            }
            labelDiff.Text = "SqDiff = " + sumSqDiffR.ToString("G3") + " , " + sumSqDiffI.ToString("G3");
            if (m_FFTW_1D == null && checkBoxUseFFTW.Checked)
            {
                labelDiff.Text += "\r\nERROR: Can't use FFTW because of an initialization error!";
            }

            if (checkBoxInvertFilter.Checked)
            {
                for (int i = 0; i < m_spectrum.Length; i++)
                {
                    m_spectrum[i] = m_spectrumGPU[i];
                }
            }
// else
//  for ( int i=0; i < m_spectrum.Length; i++ )
//      m_spectrum[i] *= 2.0;


            // Filter
            FilterDelegate filter = null;

            switch (m_filter1D)
            {
            case FILTER_TYPE.CUT_LARGE:
                filter = (int i, int frequency) => { return(Math.Abs(frequency) > 256 ? 0 : 1.0); };                                            // Cut
                break;

            case FILTER_TYPE.CUT_MEDIUM:
                filter = (int i, int frequency) => { return(Math.Abs(frequency) > 128 ? 0 : 1.0); };                                            // Cut
                break;

            case FILTER_TYPE.CUT_SHORT:
                filter = (int i, int frequency) => { return(Math.Abs(frequency) > 64 ? 0 : 1.0); };                                             // Cut
                break;

            case FILTER_TYPE.EXP:
                filter = (int i, int frequency) => { return(Math.Exp(-0.01f * Math.Abs(frequency))); };                                         // Exponential
                break;

            case FILTER_TYPE.GAUSSIAN:
                filter = (int i, int frequency) => { return(Math.Exp(-0.005f * frequency * frequency)); };                                      // Gaussian
                break;

            case FILTER_TYPE.INVERSE:
                filter = (int i, int frequency) => { return(Math.Min(1.0, 4.0 / (1 + Math.Abs(frequency)))); };                                 // Inverse
                break;
//              case FILTER_TYPE.SINUS:
//                  filter = ( int i, int frequency ) => { return Math.Sin( -2.0f * Math.PI * frequency / 32 ); };		// Gni ?
//                  break;
            }
            if (filter != null)
            {
                int size     = m_spectrum.Length;
                int halfSize = size >> 1;
                if (!checkBoxInvertFilter.Checked)
                {
                    for (int i = 0; i < size; i++)
                    {
                        int    frequency   = ((i + halfSize) % size) - halfSize;
                        double filterValue = filter(i, frequency);
                        m_spectrum[i] *= filterValue;
                    }
                }
                else
                {
                    for (int i = 0; i < size; i++)
                    {
                        int    frequency   = ((size - i) % size) - halfSize;
                        double filterValue = filter(i, frequency);
                        m_spectrum[i] *= filterValue;
                    }
                }
            }

            // Inverse Transform
            if (m_FFTW_1D != null && checkBoxUseFFTW.Checked)
            {
                m_FFTW_1D.FillInputFrequency((int x, int y, out float r, out float i) => {
                    r = (float)m_spectrum[x].r;
                    i = (float)m_spectrum[x].i;
                });
                m_FFTW_1D.Execute(fftwlib.FFT2D.Normalization.NONE);
                m_FFTW_1D.GetOutput((int x, int y, float r, float i) => {
                    m_signalReconstructed[x].Set(r, i);
                });
            }
            else
            {
//				DFT1D.DFT_Inverse( m_spectrum, m_signalReconstructed );
                FFT1D.FFT_Inverse(m_spectrum, m_signalReconstructed);
            }
        }
 public static double GetUniform(double max)
 {
     return(max * SimpleRNG.GetUniform());
 }
Example #19
0
    void GenWalls()
    {
        if (useRandomSeed)
        {
            SimpleRNG.SetSeedFromSystemTime();
        }
        else
        {
            SimpleRNG.SetSeed((uint)manualSeed);
        }

        foreach (Cell c in cells)
        {
            unassignedRooms.Add(c);
        }

        Cell startRoom = null;
        int  curRoom   = 1;

        while (unassignedRooms.Count > 0)
        {
            // add room of random size
            int nextRoomSize = (int)(SimpleRNG.GetUniform() * (maxRoomSize - minRoomSize)) + minRoomSize;

            Cell centreCell = unassignedRooms[(int)(SimpleRNG.GetUniform() * (unassignedRooms.Count - 1))];
            if (startRoom == null)
            {
                startRoom = centreCell;
            }

            // work out ideal bounds of new room
            int startX = centreCell.x - Mathf.CeilToInt(nextRoomSize / 2f) + 1;
            int endX   = Mathf.Min(startX + nextRoomSize, cellsPerSide);
            startX = Mathf.Max(0, startX);

            int startY = centreCell.y - Mathf.CeilToInt(nextRoomSize / 2f) + 1;
            int endY   = Mathf.Min(startY + nextRoomSize, cellsPerSide);
            startY = Mathf.Max(0, startY);

            var roomCells  = new List <Cell>();
            var lastInRoom = new List <int>();                  // which rows in the last column had a room on it? If no rows match, column won't be inited and room will stop. Avoids split rooms

            for (int x = startX; x < endX; x++)
            {
                var cellsThisColumn = new List <int>();
                if (lastInRoom.Count == 0)
                {
                    // no cells in room yet, add first block
                    bool started = false;
                    for (int y = startY; y < endY; y++)
                    {
                        if (cells[x, y].room == 0)
                        {
                            cellsThisColumn.Add(y);
                            started = true;
                        }
                        else if (started)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    // add last column's rooms to this column if valid, then spread up and down until hits another room
                    foreach (int roomRow in lastInRoom)
                    {
                        if (!cellsThisColumn.Contains(roomRow) && cells[x, roomRow].room == 0)
                        {
                            cellsThisColumn.Add(roomRow);
                            for (int south = roomRow - 1; south >= startY; south--)
                            {
                                if (cells[x, south].room == 0)
                                {
                                    cellsThisColumn.Add(south);
                                }
                                else
                                {
                                    break;
                                }
                            }
                            for (int north = roomRow + 1; north < endY; north++)
                            {
                                if (cells[x, north].room == 0)
                                {
                                    cellsThisColumn.Add(north);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }

                    // if no valid connection after room has started, stop making room
                    if (cellsThisColumn.Count == 0)
                    {
                        break;
                    }
                }

                // actually make rooms
                foreach (int row in cellsThisColumn)
                {
                    // for each cell within room edges, add walls between neighbouring rooms (if not in another room already)
                    // add each valid room to list, and if can't path to first room after all rooms done, make holes
                    Cell roomCell = cells[x, row];
                    if (AddCellToRoom(roomCell, curRoom))
                    {
                        roomCells.Add(roomCell);
                    }
                }
                lastInRoom = cellsThisColumn;
            }

            Debug.Log("Room made");
            PrintLayout();

            // try to path to start room
            if (roomCells.Count > 0 && CellPath.PathTo(startRoom.centrePosition, roomCells[0].centrePosition) == null)
            {
                // no path, make corridor to first cell
                Cell pathEnd    = null;
                int  distToTarg = int.MaxValue;
                foreach (Cell edgeCell in roomCells)
                {
                    int newDist = Mathf.Abs(edgeCell.x - startRoom.x) + Mathf.Abs(edgeCell.y - startRoom.y);
                    if (newDist < distToTarg)
                    {
                        distToTarg = newDist;
                        pathEnd    = edgeCell;
                    }
                }

                while (pathEnd.room == curRoom)
                {
                    Debug.Log("Opening path from " + pathEnd);
                    int xDist = startRoom.x - pathEnd.x;
                    int yDist = startRoom.y - pathEnd.y;
                    if (xDist >= Mathf.Abs(yDist))
                    {
                        pathEnd = OpenCellInDirection(pathEnd, Direction.East);
                    }
                    else if (xDist <= -Mathf.Abs(yDist))
                    {
                        pathEnd = OpenCellInDirection(pathEnd, Direction.West);
                    }
                    else if (yDist > Mathf.Abs(xDist))
                    {
                        pathEnd = OpenCellInDirection(pathEnd, Direction.North);
                    }
                    else if (yDist < -Mathf.Abs(xDist))
                    {
                        pathEnd = OpenCellInDirection(pathEnd, Direction.South);
                    }
                }

                // check if can path. JUST IN CASE
                if (CellPath.PathTo(startRoom.centrePosition, roomCells[0].centrePosition) == null)
                {
                    Debug.LogWarning("Still no path from room " + curRoom);
                    PrintLayout();
                }
            }

            curRoom++;
        }

        Debug.Log("Layout complete...");
        PrintLayout();

        // Instantiate walls?
        var verticalWalls = new Cell[cellsPerSide, cellsPerSide];

        for (int x = 0; x < cellsPerSide - 1; x++)
        {
            int wallType = Random.Range(0, wallPrefabs.Length);
            for (int y = 0; y < cellsPerSide; y++)
            {
                if (!cells[x, y].canGoEast)
                {
                    CreateWall(cells[x, y], Direction.East, wallType);
                    verticalWalls[x, y] = cells[x, y];

                    if (y > 0 && verticalWalls[x, y - 1] == null)
                    {
                        CreateWallCap(cells[x, y], true);
                    }
                }
                else
                {
                    wallType = Random.Range(0, wallPrefabs.Length);
                    if (y > 0 && verticalWalls[x, y - 1] != null)
                    {
                        CreateWallCap(cells[x, y], true);
                    }
                }
            }
        }

        var horizontalWalls = new Cell[cellsPerSide, cellsPerSide];

        for (int y = 0; y < cellsPerSide - 1; y++)
        {
            int wallType = Random.Range(0, wallPrefabs.Length);
            for (int x = 0; x < cellsPerSide; x++)
            {
                if (!cells[x, y].canGoNorth)
                {
                    CreateWall(cells[x, y], Direction.North, wallType);
                    horizontalWalls[x, y] = cells[x, y];

                    if (x > 0 && horizontalWalls[x - 1, y] == null)
                    {
                        CreateWallCap(cells[x, y], false);
                    }
                }
                else
                {
                    wallType = Random.Range(0, wallPrefabs.Length);
                    if (x > 0 && horizontalWalls[x - 1, y] != null)
                    {
                        CreateWallCap(cells[x, y], false);
                    }
                }
            }
        }
    }
Example #20
0
    /// <summary>
    /// Adds the cell to given room.
    /// </summary>
    /// <returns>
    /// Whether the cell was added
    /// </returns>
    /// <param name='newCell'>
    /// Cell to add
    /// </param>
    /// <param name='inRoom'>
    /// Room number to add to
    /// </param>
    bool AddCellToRoom(Cell newCell, int inRoom)
    {
        // Add walls between this and cells that have been set to other rooms
        if (newCell.room == 0)
        {
            newCell.room = inRoom;
            if (newCell.x > 0 && newCell.CellInDirection(Direction.West).room != 0 && newCell.CellInDirection(Direction.West).room != inRoom && SimpleRNG.GetUniform() < wallDensity)
            {
                newCell.canGoWest = newCell.CellInDirection(Direction.West).canGoEast = false;
            }
            if (newCell.x < cellsPerSide - 1 && newCell.CellInDirection(Direction.East).room != 0 && newCell.CellInDirection(Direction.East).room != inRoom && SimpleRNG.GetUniform() < wallDensity)
            {
                newCell.canGoEast = newCell.CellInDirection(Direction.East).canGoWest = false;
            }
            if (newCell.y > 0 && newCell.CellInDirection(Direction.South).room != 0 && newCell.CellInDirection(Direction.South).room != inRoom && SimpleRNG.GetUniform() < wallDensity)
            {
                newCell.canGoSouth = newCell.CellInDirection(Direction.South).canGoNorth = false;
            }
            if (newCell.y < cellsPerSide - 1 && newCell.CellInDirection(Direction.North).room != 0 && newCell.CellInDirection(Direction.North).room != inRoom && SimpleRNG.GetUniform() < wallDensity)
            {
                newCell.canGoNorth = newCell.CellInDirection(Direction.North).canGoSouth = false;
            }

            unassignedRooms.Remove(newCell);
            return(true);
        }

        return(false);
    }
        /// <summary>
        /// Generates blue noise distribution by randomly swapping pixels in the texture to reach lowest possible score and minimize a specific energy function
        /// </summary>
        /// <param name="_randomSeed"></param>
        /// <param name="_maxIterations">The maximum amount of iterations before exiting with the last best solution</param>
        /// <param name="_standardDeviationImage">Standard deviation for image space. If not sure, use 2.1</param>
        /// <param name="_standardDeviationValue">Standard deviation for value space. If not sure, use 1.0</param>
        /// <param name="_neighborsOnlyMutations">True to only authorize mutations of neighbor pixels, false to randomly mutate any pixel</param>
        /// <param name="_notifyProgressEveryNIterations">Will read back the GPU texture to the CPU and notify of progress every N iterations</param>
        /// <param name="_progress"></param>
        public void             Generate(uint _randomSeed, uint _maxIterations, float _standardDeviationImage, float _standardDeviationValue, bool _neighborsOnlyMutations, uint _notifyProgressEveryNIterations, ProgressDelegate _progress)
        {
            m_CB_Main.m._texturePOT  = (uint)m_texturePOT;
            m_CB_Main.m._textureSize = m_textureSize;
            m_CB_Main.m._textureMask = m_textureSizeMask;

            m_CB_Main.m._kernelFactorSpatial = -1.0f / (_standardDeviationImage * _standardDeviationImage);
            m_CB_Main.m._kernelFactorValue   = -1.0f / (_standardDeviationValue * _standardDeviationValue);

            m_CB_Main.UpdateData();

            //////////////////////////////////////////////////////////////////////////
            // Generate initial white noise
            {
                SimpleRNG.SetSeed(_randomSeed, 362436069U);
                switch (m_vectorDimension)
                {
                case 1: {
                    // Build ordered initial values
                    float[,]        initialValues = new float[m_textureSize, m_textureSize];
                    for (uint Y = 0; Y < m_textureSize; Y++)
                    {
                        for (uint X = 0; X < m_textureSize; X++)
                        {
                            initialValues[X, Y] = (float)(m_textureSize * Y + X) / m_textureTotalSize;
                        }
                    }

                    // Displace them randomly
                    for (uint i = 0; i < m_textureTotalSize; i++)
                    {
                        uint  startX = GetUniformInt(m_textureSize);
                        uint  startY = GetUniformInt(m_textureSize);
                        uint  endX   = GetUniformInt(m_textureSize);
                        uint  endY   = GetUniformInt(m_textureSize);
                        float temp   = initialValues[startX, startY];
                        initialValues[startX, startY] = initialValues[endX, endY];
                        initialValues[endX, endY]     = temp;
                    }

                    m_texNoiseCPU.WritePixels(0, 0, (uint _X, uint _Y, System.IO.BinaryWriter _W) => {
                            _W.Write(initialValues[_X, _Y]);
                        });
                    break;
                }

                case 2: {
                    // Build ordered initial values
                    float2[,]       initialValues = new float2[m_textureSize, m_textureSize];
                    for (uint Y = 0; Y < m_textureSize; Y++)
                    {
                        for (uint X = 0; X < m_textureSize; X++)
                        {
                            initialValues[X, Y].Set((float)(m_textureSize * Y + X) / m_textureTotalSize, (float)(m_textureSize * Y + X) / m_textureTotalSize);
                        }
                    }

                    // Displace them randomly
                    for (uint i = 0; i < m_textureTotalSize; i++)
                    {
                        uint  startX = GetUniformInt(m_textureSize);
                        uint  startY = GetUniformInt(m_textureSize);
                        uint  endX   = GetUniformInt(m_textureSize);
                        uint  endY   = GetUniformInt(m_textureSize);
                        float temp   = initialValues[startX, startY].x;
                        initialValues[startX, startY].x = initialValues[endX, endY].x;
                        initialValues[endX, endY].x     = temp;

                        startX = GetUniformInt(m_textureSize);
                        startY = GetUniformInt(m_textureSize);
                        endX   = GetUniformInt(m_textureSize);
                        endY   = GetUniformInt(m_textureSize);
                        temp   = initialValues[startX, startY].y;
                        initialValues[startX, startY].y = initialValues[endX, endY].y;
                        initialValues[endX, endY].y     = temp;
                    }

                    m_texNoiseCPU.WritePixels(0, 0, (uint _X, uint _Y, System.IO.BinaryWriter _W) => {
                            _W.Write(initialValues[_X, _Y].x);
                            _W.Write(initialValues[_X, _Y].y);
                        });
                    break;
                }
                }
                m_texNoise0.CopyFrom(m_texNoiseCPU);
            }

            //////////////////////////////////////////////////////////////////////////
            // Perform iterations
            float bestScore      = ComputeScore(m_texNoise0);
            float score          = bestScore;
            uint  iterationIndex = 0;
            uint  mutationsRate  = MAX_MUTATIONS_RATE;
            int   iterationsCountWithoutImprovement = 0;

#if !CAILLOU
            float maxIterationsCountWithoutImprovementBeforeDecreasingMutationsCount = 0.1f * m_textureTotalSize;                       // Arbitrary: 10% of the texture size
#else
            float maxIterationsCountWithoutImprovementBeforeDecreasingMutationsCount = 0.01f * m_textureTotalSize;                      // Arbitrary: 1% of the texture size
#endif
//			float		maxIterationsCountWithoutImprovementBeforeDecreasingMutationsCount = 0.002f * m_textureTotalSize;	// Arbitrary: 0.2% of the texture size
            float averageIterationsCountWithoutImprovement = 0.0f;
            float alpha = 0.001f;

            uint[] neighborOffsetX = new uint[8] {
                0, 1, 2, 2, 2, 1, 0, 0
            };
            uint[] neighborOffsetY = new uint[8] {
                0, 0, 0, 1, 2, 2, 2, 1
            };

            List <float> statistics = new List <float>();
//ReadBackScoreTexture( m_texNoiseScore2, textureCPU );
            while (iterationIndex < _maxIterations)
            {
                //////////////////////////////////////////////////////////////////////////
                // Copy
                if (m_CS_Copy.Use())
                {
                    m_texNoise0.SetCS(0);
                    m_texNoise1.SetCSUAV(0);

                    uint groupsCount = m_textureSize >> 4;
                    m_CS_Copy.Dispatch(groupsCount, groupsCount, 1);
                }

                //////////////////////////////////////////////////////////////////////////
                // Mutate current solution by swapping up to N pixels randomly
                if (m_CS_Mutate.Use())
                {
                    // Fill up mutations buffer
                    if (_neighborsOnlyMutations)
                    {
                        // Swap neighbor pixels only
                        for (int mutationIndex = 0; mutationIndex < mutationsRate; mutationIndex++)
                        {
                            uint sourceIndex = GetUniformInt(m_textureTotalSize);
                            uint X, Y;
                            ComputeXYFromSingleIndex(sourceIndex, out X, out Y);

                            // Randomly pick one of the 8 neighbors
                            uint neighborIndex = SimpleRNG.GetUint() & 0x7;
                            uint Xn            = (X + m_textureSizeMask + neighborOffsetX[neighborIndex]) & m_textureSizeMask;
                            uint Yn            = (Y + m_textureSizeMask + neighborOffsetY[neighborIndex]) & m_textureSizeMask;

                            m_SB_Mutations.m[mutationIndex]._pixelSourceX = X;
                            m_SB_Mutations.m[mutationIndex]._pixelSourceY = Y;
                            m_SB_Mutations.m[mutationIndex]._pixelTargetX = Xn;
                            m_SB_Mutations.m[mutationIndex]._pixelTargetY = Yn;

                            if (m_vectorDimension > 1)
                            {
                                m_SB_Mutations.m[mutationIndex]._pixelTargetY |= SimpleRNG.GetUniform() > 0.5 ? 0x80000000U : 0x40000000U;
                            }
                        }
                    }
                    else
                    {
                        // Swap pixels randomly
                        for (int mutationIndex = 0; mutationIndex < mutationsRate; mutationIndex++)
                        {
                            uint sourceIndex = GetUniformInt(m_textureTotalSize);
                            uint targetIndex = GetUniformInt(m_textureTotalSize);
                            ComputeXYFromSingleIndex(sourceIndex, out m_SB_Mutations.m[mutationIndex]._pixelSourceX, out m_SB_Mutations.m[mutationIndex]._pixelSourceY);
                            ComputeXYFromSingleIndex(targetIndex, out m_SB_Mutations.m[mutationIndex]._pixelTargetX, out m_SB_Mutations.m[mutationIndex]._pixelTargetY);

                            if (m_vectorDimension > 1)
                            {
                                m_SB_Mutations.m[mutationIndex]._pixelTargetY |= SimpleRNG.GetUniform() > 0.5 ? 0x80000000U : 0x40000000U;
                            }
                        }
                    }

                    m_SB_Mutations.Write(mutationsRate);
                    m_SB_Mutations.SetInput(1);

                    m_CS_Mutate.Dispatch(mutationsRate, 1, 1);

                    m_texNoise0.RemoveFromLastAssignedSlots();
                    m_texNoise1.RemoveFromLastAssignedSlotUAV();
                }

                //////////////////////////////////////////////////////////////////////////
                // Compute new score
                float previousScore = score;
                score = ComputeScore(m_texNoise1);
                if (score < bestScore)
                {
                    // New best score! Swap textures so we accept the new state...
                    bestScore = score;
                    Texture2D temp = m_texNoise0;
                    m_texNoise0 = m_texNoise1;
                    m_texNoise1 = temp;

                    iterationsCountWithoutImprovement = 0;
                }
                else
                {
                    iterationsCountWithoutImprovement++;
                }

                averageIterationsCountWithoutImprovement *= 1.0f - alpha;
                averageIterationsCountWithoutImprovement += alpha * iterationsCountWithoutImprovement;

                if (averageIterationsCountWithoutImprovement > maxIterationsCountWithoutImprovementBeforeDecreasingMutationsCount)
                {
                    averageIterationsCountWithoutImprovement = 0.0f; // Start over...
                    mutationsRate >>= 1;                             // Halve mutations count
                    if (mutationsRate == 0)
                    {
                        break;                          // Clearly we've reached a steady state here...
                    }
                }

//statistics.Add( averageIterationsCountWithoutImprovement );


                //////////////////////////////////////////////////////////////////////////
                // Notify
                iterationIndex++;
                if (_progress == null || (iterationIndex % _notifyProgressEveryNIterations) != 1)
                {
                    continue;
                }

//				_progress( iterationIndex, mutationsCount, bestScore, ReadBackScoreTexture( m_texNoiseScore ), statistics );	// Notify!
                switch (m_vectorDimension)
                {
                case 1: _progress(iterationIndex, mutationsRate, bestScore, ReadBackTexture1D(m_texNoise0), statistics); break;                                 // Notify!

                case 2: _progress(iterationIndex, mutationsRate, bestScore, ReadBackTexture2D(m_texNoise0), statistics); break;                                 // Notify!
                }
            }

            // One final call with our best final result
            switch (m_vectorDimension)
            {
            case 1: ReadBackTexture1D(m_texNoise0); break;

            case 2: ReadBackTexture2D(m_texNoise0); break;
            }

            if (_progress != null)
            {
//				_progress( iterationIndex, mutationsCount, bestScore, ReadBackScoreTexture( m_texNoiseScore ), statistics );	// Notify!
                switch (m_vectorDimension)
                {
                case 1: _progress(iterationIndex, mutationsRate, bestScore, ReadBackTexture1D(m_texNoise0), statistics); break;                                 // Notify!

                case 2: _progress(iterationIndex, mutationsRate, bestScore, ReadBackTexture2D(m_texNoise0), statistics); break;                                 // Notify!
                }
            }
        }
Example #22
0
//      public float3x3			MakeRot( float3 _from, float3 _to ) {
//          float3	v = _from.Cross( _to );
//          float	c = _from.Dot( _to );
//          float	k = 1.0f / (1.0f + c);
//
//          float3x3	R = new float3x3();
//          R.m[0, 0] = v.x*v.x*k + c;		R.m[0, 1] = v.y*v.x*k - v.z;	R.m[0, 2] = v.z*v.x*k + v.y;
//          R.m[1, 0] = v.x*v.y*k + v.z;	R.m[1, 1] = v.y*v.y*k + c;		R.m[1, 2] = v.z*v.y*k - v.x;
//          R.m[2, 0] = v.x*v.z*k - v.y;	R.m[2, 1] = v.y*v.z*k + v.x;	R.m[2, 2] = v.z*v.z*k + c;
//
//          return R;
//      }

        public FittingForm()
        {
//          Random		RNG = new Random();
//          float3		From = new float3( 2.0f * (float) RNG.NextDouble() - 1.0f, 2.0f * (float) RNG.NextDouble() - 1.0f, 2.0f * (float) RNG.NextDouble() - 1.0f ).Normalized;
//          float3		To = new float3( 2.0f * (float) RNG.NextDouble() - 1.0f, 2.0f * (float) RNG.NextDouble() - 1.0f, 2.0f * (float) RNG.NextDouble() - 1.0f ).Normalized;
//          float3x3	Pipo = MakeRot( From, To );
//          float3		Test = Pipo * From;

//TestChromaRanges();
//TestSHRGBEEncoding();
//TestSquareFilling();

            InitializeComponent();

            // Create the random points
            List <float3> RandomDirections = new List <float3>();
            List <float>  RandomThetas     = new List <float>();

            for (int LobeIndex = 0; LobeIndex < m_RandomLobes.Length; LobeIndex++)
            {
                float MainPhi       = (float)(m_RandomLobes[LobeIndex].Phi * Math.PI / 180.0f);
                float MainTheta     = (float)(m_RandomLobes[LobeIndex].Theta * Math.PI / 180.0f);
                float Concentration = m_RandomLobes[LobeIndex].Concentration;
                int   PointsCount   = m_RandomLobes[LobeIndex].RandomPointsCount;

                // Build the main direction for the target lobe
                float3 MainDirection = new float3(
                    (float)(Math.Sin(MainTheta) * Math.Sin(MainPhi)),
                    (float)(Math.Cos(MainTheta)),
                    (float)(Math.Sin(MainTheta) * Math.Cos(MainPhi))
                    );

                // Build the transform to bring Y-aligned points to the main direction
                float3x3 Rot = new float3x3();
                Rot.BuildRot(float3.UnitY, MainDirection);

                BuildDistributionMapping(Concentration, 0.0);

                // Draw random points in the Y-aligned hemisphere and transform them into the main direction
                for (int PointIndex = 0; PointIndex < PointsCount; PointIndex++)
                {
                    double Theta    = GetTheta();
                    float  CosTheta = (float)Math.Cos(Theta);
//					float	SinTheta = (float) Math.Sqrt( 1.0f - CosTheta*CosTheta );
                    float SinTheta = (float)Math.Sin(Theta);
                    float Phi      = (float)(SimpleRNG.GetUniform() * Math.PI);

                    float3 RandomDirection = new float3(
                        (float)(SinTheta * Math.Sin(Phi)),
                        CosTheta,
                        (float)(SinTheta * Math.Cos(Phi))
                        );

                    float3 FinalDirection = RandomDirection * Rot;

                    RandomDirections.Add(FinalDirection);

                    RandomThetas.Add(CosTheta);
                }
            }

            m_RandomDirections = RandomDirections.ToArray();
            m_RandomThetas     = RandomThetas.ToArray();

            panelOutput.UpdateBitmap();
            panelOutputNormalDistribution.UpdateBitmap();

            // Do it!
            FitLobe[] Result = new FitLobe[FITTING_LOBES_COUNT];
            for (int h = 0; h < Result.Length; h++)
            {
                Result[h] = new FitLobe();
            }
            PerformExpectationMaximization(m_RandomDirections, Result);
        }
Example #23
0
        private void buttonShootPhotons_Click(object sender, EventArgs e)
        {
            //////////////////////////////////////////////////////////////////////////
            // 1] Build initial photon positions and directions
            float3 SunDirection = new float3(0, 1, 0).Normalized;

            uint InitialDirection = PackPhotonDirection(-SunDirection);
            uint InitialColor     = EncodeRGBE(new float3(1.0f, 1.0f, 1.0f));

            int   PhotonsPerSize     = (int)Math.Floor(Math.Sqrt(PHOTONS_COUNT));
            float PhotonCoverageSize = CLOUDSCAPE_SIZE / PhotonsPerSize;

            for (int PhotonIndex = 0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++)
            {
                int Z = PhotonIndex / PhotonsPerSize;
                int X = PhotonIndex - Z * PhotonsPerSize;

                float x = ((X + (float)SimpleRNG.GetUniform()) / PhotonsPerSize - 0.5f) * CLOUDSCAPE_SIZE;
                float z = ((Z + (float)SimpleRNG.GetUniform()) / PhotonsPerSize - 0.5f) * CLOUDSCAPE_SIZE;

                m_SB_Photons.m[PhotonIndex].Position.Set(x, z);
                m_SB_Photons.m[PhotonIndex].Direction = InitialDirection;
                m_SB_Photons.m[PhotonIndex].RGBE      = InitialColor;

#if DEBUG_INFOS
                m_SB_Photons.m[PhotonIndex].Infos.Set(0, 0, 0, 0);                      // Will store scattering events counter, marched length, steps count, etc.
#endif
            }
            m_SB_Photons.Write();


            //////////////////////////////////////////////////////////////////////////
            // 2] Initialize layers & textures

            // 2.1) Fill source bucket with all photons
            for (int PhotonIndex = 0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++)
            {
                m_SB_PhotonLayerIndices.m[PhotonIndex] = 0U;                    // Starting from top layer, direction is down
            }
            m_SB_PhotonLayerIndices.Write();

            // 2.2) Clear photon splatting texture
            m_Device.Clear(m_Tex_PhotonLayers_Flux, new float4(0, 0, 0, 0));
            m_Device.Clear(m_Tex_PhotonLayers_Direction, new float4(0, 0, 0, 0));


            //////////////////////////////////////////////////////////////////////////
            // 3] Prepare buffers & states

            m_CloudScapeSize.Set(CLOUDSCAPE_SIZE, floatTrackbarControlCloudscapeThickness.Value, CLOUDSCAPE_SIZE);

            // 3.1) Prepare density field
            m_Tex_DensityField.SetCS(2);

            // 3.2) Constant buffer for photon shooting
            m_CB_PhotonShooterInput.m.LayersCount     = LAYERS_COUNT;
            m_CB_PhotonShooterInput.m.MaxScattering   = 30;
            m_CB_PhotonShooterInput.m.LayerThickness  = m_CloudScapeSize.y / LAYERS_COUNT;
            m_CB_PhotonShooterInput.m.SigmaScattering = floatTrackbarControlSigmaScattering.Value;              // 0.04523893421169302263386206471922f;	// re=6µm Gamma=2 N0=4e8   Sigma_t = N0 * PI * re²
            m_CB_PhotonShooterInput.m.CloudScapeSize  = m_CloudScapeSize;

            // 3.3) Prepare photon splatting buffer & states
            m_CB_SplatPhoton.m.CloudScapeSize = m_CloudScapeSize;
            m_CB_SplatPhoton.m.SplatSize      = 1.0f * (2.0f / m_Tex_PhotonLayers_Flux.Width);
            m_CB_SplatPhoton.m.SplatIntensity = 1.0f;                                                                // 1000.0f / PHOTONS_COUNT;

            m_Device.SetRenderStates(RASTERIZER_STATE.CULL_NONE, DEPTHSTENCIL_STATE.DISABLED, BLEND_STATE.ADDITIVE); // Splatting is additive
            m_Tex_PhotonLayers_Flux.RemoveFromLastAssignedSlots();
            m_Tex_PhotonLayers_Direction.RemoveFromLastAssignedSlots();


            //////////////////////////////////////////////////////////////////////////
            // 4] Splat initial photons to the top layer
            m_PS_PhotonSplatter.Use();

            m_SB_Photons.SetInput(0);                           // RO version for splatting
            m_SB_PhotonLayerIndices.SetInput(1);                // RO version for splatting

            m_CB_SplatPhoton.m.LayerIndex = 0U;
            m_CB_SplatPhoton.UpdateData();

            m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                      new View3D[] {
                m_Tex_PhotonLayers_Flux.GetView(0, 0, 0, 1),
                m_Tex_PhotonLayers_Direction.GetView(0, 0, 0, 1)
            }, null);
            m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);


            //////////////////////////////////////////////////////////////////////////
            // 5] Render loop
            int BatchesCount = PHOTONS_COUNT / PHOTON_BATCH_SIZE;

            m_SB_ProcessedPhotonsCounter.SetOutput(2);

            for (int BounceIndex = 0; BounceIndex < BOUNCES_COUNT; BounceIndex++)
            {
                // 5.1] Process every layers from top to bottom
                m_SB_ProcessedPhotonsCounter.m[0] = 0;
                m_SB_ProcessedPhotonsCounter.Write();                   // Reset processed photons counter

                for (int LayerIndex = 0; LayerIndex < LAYERS_COUNT; LayerIndex++)
                {
                    // 5.1.1) Shoot a bunch of photons from layer "LayerIndex" to layer "LayerIndex+1"
                    m_CS_PhotonShooter.Use();

                    m_CB_PhotonShooterInput.m.LayerIndex = (uint)LayerIndex;

                    m_SB_Photons.RemoveFromLastAssignedSlots();
                    m_SB_PhotonLayerIndices.RemoveFromLastAssignedSlots();

                    m_SB_Photons.SetOutput(0);
                    m_SB_PhotonLayerIndices.SetOutput(1);

                    m_SB_Random.SetInput(0);
                    m_SB_PhaseQuantile.SetInput(1);

                    for (int BatchIndex = 0; BatchIndex < BatchesCount; BatchIndex++)
                    {
                        m_CB_PhotonShooterInput.m.BatchIndex = (uint)BatchIndex;
                        m_CB_PhotonShooterInput.UpdateData();

                        m_CS_PhotonShooter.Dispatch(1, 1, 1);

                        m_Device.Present(true);

                        // Notify of progress
                        progressBar1.Value = progressBar1.Maximum * (1 + BatchIndex + BatchesCount * (LayerIndex + LAYERS_COUNT * BounceIndex)) / (BOUNCES_COUNT * LAYERS_COUNT * BatchesCount);
                        Application.DoEvents();
                    }

#if DEBUG_INFOS
//DEBUG Read back photons buffer
                    m_SB_Photons.Read();
// m_SB_PhotonLayerIndices.Read();
// Verify photons have the same energy and were indeed transported to the next layer unaffected (this test is only valid if the density field is filled with 0s)
// for ( int PhotonIndex=0; PhotonIndex < PHOTONS_COUNT; PhotonIndex++ )
// {
//  if ( m_SB_Photons.m[PhotonIndex].RGBE != 0x80FFFFFF )
//      throw new Exception( "Intensity changed!" );
//  if ( m_SB_PhotonLayerIndices.m[PhotonIndex] != LayerIndex+1 )
//      throw new Exception( "Unexpected layer index!" );
// }
//DEBUG
#endif

                    // 5.1.2) Splat the photons that got through to the 2D texture array
                    m_PS_PhotonSplatter.Use();

                    m_SB_Photons.SetInput(0);                                   // RO version for splatting
                    m_SB_PhotonLayerIndices.SetInput(1);                        // RO version for splatting

                    m_CB_SplatPhoton.m.LayerIndex = (uint)(LayerIndex + 1);
                    m_CB_SplatPhoton.UpdateData();

                    m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                              new View3D[] {
                        m_Tex_PhotonLayers_Flux.GetView(0, 0, LayerIndex + 1, 1),
                        m_Tex_PhotonLayers_Direction.GetView(0, 0, LayerIndex + 1, 1)
                    }, null);
                    m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);
                }

                m_SB_ProcessedPhotonsCounter.Read();
                if (m_SB_ProcessedPhotonsCounter.m[0] < LOW_PHOTONS_COUNT_RATIO * PHOTONS_COUNT)
                {
                    break;                      // We didn't shoot a significant number of photons to go on...
                }
                // ================================================================================
                // 5.2] Process every layers from bottom to top
                BounceIndex++;
                if (BounceIndex >= BOUNCES_COUNT)
                {
                    break;
                }

                m_SB_ProcessedPhotonsCounter.m[0] = 0;
                m_SB_ProcessedPhotonsCounter.Write();                   // Reset processed photons counter

                for (int LayerIndex = LAYERS_COUNT; LayerIndex > 0; LayerIndex--)
                {
                    // 5.2.1) Shoot a bunch of photons from layer "LayerIndex" to layer "LayerIndex-1"
                    m_CS_PhotonShooter.Use();

                    m_CB_PhotonShooterInput.m.LayerIndex = (uint)LayerIndex | 0x80000000U;                      // <= MSB indicates photons are going up

                    m_SB_Photons.RemoveFromLastAssignedSlots();
                    m_SB_PhotonLayerIndices.RemoveFromLastAssignedSlots();

                    m_SB_Photons.SetOutput(0);
                    m_SB_PhotonLayerIndices.SetOutput(1);

                    m_SB_Random.SetInput(0);
                    m_SB_PhaseQuantile.SetInput(1);

                    for (int BatchIndex = 0; BatchIndex < BatchesCount; BatchIndex++)
                    {
                        m_CB_PhotonShooterInput.m.BatchIndex = (uint)BatchIndex;
                        m_CB_PhotonShooterInput.UpdateData();

                        m_CS_PhotonShooter.Dispatch(1, 1, 1);

                        m_Device.Present(true);

                        // Notify of progress
                        progressBar1.Value = progressBar1.Maximum * (1 + BatchIndex + BatchesCount * (LayerIndex + LAYERS_COUNT * BounceIndex)) / (BOUNCES_COUNT * LAYERS_COUNT * BatchesCount);
                        Application.DoEvents();
                    }

                    // 5.2.2) Splat the photons that got through to the 2D texture array
                    m_PS_PhotonSplatter.Use();

                    m_SB_Photons.SetInput(0);                                             // RO version for splatting
                    m_SB_PhotonLayerIndices.SetInput(1);                                  // RO version for splatting

                    m_CB_SplatPhoton.m.LayerIndex = (uint)(LayerIndex - 1) | 0x80000000U; // <= MSB indicates photons are going up
                    m_CB_SplatPhoton.UpdateData();

                    m_Device.SetRenderTargets(m_Tex_PhotonLayers_Flux.Width, m_Tex_PhotonLayers_Flux.Height,
                                              new View3D[] {
                        m_Tex_PhotonLayers_Flux.GetView(0, 0, LayerIndex - 1, 0),
                        m_Tex_PhotonLayers_Direction.GetView(0, 0, LayerIndex - 1, 0)
                    }, null);
                    m_Prim_Point.RenderInstanced(m_PS_PhotonSplatter, PHOTONS_COUNT);
                }

                m_SB_ProcessedPhotonsCounter.Read();
                if (m_SB_ProcessedPhotonsCounter.m[0] < LOW_PHOTONS_COUNT_RATIO * PHOTONS_COUNT)
                {
                    break;                      // We didn't shoot a significant number of photons to go on...
                }
            }

            m_Tex_PhotonLayers_Flux.RemoveFromLastAssignedSlots();
            m_Tex_PhotonLayers_Direction.RemoveFromLastAssignedSlots();

            Render();
        }
Example #24
0
        void    CreateNoiseSpectrum(Complex[,] _spectrum)
        {
            uint size     = m_handMadeBlueNoise.Width;
            uint halfSize = size >> 1;

            double noiseScale        = floatTrackbarControlScale.Value;
            double noiseBias         = floatTrackbarControlOffset.Value;
            double radialOffset      = floatTrackbarControlRadialOffset.Value;
            double radialScale       = floatTrackbarControlRadialScale.Value;
            double distributionPower = floatTrackbarControlDistributionPower.Value;
            double sigma             = floatTrackbarControlSigma.Value;

            Complex Cnoise = new Complex();

            for (uint Y = 0; Y < m_handMadeBlueNoise.Height; Y++)
            {
                uint Yoff = (Y + halfSize) & (size - 1);
                int  Yrel = (int)Y - (int)halfSize;
                for (uint X = 0; X < m_handMadeBlueNoise.Width; X++)
                {
                    uint Xoff = (X + halfSize) & (size - 1);
                    int  Xrel = (int)X - (int)halfSize;

                    // Fetch "center noise" from blue noise
//					Cnoise = output[(halfSize>>1) + (X & (halfSize-1)), (halfSize>>1) + (Y & (halfSize-1))];
//					Cnoise /= maxAverage;	// Center noise is already factored by the maximum average so we "renormalize it"

                    // Apply simple uniform noise
                    Cnoise.r = noiseScale * (Math.Pow(SimpleRNG.GetUniform(), distributionPower) - noiseBias);
                    Cnoise.i = noiseScale * (Math.Pow(SimpleRNG.GetUniform(), distributionPower) - noiseBias);

//                  Cnoise.r = noiseScale * (SimpleRNG.GetNormal() - noiseBias);
//                  Cnoise.i = noiseScale * (SimpleRNG.GetNormal() - noiseBias);

//                  Cnoise.r = noiseScale * (SimpleRNG.GetLaplace( 0, sigma ) - noiseBias);
//                  Cnoise.i = noiseScale * (SimpleRNG.GetLaplace( 0, sigma ) - noiseBias);

//                  Cnoise.r = 2.0 * SimpleRNG.GetNormal( 0, 1 ) - 1.0;
//                  Cnoise.i = 2.0 * SimpleRNG.GetNormal( 0, 1 ) - 1.0;

// Cnoise.r = 1.0;
// Cnoise.i = 0.0;

                    // Apply weighting by radial profile
                    int sqRadius = Xrel * Xrel + Yrel * Yrel;

                    // Use averaged radial profile extracted from the noise texture
//					int		radius = (int) Math.Max( 1, Math.Min( halfSize-1, Math.Sqrt( sqRadius ) ) );
//					double	profileFactor = m_radialSliceAverage_Smoothed[radius].r;
//profileFactor *= 2.0;

                    // Use the Mathematica hand-fitted curve
                    double profileFactor = RadialProfile(radialOffset + radialScale * Math.Sqrt(sqRadius) / halfSize);
//profileFactor *= 0.75 / 1;
//profileFactor *= 3.0;

//profileFactor *= Math.Sqrt( 2.0 );
//profileFactor *= 1.1;

                    Cnoise *= profileFactor;

//Cnoise = output[Xoff,Yoff];
//Cnoise *= Math.Exp( 0.01 * Math.Max( 0.0, radius - 128 ) );

                    _spectrum[Xoff, Yoff] = Cnoise;
                }
            }
            _spectrum[0, 0].Set(floatTrackbarControlDC.Value, 0.0);                     // Central value for constant term


                        #if COMPUTE_RADIAL_SLICE
            const int BUCKETS_COUNT = 1000;
            uint[]    noiseDistributionHistogram = new uint[BUCKETS_COUNT];
            for (uint i = 0; i < m_handMadeBlueNoise.Width * m_handMadeBlueNoise.Height; i++)
            {
                double noiseValue  = noiseScale * (Math.Pow(SimpleRNG.GetUniform(), distributionPower) - noiseBias);
                double noiseValue2 = noiseScale * (Math.Pow(SimpleRNG.GetUniform(), distributionPower) - noiseBias);
                noiseValue = Math.Abs(noiseValue + noiseValue2);

                noiseValue = Math.Pow(SimpleRNG.GetUniform(), 0.5);
                noiseValue = SimpleRNG.GetUniform() < 0.5 ? 0.5 * Math.Sqrt(1.0 - noiseValue) : 1.0 - 0.5 * Math.Sqrt(1.0 - noiseValue);

                int bucketIndex = Math.Min(BUCKETS_COUNT - 1, (int)Math.Floor(noiseValue * BUCKETS_COUNT));
                noiseDistributionHistogram[bucketIndex]++;
            }

//              for ( uint Y=0; Y < m_handMadeBlueNoise.Height; Y++ ) {
//                  uint	Yoff = (Y + halfSize) & (size-1);
//                  int		Yrel = (int) Y - (int) halfSize;
//                  for ( uint X=0; X < m_handMadeBlueNoise.Width; X++ ) {
//                      uint	Xoff = (X + halfSize) & (size-1);
//                      int		Xrel = (int) X - (int) halfSize;
//                      int		sqRadius = Xrel*Xrel + Yrel*Yrel;
//                      double	radius = Math.Sqrt( sqRadius ) / halfSize;
//                      if ( radius < 0.01f )
//                          continue;	// Avoid central values because of too much imprecision
//
//                      double	random = Math.Abs( _spectrum[Xoff,Yoff].r );
//                      double	profileAmplitude = RadialProfile( radius );
//                      double	normalizedRandom = random / profileAmplitude;
//
//                      int		bucketIndex = Math.Min( BUCKETS_COUNT-1, (int) Math.Floor( normalizedRandom * BUCKETS_COUNT ) );
//                      noiseDistributionHistogram[bucketIndex]++;
//                  }
//              }

            m_spectrumNoiseDistribution_Custom.Clear(float4.One);
            float2 rangeX = new float2(0, 1);
            float2 rangeY = new float2(0, 4.0f / BUCKETS_COUNT);
            m_spectrumNoiseDistribution_Custom.PlotGraph(float4.UnitW, rangeX, rangeY, ( float _x ) => {
                int bucketIndex = Math.Min(BUCKETS_COUNT - 1, (int)Math.Floor(_x * BUCKETS_COUNT));
                return((float)noiseDistributionHistogram[bucketIndex] / (m_blueNoise.Width * m_blueNoise.Height));
            });
                        #endif
        }
Example #25
0
        void    NumericalIntegration()
        {
            // Generate a bunch of rays with equal probability on the hemisphere
            const int    THETA_SAMPLES = 100;
            const int    SAMPLES_COUNT = 4 * THETA_SAMPLES * THETA_SAMPLES;
            const double dPhi          = 2.0 * Math.PI / (4 * THETA_SAMPLES);

            float3[] directions = new float3[SAMPLES_COUNT];
            for (int Y = 0; Y < THETA_SAMPLES; Y++)
            {
                for (int X = 0; X < 4 * THETA_SAMPLES; X++)
                {
                    double phi   = dPhi * (X + SimpleRNG.GetUniform());
                    double theta = 2.0 * Math.Acos(Math.Sqrt(1.0 - 0.5 * (Y + SimpleRNG.GetUniform()) / THETA_SAMPLES));                                // Uniform sampling on theta
                    directions[4 * THETA_SAMPLES * Y + X].Set((float)(Math.Sin(theta) * Math.Cos(phi)), (float)(Math.Sin(theta) * Math.Sin(phi)), (float)Math.Cos(theta));
                }
            }

            // Compute numerical integration for various sets of angles
            const int TABLE_SIZE = 100;

            float3 coneDirection = float3.Zero;

            float3[,]       integratedSHCoeffs = new float3[TABLE_SIZE, TABLE_SIZE];

            double avgDiffA0 = 0.0;
            double avgDiffA1 = 0.0;
            double avgDiffA2 = 0.0;

            for (int thetaIndex = 0; thetaIndex < TABLE_SIZE; thetaIndex++)
            {
//				float	cosTheta = 1.0f - (float) thetaIndex / TABLE_SIZE;
                float cosTheta = (float)Math.Cos(0.5 * Math.PI * thetaIndex / TABLE_SIZE);
                coneDirection.x = (float)Math.Sqrt(1.0f - cosTheta * cosTheta);
                coneDirection.z = cosTheta;

                for (int AOIndex = 0; AOIndex < TABLE_SIZE; AOIndex++)
                {
//					float	AO = 1.0f - (float) AOIndex / TABLE_SIZE;
//					float	coneHalfAngle = 0.5f * (float) Math.PI * AO;			// Cone half angle varies in [0,PI/2]
//					float	cosConeHalfAngle = (float) Math.Cos( coneHalfAngle );
                    float cosConeHalfAngle = (float)AOIndex / TABLE_SIZE;

                    double A0 = 0.0;
                    double A1 = 0.0;
                    double A2 = 0.0;
                    for (int sampleIndex = 0; sampleIndex < SAMPLES_COUNT; sampleIndex++)
                    {
                        float3 direction = directions[sampleIndex];
                        if (direction.Dot(coneDirection) < cosConeHalfAngle)
                        {
                            continue;                                   // Sample is outside cone
                        }
                        float u  = direction.z;                         // cos(theta_sample)
                        float u2 = u * u;
                        float u3 = u * u2;
                        A0 += u;
//A0 += 1.0;
                        A1 += u2;
                        A2 += 0.5 * (3 * u3 - u);
                    }

                    A0 *= 2.0 * Math.PI / SAMPLES_COUNT;
                    A1 *= 2.0 * Math.PI / SAMPLES_COUNT;
                    A2 *= 2.0 * Math.PI / SAMPLES_COUNT;
                    A0 *= Math.Sqrt(1.0 / (4.0 * Math.PI));
                    A1 *= Math.Sqrt(3.0 / (4.0 * Math.PI));
                    A2 *= Math.Sqrt(5.0 / (4.0 * Math.PI));

// float3	verify = EstimateLambertReflectanceFactors( cosConeHalfAngle, 0.5f * (float) Math.PI * thetaIndex / TABLE_SIZE );
// avgDiffA0 += Math.Abs( A0 - verify.x );
// avgDiffA1 += Math.Abs( A1 - verify.y );
// avgDiffA2 += Math.Abs( A2 - verify.z );

                    integratedSHCoeffs[thetaIndex, AOIndex].Set((float)A0, (float)A1, (float)A2);
                }
            }

            avgDiffA0 /= TABLE_SIZE * TABLE_SIZE;
            avgDiffA1 /= TABLE_SIZE * TABLE_SIZE;
            avgDiffA2 /= TABLE_SIZE * TABLE_SIZE;

            using (System.IO.FileStream S = new System.IO.FileInfo(@"ConeTable_cosAO.float3").Create())
                using (System.IO.BinaryWriter W = new System.IO.BinaryWriter(S)) {
                    for (int thetaIndex = 0; thetaIndex < TABLE_SIZE; thetaIndex++)
                    {
                        for (int AOIndex = 0; AOIndex < TABLE_SIZE; AOIndex++)
                        {
                            W.Write(integratedSHCoeffs[thetaIndex, AOIndex].x);
                            W.Write(integratedSHCoeffs[thetaIndex, AOIndex].y);
                            W.Write(integratedSHCoeffs[thetaIndex, AOIndex].z);
                        }
                    }
                }
        }
Example #26
0
        private void buttonReset_Click(object sender, EventArgs e)
        {
            m_CB_Main.m._cameraSize   = 10.0f * float2.One;
            m_CB_Main.m._cameraCenter = float2.Zero;
            m_CB_Main.UpdateData();

#if true
            for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++)
            {
                m_SB_NodeSims[0].m[neuronIndex].m_position.Set(0.5f * m_CB_Main.m._cameraSize.x * (2.0f * (float)SimpleRNG.GetUniform() - 1.0f), 0.5f * m_CB_Main.m._cameraSize.y * (2.0f * (float)SimpleRNG.GetUniform() - 1.0f));                     // In a size 2 square
//m_SB_NodeSims[0].m[neuronIndex].m_position.Set( 2.0f * neuronIndex - 1.0f, 0.0f );
                m_SB_NodeSims[0].m[neuronIndex].m_velocity.Set(0, 0);
            }
            m_SB_NodeSims[0].Write();
#else
            for (int neuronIndex = 0; neuronIndex < m_nodesCount; neuronIndex++)
            {
                float a = Mathf.TWOPI * neuronIndex / m_nodesCount;
                m_SB_NodeSims[0].m[neuronIndex].m_position.Set(Mathf.Cos(a), Mathf.Sin(a));                             // Set on a unit circle
                m_SB_NodeSims[0].m[neuronIndex].m_velocity.Set(0, 0);
            }
            m_SB_NodeSims[0].Write();
#endif
        }
Example #27
0
 private static double RdmGenerator(double max)
 {
     return(max * SimpleRNG.GetUniform());
 }