Example #1
0
        private void Generate()
        {
            try {
                tabControlGenerators.Enabled = false;

                //////////////////////////////////////////////////////////////////////////
                // 1] Apply bilateral filtering to the input texture as a pre-process
                ApplyBilateralFiltering( m_textureSourceHeightMap, m_textureTarget0, floatTrackbarControlBilateralRadius.Value, floatTrackbarControlBilateralTolerance.Value, checkBoxWrap.Checked );

                //////////////////////////////////////////////////////////////////////////
                // 2] Compute directional occlusion
                m_textureTarget1.RemoveFromLastAssignedSlots();

                // Prepare computation parameters
                m_textureTarget0.SetCS( 0 );
                m_textureTarget1.SetCSUAV( 0 );
                m_SB_Rays.SetInput( 1 );

                m_CB_Input.m.RaysCount = (UInt32) Math.Min( MAX_THREADS, integerTrackbarControlRaysCount.Value );
                m_CB_Input.m.MaxStepsCount = (UInt32) integerTrackbarControlMaxStepsCount.Value;
                m_CB_Input.m.Tile = (uint) (checkBoxWrap.Checked ? 1 : 0);
                m_CB_Input.m.TexelSize_mm = TextureSize_mm / Math.Max( W, H );
                m_CB_Input.m.Displacement_mm = TextureHeight_mm;

                // Start
                if ( !m_CS_GenerateSSBumpMap.Use() )
                    throw new Exception( "Can't generate self-shadowed bump map as compute shader failed to compile!" );

                uint	h = Math.Max( 1, MAX_LINES*1024 / W );
                uint	callsCount = (uint) Math.Ceiling( (float) H / h );
                for ( uint i=0; i < callsCount; i++ ) {
                    m_CB_Input.m.Y0 = i * h;
                    m_CB_Input.UpdateData();

                    m_CS_GenerateSSBumpMap.Dispatch( W, h, 1 );

                    m_device.Present( true );

                    progressBar.Value = (int) (0.01f * (BILATERAL_PROGRESS + (100-BILATERAL_PROGRESS) * (i+1) / (callsCount)) * progressBar.Maximum);
            //					for ( int a=0; a < 10; a++ )
                        Application.DoEvents();
                }

                m_textureTarget1.RemoveFromLastAssignedSlotUAV();	// So we can use it as input for next stage

                progressBar.Value = progressBar.Maximum;

                // Compute in a single shot (this is madness!)
            // 				m_CB_Input.m.y = 0;
            // 				m_CB_Input.UpdateData();
            // 				m_CS_GenerateSSBumpMap.Dispatch( W, H, 1 );

                //////////////////////////////////////////////////////////////////////////
                // 3] Copy target to staging for CPU readback and update the resulting bitmap
                m_textureTarget_CPU.CopyFrom( m_textureTarget1 );

                if ( m_imageResult != null )
                    m_imageResult.Dispose();
                m_imageResult = null;
                m_imageResult = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.RGBA8, m_linearProfile );

                float4[]		scanline = new float4[W];
                PixelsBuffer	pixels = m_textureTarget_CPU.Map( 0, 0 );
                using ( System.IO.BinaryReader R = pixels.OpenStreamRead() )
                    for ( uint Y=0; Y < H; Y++ ) {
                        R.BaseStream.Position = Y * pixels.RowPitch;
                        for ( int X=0; X < W; X++ ) {
                            scanline[X].Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle(), R.ReadSingle() );
                        }
                        m_imageResult.WriteScanline( Y, scanline );
                    }

                pixels.Dispose();
                m_textureTarget_CPU.UnMap( 0, 0 );

                // Assign result
                viewportPanelResult.Image = m_imageResult;

            } catch ( Exception _e ) {
                MessageBox( "An error occurred during generation!\r\n\r\nDetails: ", _e );
            } finally {
                tabControlGenerators.Enabled = true;
            }
        }
Example #2
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 #3
0
        private void MixResults( float3 _MixColor )
        {
            if ( m_TextureTargets[0][0] == null )
                return;	// Nothing to mix yet...

            if ( !m_CS_Helper_Mix.Use() )
                throw new Exception( "Can't mix translucency maps as mixer compute shader failed to compile!" );

            //////////////////////////////////////////////////////////////////////////
            // 1] Combine
            m_CB_Helper.m._Width = (uint) W;
            m_CB_Helper.m._Height = (uint) H;
            m_CB_Helper.m._Parms = _MixColor;
            m_CB_Helper.UpdateData();

            m_TextureTargets[0][0].SetCS( 0 );
            m_TextureTargets[1][0].SetCS( 1 );
            m_TextureTargets[2][0].SetCS( 2 );
            m_TextureTargetCombined.RemoveFromLastAssignedSlots();
            m_TextureTargetCombined.SetCSUAV( 0 );

            uint	groupsCountX = (W + 15) >> 4;
            uint	groupsCountY = (H + 15) >> 4;

            m_CS_Helper_Mix.Dispatch( groupsCountX, groupsCountY, 1 );

            m_TextureTargetCombined.RemoveFromLastAssignedSlotUAV();	// So we can use it as input for next stage

            //////////////////////////////////////////////////////////////////////////
            // 2] Copy target to staging for CPU readback and update the resulting bitmaps
            if ( m_imageResultCombined != null )
                m_imageResultCombined.Dispose();
            m_imageResultCombined = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.RGBA8, m_sRGBProfile );

            // Copy from GPU to CPU
            m_TextureTarget_CPU.CopyFrom( m_TextureTargetCombined );

            PixelsBuffer	Pixels = m_TextureTarget_CPU.Map( 0, 0 );
            float4[]		scanline = new float4[W];
            float4			gammaRGB = float4.Zero;

            using ( System.IO.BinaryReader R = Pixels.OpenStreamRead() )
                for ( uint Y=0; Y < H; Y++ ) {
                    R.BaseStream.Position = Y * Pixels.RowPitch;
                    for ( uint X=0; X < W; X++ ) {
                        gammaRGB.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle(), R.ReadSingle() );
                        m_sRGBProfile.LinearRGB2GammaRGB( gammaRGB, ref scanline[X] );
                    }
                    m_imageResultCombined.WriteScanline( Y, scanline );
                }

            Pixels.Dispose();
            m_TextureTarget_CPU.UnMap( 0, 0 );

            // Assign result
            imagePanelResult3.Image = m_imageResultCombined;
        }
Example #4
0
        private void    Generate()
        {
            try {
                tabControlGenerators.Enabled = false;

                //////////////////////////////////////////////////////////////////////////
                // 1] Apply bilateral filtering to the input texture as a pre-process
                ApplyBilateralFiltering(m_textureSourceHeightMap, m_textureTarget0, floatTrackbarControlBilateralRadius.Value, floatTrackbarControlBilateralTolerance.Value, checkBoxWrap.Checked);


                //////////////////////////////////////////////////////////////////////////
                // 2] Compute directional occlusion
                m_textureTarget1.RemoveFromLastAssignedSlots();

                // Prepare computation parameters
                m_textureTarget0.SetCS(0);
                m_textureTarget1.SetCSUAV(0);
                m_SB_Rays.SetInput(1);

                m_CB_Input.m.RaysCount       = (UInt32)Math.Min(MAX_THREADS, integerTrackbarControlRaysCount.Value);
                m_CB_Input.m.MaxStepsCount   = (UInt32)integerTrackbarControlMaxStepsCount.Value;
                m_CB_Input.m.Tile            = (uint)(checkBoxWrap.Checked ? 1 : 0);
                m_CB_Input.m.TexelSize_mm    = TextureSize_mm / Math.Max(W, H);
                m_CB_Input.m.Displacement_mm = TextureHeight_mm;

                // Start
                if (!m_CS_GenerateSSBumpMap.Use())
                {
                    throw new Exception("Can't generate self-shadowed bump map as compute shader failed to compile!");
                }

                uint h          = Math.Max(1, MAX_LINES * 1024 / W);
                uint callsCount = (uint)Math.Ceiling((float)H / h);
                for (uint i = 0; i < callsCount; i++)
                {
                    m_CB_Input.m.Y0 = i * h;
                    m_CB_Input.UpdateData();

                    m_CS_GenerateSSBumpMap.Dispatch(W, h, 1);

                    m_device.Present(true);

                    progressBar.Value = (int)(0.01f * (BILATERAL_PROGRESS + (100 - BILATERAL_PROGRESS) * (i + 1) / (callsCount)) * progressBar.Maximum);
//					for ( int a=0; a < 10; a++ )
                    Application.DoEvents();
                }

                m_textureTarget1.RemoveFromLastAssignedSlotUAV();                       // So we can use it as input for next stage

                progressBar.Value = progressBar.Maximum;

                // Compute in a single shot (this is madness!)
//              m_CB_Input.m.y = 0;
//              m_CB_Input.UpdateData();
//              m_CS_GenerateSSBumpMap.Dispatch( W, H, 1 );


                //////////////////////////////////////////////////////////////////////////
                // 3] Copy target to staging for CPU readback and update the resulting bitmap
                m_textureTarget_CPU.CopyFrom(m_textureTarget1);

                if (m_imageResult != null)
                {
                    m_imageResult.Dispose();
                }
                m_imageResult = null;
                m_imageResult = new ImageUtility.ImageFile(W, H, ImageUtility.PIXEL_FORMAT.RGBA8, m_linearProfile);

                float4[]     scanline = new float4[W];
                PixelsBuffer pixels   = m_textureTarget_CPU.MapRead(0, 0);
                using (System.IO.BinaryReader R = pixels.OpenStreamRead())
                    for (uint Y = 0; Y < H; Y++)
                    {
                        R.BaseStream.Position = Y * pixels.RowPitch;
                        for (int X = 0; X < W; X++)
                        {
                            scanline[X].Set(R.ReadSingle(), R.ReadSingle(), R.ReadSingle(), R.ReadSingle());
                        }
                        m_imageResult.WriteScanline(Y, scanline);
                    }

                m_textureTarget_CPU.UnMap(pixels);

                // Assign result
                viewportPanelResult.Image = m_imageResult;
            } catch (Exception _e) {
                MessageBox("An error occurred during generation!\r\n\r\nDetails: ", _e);
            } finally {
                tabControlGenerators.Enabled = true;
            }
        }