Ejemplo n.º 1
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 });
        }
Ejemplo n.º 2
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!
                }
            }
        }
Ejemplo n.º 3
0
 public GA(int seed, int popsize, int offsize, double deathRate)
 {
     _seed = seed;
     SimpleRNG.SetSeed((uint)_seed, (uint)_seed + 1);
     _popsize   = popsize;
     _offsize   = offsize;
     _deathRate = deathRate;
     population = new ScheduleGenome[_popsize];
     offspring  = new ScheduleGenome[_offsize];
     // Default operator options:
     realCrossover     = RealCrossoverOp.MeanWithNoise;
     survivalSelection = SurvivalSelectionOp.Elitist;
     parentSelection   = ParentSelectionOp.Tournament;
 }
Ejemplo n.º 4
0
    public void UpdateStonesAtPatch(IntVector2 patchCoord, Transform patchHolder)
    {
        // reset SimpleRNG using cactus seed
        SimpleRNG.SetSeed((uint)(stoneSeed + patchCoord.x + patchCoord.y * terrainManager.worldPatchesX));
        // set RNG seed depending on stone seed, world seed, and patch coordinates
        stoneRNG = new System.Random(stoneSeed + patchCoord.x + patchCoord.y * terrainManager.worldPatchesX);

        // in plain terrain
        float stonePlainDensityHere = stonePlainDensity.min + (float)stoneRNG.NextDouble() * (stonePlainDensity.max - stonePlainDensity.min);

        for (int i = 0; i < stonePlainDensityHere; i++)
        {
            Vector3 point = loadSceneryAndLore.GetValidRandomPositionInPatch(patchCoord, 1f, stoneRNG);

            float slope = terrainManager.GetSlopeAtPoint(point.x, point.z);
            //Debug.Log(point + ", " + slope);

            if (slope > stonePlainSlope.min && slope < stonePlainSlope.max)
            {
                GameObject temp = Instantiate(stonePlainPrefabs[stoneRNG.Next(stonePlainPrefabs.Length)], point, Quaternion.identity);
                temp.transform.localScale = Vector3.one * (stonePlainScale.min + (float)stoneRNG.NextDouble() * (stonePlainScale.max - stonePlainScale.min));
                temp.transform.Translate(stonePlainOffset * temp.transform.localScale.x);
                temp.transform.Rotate(Vector3.up * (float)stoneRNG.NextDouble() * 360f);

                temp.transform.parent = patchHolder.transform;
            }
        }

        // in cliffs
        float stoneCliffDensityHere = stoneCliffDensity.min + (float)stoneRNG.NextDouble() * (stoneCliffDensity.max - stoneCliffDensity.min);

        for (int i = 0; i < stoneCliffDensityHere; i++)
        {
            Vector3 point = loadSceneryAndLore.GetValidRandomPositionInPatch(patchCoord, 1f, stoneRNG);

            float slope = terrainManager.GetSlopeAtPoint(point.x, point.z);

            if (slope > stoneCliffSlope.min && slope < stoneCliffScale.max)
            {
                GameObject temp = Instantiate(stoneCliffPrefabs[stoneRNG.Next(stoneCliffPrefabs.Length)], point, Quaternion.identity);
                temp.transform.localScale = Vector3.one * (stoneCliffScale.min + (float)stoneRNG.NextDouble() * (stoneCliffScale.max - stoneCliffScale.min)); // re-scale
                temp.transform.Translate(stoneCliffOffset * temp.transform.localScale.x);                                                                     // apply downwards offset
                temp.transform.Rotate(Vector3.up * (float)stoneRNG.NextDouble() * 360f);

                temp.transform.parent = patchHolder.transform;
            }
        }
    }
Ejemplo n.º 5
0
        public void Initialize()
        {
            simpleRng             = new SimpleRNG();
            animationCurveSampler = new AnimationCurveSampler(probabilityCurve);

            //Clear LowDiscrepancyList
            lowDiscrepancyValues.Clear();

            //Seed
            switch (seedType)
            {
            case SeedType.GenerateSeed: //generate random seed
                simpleRng.SetSeedFromSystemTime();
                break;

            case SeedType.CustomSeed: //use custom seed
                simpleRng.SetSeed(customSeed);
                break;
            }
        }
Ejemplo n.º 6
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);
            }
        }
Ejemplo n.º 7
0
    public void UpdateVegetationAtPatch(IntVector2 patchCoord, Transform patchHolder)
    {
        // reset SimpleRNG using tree seed
        SimpleRNG.SetSeed((uint)(treeNoiseSeed + patchCoord.x + patchCoord.y * terrainManager.worldPatchesX));
        // set RNG seed depending on tree seed, world seed, and patch coordinates
        treeRNG = new System.Random(treeNoiseSeed + patchCoord.x + patchCoord.y * terrainManager.worldPatchesX);

        if (treePrefabs.Length > 0)
        {
            // get the number of trees in the patch (vegetation density)
            int numberOftrees = 0;
            if (true)
            {
                numberOftrees = Mathf.RoundToInt(Mathf.Max(0f, (float)SimpleRNG.GetNormal(treeDensity, treeDensityStdev)));
            }
            else
            {
                numberOftrees = Mathf.RoundToInt(vegetationNoiseOutsideModel.FractalNoise2D(patchCoord.x, patchCoord.y, 4, treeNoiseFrequency, treeNoiseScale) * treeDensity);
            }

            // place trees
            for (int i = 0; i < numberOftrees; i++)
            {
                // scale x and z coordinates for placing prefab prototypes in terrain. Note that this is not needed when placing GameObjects
                //Vector3 point = terrainManager.GetRandomPointInPatchSurface(patchCoord, treeRNG, scaleToTerrain: true);
                Vector3 point = loadSceneryAndLore.GetValidRandomPositionInPatch(patchCoord, 1f, treeRNG);

                float slope = terrainManager.GetSlopeAtPoint(point.x, point.z);

                if (slope < 0.7f)
                { //make sure tree are not on cliffs
                    GameObject temp = Instantiate(treePrefabs[Random.Range(0, treePrefabs.Length)], point, Quaternion.identity);
                    //temp.transform.Translate(Vector3.down * 1f);
                    temp.transform.localScale = Vector3.one * (treeScale.min + (float)treeRNG.NextDouble() * (treeScale.max - treeScale.min));
                    temp.transform.Rotate(Vector3.up * Random.Range(0f, 360f));

                    temp.transform.parent = patchHolder.transform;
                    //					TreeInstance temp = new TreeInstance ();
                    //					temp.position = point;
                    //					temp.rotation = Random.Range (0f, 360f) * Mathf.Deg2Rad;
                    //					temp.prototypeIndex = Random.Range (0, treePrefabs.Length);
                    //					temp.color = Color.white;
                    //					temp.lightmapColor = Color.white;
                    //
                    //					actTerrain.AddTreeInstance (temp);
                }
            }
        }
        //Debug.Log (terrainData.treeInstanceCount);

        // reset SimpleRNG using cactus seed
        SimpleRNG.SetSeed((uint)(cactusNoiseSeed + patchCoord.x + patchCoord.y * terrainManager.worldPatchesX));
        // set RNG seed depending on cactus seed, world seed, and patch coordinates
        cactusRNG = new System.Random(cactusNoiseSeed + patchCoord.x + patchCoord.y * terrainManager.worldPatchesX);

        if (cactusPrefabs.Length > 0)
        {
            // get the number of cactus in the patch (vegetation density)
            int numberOfCactus = 0;
            if (true)
            {
                numberOfCactus = Mathf.RoundToInt(Mathf.Max((float)SimpleRNG.GetNormal(cactusDensity, cactusDensityStdev)));
            }
            else
            {
                numberOfCactus = Mathf.RoundToInt(vegetationNoiseOutsideModel.FractalNoise2D(patchCoord.x, patchCoord.y, 4, cactusNoiseFrequency, cactusNoiseScale) * cactusDensity);
            }

            // place trees
            for (int i = 0; i < numberOfCactus; i++)
            {
                //Debug.Log(patchCoord.ToString());
                // scale x and z coordinates for placing prefab prototypes in terrain. Note that this is not needed when placing GameObjects
                //Vector3 point = terrainManager.GetRandomPointInPatchSurface(patchCoord, cactusRNG, scaleToTerrain: true);
                Vector3 point = loadSceneryAndLore.GetValidRandomPositionInPatch(patchCoord, 1f, cactusRNG);

                // normal diffusion
                //point = new Vector3(point.x + (float)SimpleRNG.GetNormal(0, .01f), 0f, point.z + (float)SimpleRNG.GetNormal(0, 0.01f));

                float slope = terrainManager.GetSlopeAtPoint(point.x, point.z);

                if (slope < 0.7f)
                { //make sure cactus are not on cliffs
                    GameObject temp = Instantiate(cactusPrefabs[cactusRNG.Next(0, cactusPrefabs.Length)], point, Quaternion.identity);
                    //temp.transform.Translate(Vector3.down * 0.2f);
                    temp.transform.localScale = Vector3.one * (cactusScale.min + (float)cactusRNG.NextDouble() * (cactusScale.max - cactusScale.min));
                    temp.transform.Rotate(Vector3.up * Random.Range(0f, 360f));

                    temp.transform.parent = patchHolder.transform;
                    //TreeInstance temp = new TreeInstance();
                    //temp.position = point;
                    //temp.rotation = Random.Range(0f, 360f) * Mathf.Deg2Rad;
                    //temp.prototypeIndex = Random.Range(treePrefabs.Length, treePrefabs.Length + cactusPrefabs.Length);
                    //float randomScale = Random.Range(1f, cactusMaxScale);
                    //temp.widthScale = randomScale;
                    //temp.heightScale = randomScale;
                    //temp.color = Color.white;
                    //temp.lightmapColor = Color.white;
                    //actTerrain.AddTreeInstance(temp);
                }
            }
        }
    }
        /// <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!
                }
            }
        }
Ejemplo n.º 9
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);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Generates blue noise distribution using the void-and-cluster method
        /// </summary>
        /// <param name="_randomSeed"></param>
        /// <param name="_standardDeviation">Standard deviation for gaussian kernel. If not sure, use 2.1</param>
        /// <param name="_notifyProgressInterval">Will read back the GPU texture to the CPU and notify of progress each time we run for that much progress interval</param>
        /// <param name="_progress"></param>
        public void             Generate(uint _randomSeed, float _standardDeviation, float _notifyProgressInterval, ProgressDelegate _progress)
        {
            if (m_device == null)
            {
                // Use the CPU version!
                GenerateCPU(_randomSeed, _standardDeviation, _notifyProgressInterval, _progress);
                return;
            }

            uint progressNotificationInterval = Math.Max(1, (uint)Math.Ceiling(_notifyProgressInterval * m_textureTotalSize));

            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._kernelFactor = -1.0f / (2.0f * _standardDeviation * _standardDeviation);

            m_texBinaryPattern.SetCSUAV(0);
            m_texDitheringArray.SetCSUAV(1);

            SimpleRNG.SetSeed(_randomSeed, 362436069U);

            List <float> statistics = new List <float>((int)m_textureTotalSize);

            for (uint iterationIndex = 0; iterationIndex < m_textureTotalSize; iterationIndex++)
            {
                m_CB_Main.m._randomOffsetX  = GetUniformInt(m_textureSize);
                m_CB_Main.m._randomOffsetY  = GetUniformInt(m_textureSize);
                m_CB_Main.m._iterationIndex = iterationIndex;
                m_CB_Main.UpdateData();

                // 1] Filter binary texture and compute "clustering score"
                if (m_CS_Filter.Use())
                {
                    m_texScore0.SetCSUAV(2);

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

                    m_texScore0.RemoveFromLastAssignedSlotUAV();
                }

                // 2] Downsample score and keep lowest value and the position where to find it
                                #if !BYPASS_GPU_DOWNSAMPLING
                if (m_CS_DownsampleScore16.Use())
                {
                    uint groupsCount    = m_textureSize;
                    uint mipLevelIndex  = 0;
                    uint mipLevelsCount = (uint)m_texturePOT;

                    m_CB_Mips.m._textureMipTarget = 0;

                    // 2.1) Downsample by groups of 4 mips
                    while (mipLevelsCount >= 4)
                    {
                        mipLevelIndex  += 4;
                        mipLevelsCount -= 4;
                        groupsCount   >>= 4;

                        m_texScore0.SetCS(0);
                        m_texScore1.GetView(mipLevelIndex, 1, 0, 1).SetCSUAV(2);

                        m_CB_Mips.m._textureMipSource = m_CB_Mips.m._textureMipTarget;
                        m_CB_Mips.m._textureMipTarget = mipLevelIndex;
                        m_CB_Mips.UpdateData();

                        m_CS_DownsampleScore16.Dispatch(groupsCount, groupsCount, 1);

                        m_texScore0.RemoveFromLastAssignedSlots();
                        m_texScore1.RemoveFromLastAssignedSlotUAV();

                        // Swap
                        Texture2D temp = m_texScore0;
                        m_texScore0 = m_texScore1;
                        m_texScore1 = temp;

                        // Clear any random offset after first pass
                        m_CB_Main.m._randomOffsetX = 0;
                        m_CB_Main.m._randomOffsetY = 0;
                        m_CB_Main.UpdateData();
                    }

                    // 2.2) Downsample to last mip
                    ComputeShader CSLastMip = null;
                    switch (mipLevelsCount)
                    {
                    case 3: CSLastMip = m_CS_DownsampleScore8; break;

                    case 2: CSLastMip = m_CS_DownsampleScore4; break;

                    case 1: CSLastMip = m_CS_DownsampleScore2; break;
                    }
                    if (CSLastMip != null && CSLastMip.Use())
                    {
                        m_texScore0.SetCS(0);
                        m_texScore1.GetView((uint)m_texturePOT, 1, 0, 1).SetCSUAV(2);

                        m_CB_Mips.m._textureMipSource = m_CB_Mips.m._textureMipTarget;
                        m_CB_Mips.m._textureMipTarget = (uint)m_texturePOT;
                        m_CB_Mips.UpdateData();

                        CSLastMip.Dispatch(1, 1, 1);

                        m_texScore0.RemoveFromLastAssignedSlots();
                        m_texScore1.RemoveFromLastAssignedSlotUAV();

                        // Swap
                        Texture2D temp = m_texScore0;
                        m_texScore0 = m_texScore1;
                        m_texScore1 = temp;
                    }

// #if DEBUG
// DebugDownsampling();
// //DebugSplatPosition( iterationIndex );
// #endif
                }
                                #else
                DownsampleCPU(iterationIndex, statistics);
                m_CB_Mips.m._textureMipTarget = (uint)m_texturePOT;
                                #endif

                // 3] Splat a new pixel where we located the best score
                if (m_CS_Splat.Use())
                {
                    m_texScore0.SetCS(0);

                    m_CB_Mips.m._textureMipSource = m_CB_Mips.m._textureMipTarget;
                    m_CB_Mips.UpdateData();

                    m_CS_Splat.Dispatch(1, 1, 1);

                    m_texScore0.RemoveFromLastAssignedSlots();
                }

                if (_progress == null || iterationIndex % progressNotificationInterval != 0)
                {
                    continue;
                }

                ReadBackTexture();
                _progress((float)iterationIndex / m_textureTotalSize, m_ditheringArray, statistics);
            }

            m_texBinaryPattern.RemoveFromLastAssignedSlotUAV();
            m_texDitheringArray.RemoveFromLastAssignedSlotUAV();

            // Read back final result
            ReadBackTexture();

            // Notify one last time
            if (_progress != null)
            {
                _progress(1.0f, m_ditheringArray, statistics);
            }
        }
Ejemplo n.º 11
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);
                    }
                }
            }
        }
    }