/// <summary>
        /// Returns a value in [0,_maxValue[
        /// </summary>
        /// <param name="_maxValue"></param>
        /// <returns></returns>
        uint    GetUniformInt(uint _maxValue)
        {
            ulong value = (ulong)_maxValue * (ulong)SimpleRNG.GetUint();

            value >>= 32;
            return((uint)value);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Randomly fills bottom states
 /// </summary>
 public void             Init()
 {
     for (int X = 0; X < m_size; X++)
     {
         for (int Z = 0; Z < m_size; Z++)
         {
             m_grid[X, m_size - 1, Z] = (byte)(1 + (SimpleRNG.GetUint() & 1));
         }
     }
 }
        /// <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!
                }
            }
        }
Exemplo n.º 4
0
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            try {
                m_device.Init(panelOutput.Handle, false, true);
            } catch (Exception _e) {
                m_device = null;
                MessageBox.Show("Failed to initialize DX device!\n\n" + _e.Message, "MSBRDF Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try {
//				m_shader_Render = new Shader( m_device, new System.IO.FileInfo( "Shaders/Render.hlsl" ), VERTEX_FORMAT.Pt4, "VS", null, "PS", null );						// OBSOLETE MSBRDF CODE! For historical purpose only...
                m_shader_Finalize = new Shader(m_device, new System.IO.FileInfo("Shaders/RenderComplete.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS_Finalize", null);
                                #if TEST_SH_ENVIRONMENT
                m_shader_Accumulate = new Shader(m_device, new System.IO.FileInfo("Shaders/RenderCompareSH.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null);                                                  // Use this to show a rendering with SH environment
                checkBoxUseRealTimeApprox.Visible            = true;
                checkBoxUseRealTimeApprox.Checked            = true;
                floatTrackbarControlRoughnessSphere.Value    = 1;                                                                                               // Show full roughness
                floatTrackbarControlReflectanceSphere2.Value = 0;                                                                                               // Disturbing if diffuse is showing!
                groupBoxPlane.Visible = false;                                                                                                                  // No plane is available in this configuration
                                #elif TEST_LTC_AREA_LIGHT
                m_shader_Accumulate = new Shader(m_device, new System.IO.FileInfo("Shaders/RenderCompareLTC.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null); // Use this to show a rendering with LTC area light
                checkBoxUseRealTimeApprox.Visible = true;
//					checkBoxUseRealTimeApprox.Checked = true;
                checkBoxUseRealTimeApprox.Checked = false;
//                  floatTrackbarControlRoughnessSphere.Value = 1;		// Show full roughness
//                  floatTrackbarControlReflectanceSphere2.Value = 0;	// Disturbing if diffuse is showing!

                checkBoxUseLTC.Visible = true;

                floatTrackbarControlRoughnessSphere.Value    = 0.25f;
                floatTrackbarControlReflectanceSphere.Value  = 0.04f;
                floatTrackbarControlRoughnessSphere2.Value   = 0.80f;
                floatTrackbarControlReflectanceSphere2.Value = 0.5f;

                floatTrackbarControlRoughnessGround.Value   = 0.85f;
                floatTrackbarControlReflectanceGround.Value = 0.35f;

                floatTrackbarControlLightElevation.Value = 0.5f;
                                #else
                m_shader_Accumulate = new Shader(m_device, new System.IO.FileInfo("Shaders/RenderComplete.hlsl"), VERTEX_FORMAT.Pt4, "VS", null, "PS", null);                                                   // Use this for a full render
                                #endif
            } catch (Exception _e) {
                MessageBox.Show("Shader failed to compile!\n\n" + _e.Message, "MSBRDF Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            uint W = (uint)panelOutput.Width;
            uint H = (uint)panelOutput.Height;

            m_CB_Global = new ConstantBuffer <CB_Global>(m_device, 0);
            m_CB_Camera = new ConstantBuffer <CB_Camera>(m_device, 1);
            m_CB_Render = new ConstantBuffer <CB_Render>(m_device, 2);
            m_CB_SH     = new ConstantBuffer <CB_SH>(m_device, 3);

            BuildNoiseTextures();

            // Shuffle group indices
            for (uint groupIndex = 0; groupIndex < GROUPS_COUNT; groupIndex++)
            {
                m_groupShuffle[groupIndex] = groupIndex;
            }
            for (uint shuffleIndex = 100 * GROUPS_COUNT; shuffleIndex > 0; shuffleIndex--)
            {
                for (uint groupIndex = 0; groupIndex < GROUPS_COUNT; groupIndex++)
                {
                    uint i0   = SimpleRNG.GetUint() % GROUPS_COUNT;
                    uint i1   = SimpleRNG.GetUint() % GROUPS_COUNT;
                    uint temp = m_groupShuffle[i0];
                    m_groupShuffle[i0] = m_groupShuffle[i1];
                    m_groupShuffle[i1] = temp;
                }
            }

// Tables are "built" with Mathematica now
//			BuildMSBRDF( new DirectoryInfo( @".\Tables\" ) );
            LoadMSBRDF(128, new FileInfo("./Tables/MSBRDF_GGX_G2_E128x128.float"), new FileInfo("./Tables/MSBRDF_GGX_G2_Eavg128.float"), out m_tex_MSBRDF_GGX_E, out m_tex_MSBRDF_GGX_Eavg);
            LoadMSBRDF(32, new FileInfo("./Tables/MSBRDF_OrenNayar_E32x32.float"), new FileInfo("./Tables/MSBRDF_OrenNayar_Eavg32.float"), out m_tex_MSBRDF_OrenNayar_E, out m_tex_MSBRDF_OrenNayar_Eavg);

                        #if TEST_LTC_AREA_LIGHT
            // Area light
            m_tex_LTC       = LoadLTC(new FileInfo(@".\Tables\LTC.dds"));
            m_tex_LTC_Unity = LoadUnityLTC();
                        #endif

            // Load cube map
            using (ImageUtility.ImagesMatrix I = new ImageUtility.ImagesMatrix()) {
//				I.DDSLoadFile( new FileInfo( "garage4_hd.dds" ) );
                I.DDSLoadFile(new FileInfo("beach.dds"));
                EncodeCubeMapIntoSH(I);
                m_tex_CubeMap = new Texture2D(m_device, I, ImageUtility.COMPONENT_FORMAT.AUTO);
            }

            m_tex_Accumulator = new Texture2D(m_device, m_device.DefaultTarget.Width, m_device.DefaultTarget.Height, 1, 1, ImageUtility.PIXEL_FORMAT.RGBA32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, null);

            // Setup camera
            m_camera.CreatePerspectiveCamera((float)(60.0 * Math.PI / 180.0), (float)panelOutput.Width / panelOutput.Height, 0.01f, 100.0f);
            m_manipulator.Attach(panelOutput, m_camera);
//			m_manipulator.InitializeCamera( new float3( 0, 1.5f, 2.0f ), new float3( -0.4f, 0, 0.4f ), float3.UnitY );					// Garage probe
            m_manipulator.InitializeCamera(new float3(1.46070266f, 1.10467184f, 1.36212754f), new float3(0, 1, 0), float3.UnitY);                       // Beach probe

            m_camera.CameraTransformChanged += Camera_CameraTransformChanged;
            Camera_CameraTransformChanged(null, EventArgs.Empty);

            // Start game time
            m_Ticks2Seconds = 1.0 / System.Diagnostics.Stopwatch.Frequency;
            m_StopWatch.Start();
            m_StartGameTime = GetGameTime();
        }