private void LoadResults( System.IO.FileInfo _FileName ) { try { groupBoxOptions.Enabled = false; // Dispose of existing resources if ( m_TextureTargets[0][0] != null ) { m_TextureTargets[0][0].Dispose(); m_TextureTargets[0][1].Dispose(); m_TextureTargets[1][0].Dispose(); m_TextureTargets[1][1].Dispose(); m_TextureTargets[2][0].Dispose(); m_TextureTargets[2][1].Dispose(); m_TextureTargetCombined.Dispose(); } m_TextureTargets[0][0] = null; m_TextureTargets[0][1] = null; m_TextureTargets[1][0] = null; m_TextureTargets[1][1] = null; m_TextureTargets[2][0] = null; m_TextureTargets[2][1] = null; m_TextureTargetCombined = null; if ( m_imageResults[0] != null ) m_imageResults[0].Dispose(); if ( m_imageResults[1] != null ) m_imageResults[1].Dispose(); if ( m_imageResults[2] != null ) m_imageResults[2].Dispose(); if ( m_imageResultCombined != null ) m_imageResultCombined.Dispose(); // m_imageResults[0] = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.R8, m_sRGBProfile ); // m_imageResults[1] = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.R8, m_sRGBProfile ); // m_imageResults[2] = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.R8, m_sRGBProfile ); // m_imageResultCombined = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.RGBA8, m_sRGBProfile ); m_imageResults[0] = new ImageUtility.ImageFile(); m_imageResults[1] = new ImageUtility.ImageFile(); m_imageResults[2] = new ImageUtility.ImageFile(); m_imageResultCombined = new ImageUtility.ImageFile(); // Load the result images assuming it's in sRGB space string[] FileNames = new string[4] { System.IO.Path.Combine( System.IO.Path.GetDirectoryName( _FileName.FullName ), System.IO.Path.GetFileNameWithoutExtension( _FileName.FullName ) + "_translucency0.png" ), System.IO.Path.Combine( System.IO.Path.GetDirectoryName( _FileName.FullName ), System.IO.Path.GetFileNameWithoutExtension( _FileName.FullName ) + "_translucency1.png" ), System.IO.Path.Combine( System.IO.Path.GetDirectoryName( _FileName.FullName ), System.IO.Path.GetFileNameWithoutExtension( _FileName.FullName ) + "_translucency2.png" ), System.IO.Path.Combine( System.IO.Path.GetDirectoryName( _FileName.FullName ), System.IO.Path.GetFileNameWithoutExtension( _FileName.FullName ) + "_translucency.png" ), }; ImageUtility.ImageFile[] images = new ImageUtility.ImageFile[] { m_imageResults[0], m_imageResults[1], m_imageResults[2], m_imageResultCombined }; Texture2D[] Results = new Texture2D[] { m_TextureTargets[0][0], m_TextureTargets[1][0], m_TextureTargets[2][0], m_TextureTargetCombined, }; ImagePanel[] Panels = new ImagePanel[] { imagePanelResult0, imagePanelResult1, imagePanelResult2, imagePanelResult3, }; for ( int i=0; i < 4; i++ ) { ImageUtility.ImageFile B = images[i]; B.Load( new System.IO.FileInfo( FileNames[i] ) ); Panels[i].Image = B; // Build the texture assuming sRGB sources float4[] scanline = new float4[B.Width]; float4 linearRGB = float4.Zero; PixelsBuffer sourceMap = new PixelsBuffer( B.Width*B.Height*16 ); using ( System.IO.BinaryWriter Wr = sourceMap.OpenStreamWrite() ) for ( uint Y=0; Y < B.Height; Y++ ) { B.ReadScanline( Y, scanline ); for ( uint X=0; X < B.Width; X++ ) { m_sRGBProfile.GammaRGB2LinearRGB( scanline[X], ref linearRGB ); Wr.Write( linearRGB.x ); Wr.Write( linearRGB.y ); Wr.Write( linearRGB.z ); Wr.Write( linearRGB.w ); } } Results[i] = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, true, new PixelsBuffer[] { sourceMap } ); } m_TextureTargets[0][0] = Results[0]; m_TextureTargets[0][1] = Results[0]; m_TextureTargets[1][0] = Results[1]; m_TextureTargets[1][1] = Results[1]; m_TextureTargets[2][0] = Results[2]; m_TextureTargets[2][1] = Results[2]; m_TextureTargetCombined = Results[3]; } catch ( Exception _e ) { MessageBox( "An error occurred while opening the result maps \"" + _FileName.FullName + "\":\n\n", _e ); } }
private void Generate() { try { groupBoxOptions.Enabled = false; ////////////////////////////////////////////////////////////////////////// // 0] Assign empty textures if ( m_imageSourceNormal == null ) LoadNormalMap( new System.IO.FileInfo( "default_normal.png" ) ); if ( m_imageSourceTransmittance == null ) LoadTransmittanceMap( new System.IO.FileInfo( "default_transmittance.png" ) ); if ( m_imageSourceAlbedo == null ) LoadAlbedoMap( new System.IO.FileInfo( "default_albedo.png" ) ); m_TextureTargets[0][0].RemoveFromLastAssignedSlots(); m_TextureTargets[0][1].RemoveFromLastAssignedSlots(); m_TextureTargets[1][0].RemoveFromLastAssignedSlots(); m_TextureTargets[1][1].RemoveFromLastAssignedSlots(); m_TextureTargets[2][0].RemoveFromLastAssignedSlots(); m_TextureTargets[2][1].RemoveFromLastAssignedSlots(); ////////////////////////////////////////////////////////////////////////// // 1] Apply bilateral filtering to the input texture as a pre-process ApplyBilateralFiltering( m_TextureSourceThickness, m_TextureFilteredThickness, floatTrackbarControlBilateralRadius.Value, floatTrackbarControlBilateralTolerance.Value, false ); ////////////////////////////////////////////////////////////////////////// // 2] Compute visibility texture BuildVisibilityMap( m_TextureFilteredThickness, m_TextureSourceVisibility ); //BuildVisibilityMap( m_TextureSourceThickness, m_TextureSourceVisibility ); // While we're not using bilateral filtering... //* ////////////////////////////////////////////////////////////////////////// // 3] Compute directional occlusion if ( !m_CS_GenerateTranslucencyMap.Use() ) throw new Exception( "Can't generate translucency map as compute shader failed to compile!" ); // Prepare computation parameters m_CB_Generate.m._Width = (uint) W; m_CB_Generate.m._Height = (uint) H; m_CB_Generate.m._TexelSize_mm = TextureSize_mm / Math.Max( W, H ); m_CB_Generate.m._Thickness_mm = Thickness_mm; m_CB_Generate.m._KernelSize = (uint) integerTrackbarControlKernelSize.Value; m_CB_Generate.m._Sigma_a = floatTrackbarControlAbsorptionCoefficient.Value; m_CB_Generate.m._Sigma_s = floatTrackbarControlScatteringCoefficient.Value; m_CB_Generate.m._g = floatTrackbarControlScatteringAnisotropy.Value; float IOR = floatTrackbarControlRefractionIndex.Value; m_CB_Generate.m._F0 = (IOR - 1.0f) / (IOR + 1.0f); m_CB_Generate.m._F0 *= m_CB_Generate.m._F0; // Assign inputs m_TextureFilteredThickness.SetCS( 0 ); //m_TextureSourceThickness.SetCS( 0 ); // While we're not using bilateral filtering... m_TextureSourceNormal.SetCS( 1 ); m_TextureSourceTransmittance.SetCS( 2 ); m_TextureSourceAlbedo.SetCS( 3 ); m_TextureSourceVisibility.SetCS( 4 ); uint groupsCountX = (W + 15) >> 4; uint groupsCountY = (H + 15) >> 4; uint raysCount = (uint) integerTrackbarControlRaysCount.Value; uint updateCountMax = Math.Max( 1, raysCount / 100 ); uint updateCount = 0; // For each HL2 basis direction for ( int i=0; i < 3; i++ ) { // switch ( i ) { // case 0: m_CB_Generate.m._Light = new float3( (float) Math.Sqrt( 2.0 / 3.0 ), 0.0f, (float) Math.Sqrt( 1.0 / 3.0 ) ); break; // case 1: m_CB_Generate.m._Light = new float3( (float) -Math.Sqrt( 1.0 / 6.0 ), (float) Math.Sqrt( 1.0 / 2.0 ), (float) Math.Sqrt( 1.0 / 3.0 ) ); break; // case 2: m_CB_Generate.m._Light = new float3( (float) -Math.Sqrt( 1.0 / 6.0 ), (float) -Math.Sqrt( 1.0 / 2.0 ), (float) Math.Sqrt( 1.0 / 3.0 ) ); break; // } // Clear initial target m_Device.Clear( m_TextureTargets[i][0], float4.Zero ); // Start for ( uint rayIndex=0; rayIndex < raysCount; rayIndex++ ) { m_CB_Generate.m._Light = m_rays[i][rayIndex]; //m_CB_Generate.m._Light = float3.UnitZ; m_CB_Generate.UpdateData(); m_TextureTargets[i][0].SetCS( 5 ); m_TextureTargets[i][1].SetCSUAV( 0 ); m_CS_GenerateTranslucencyMap.Dispatch( groupsCountX, groupsCountY, 1 ); m_TextureTargets[i][0].RemoveFromLastAssignedSlots(); m_TextureTargets[i][1].RemoveFromLastAssignedSlotUAV(); // Swap targets Texture2D Temp = m_TextureTargets[i][0]; m_TextureTargets[i][0] = m_TextureTargets[i][1]; m_TextureTargets[i][1] = Temp; // Progress if ( updateCount++ >= updateCountMax ) { updateCount = 0; m_Device.Present( true ); float progress = (float) (raysCount*i+1) / (3*raysCount); progressBar.Value = (int) (0.01f * (VISIBILITY_PROGRESS + (100-VISIBILITY_PROGRESS) * progress) * progressBar.Maximum); Application.DoEvents(); } } } progressBar.Value = progressBar.Maximum; ////////////////////////////////////////////////////////////////////////// // 3] Normalize results if ( !m_CS_Helper_Normalize.Use() ) throw new Exception( "Can't normalize translucency map as normalization compute shader failed to compile!" ); for ( int i=0; i < 3; i++ ) { m_CB_Helper.m._Width = (uint) W; m_CB_Helper.m._Height = (uint) H; m_CB_Helper.m._Parms = (1.0f / raysCount) * float3.One; m_CB_Helper.UpdateData(); m_TextureTargets[i][0].SetCS( 0 ); m_TextureTargets[i][1].SetCSUAV( 0 ); m_CS_Helper_Normalize.Dispatch( groupsCountX, groupsCountY, 1 ); m_TextureTargets[i][0].RemoveFromLastAssignedSlots(); m_TextureTargets[i][1].RemoveFromLastAssignedSlotUAV(); // Swap targets Texture2D Temp = m_TextureTargets[i][0]; m_TextureTargets[i][0] = m_TextureTargets[i][1]; m_TextureTargets[i][1] = Temp; } //*/ ////////////////////////////////////////////////////////////////////////// // 4] Copy target to staging for CPU readback and update the resulting bitmaps ImagePanel[] ImagePanels = new ImagePanel[3] { imagePanelResult0, imagePanelResult1, imagePanelResult2, }; for ( int i=0; i < 3; i++ ) { if ( m_imageResults[i] != null ) m_imageResults[i].Dispose(); // m_BitmapResults[i] = new ImageUtility.Bitmap( W, H, m_LinearProfile ); m_imageResults[i] = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.R8, m_sRGBProfile ); // Copy from GPU to CPU m_TextureTarget_CPU.CopyFrom( m_TextureTargets[i][0] ); float4[] scanline = new float4[W]; float4 gammaRGB = float4.Zero; 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 ( uint X=0; X < W; X++ ) { gammaRGB.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_sRGBProfile.LinearRGB2GammaRGB( gammaRGB, ref scanline[X] ); } m_imageResults[i].WriteScanline( Y, scanline ); } Pixels.Dispose(); m_TextureTarget_CPU.UnMap( 0, 0 ); // Assign result ImagePanels[i].Image = m_imageResults[i]; } ////////////////////////////////////////////////////////////////////////// // 5] Mix results MixResults( MixColor ); } catch ( Exception _e ) { MessageBox( "An error occurred during generation!\r\n\r\nDetails: ", _e ); } finally { groupBoxOptions.Enabled = true; } }