private void ApplyBilateralFiltering(RendererManaged.Texture2D _Source, RendererManaged.Texture2D _Target, float _BilateralRadius, float _BilateralTolerance, bool _Wrap, int _ProgressBarMax) { _Source.SetCS(0); _Target.SetCSUAV(0); // m_CB_Filter.m.Radius = _BilateralRadius; // m_CB_Filter.m.Tolerance = _BilateralTolerance; m_CB_Filter.m.Sigma_Radius = (float)(-0.5 * Math.Pow(_BilateralRadius / 3.0f, -2.0)); m_CB_Filter.m.Sigma_Tolerance = _BilateralTolerance > 0.0f ? (float)(-0.5 * Math.Pow(_BilateralTolerance, -2.0)) : -1e6f; m_CB_Filter.m.Tile = (uint)(_Wrap ? 1 : 0); m_CS_BilateralFilter.Use(); int h = Math.Max(1, MAX_LINES * 1024 / W); int CallsCount = (int)Math.Ceiling((float)H / h); for (int i = 0; i < CallsCount; i++) { m_CB_Filter.m.Y0 = (UInt32)(i * h); m_CB_Filter.UpdateData(); m_CS_BilateralFilter.Dispatch(W, h, 1); m_Device.Present(true); progressBar.Value = (int)(0.01f * (0 + _ProgressBarMax * (i + 1) / CallsCount) * progressBar.Maximum); // for ( int a=0; a < 10; a++ ) Application.DoEvents(); } // Single gulp (crashes the driver on large images!) // m_CS_BilateralFilter.Dispatch( W, H, 1 ); _Target.RemoveFromLastAssignedSlotUAV(); // So we can use it as input for next stage }
private void Generate() { try { panelParameters.Enabled = false; ////////////////////////////////////////////////////////////////////////// // 1] Apply bilateral filtering to the input texture as a pre-process ApplyBilateralFiltering(m_TextureSource, m_TextureTarget0, floatTrackbarControlBilateralRadius.Value, floatTrackbarControlBilateralTolerance.Value, checkBoxWrap.Checked, BILATERAL_PROGRESS); ////////////////////////////////////////////////////////////////////////// // 2] Compute directional occlusion m_TextureTarget1.RemoveFromLastAssignedSlots(); // Prepare computation parameters m_TextureTarget0.SetCS(0); m_TextureTarget1.SetCSUAV(0); m_SB_Rays.SetInput(1); m_TextureSourceNormal.SetCS(2); 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!"); } int h = Math.Max(1, MAX_LINES * 1024 / W); int CallsCount = (int)Math.Ceiling((float)H / h); for (int i = 0; i < CallsCount; i++) { m_CB_Input.m.Y0 = (UInt32)(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); ImageUtility.ColorProfile Profile = m_ProfilesRGB; // AO maps are sRGB! (although strange, that's certainly to have more range in dark values) if (m_BitmapResult != null) { m_BitmapResult.Dispose(); } m_BitmapResult = null; m_BitmapResult = new ImageUtility.Bitmap(W, H, Profile); m_BitmapResult.HasAlpha = false; RendererManaged.PixelsBuffer Pixels = m_TextureTarget_CPU.Map(0, 0); using (System.IO.BinaryReader R = Pixels.OpenStreamRead()) for (int Y = 0; Y < H; Y++) { R.BaseStream.Position = Y * Pixels.RowPitch; for (int X = 0; X < W; X++) { float AO = R.ReadSingle(); // Linear value ImageUtility.float4 Color = new ImageUtility.float4(AO, AO, AO, AO); Color = Profile.RGB2XYZ(Color); // Now sRGB value, converted as XYZ m_BitmapResult.ContentXYZ[X, Y] = Color; } } Pixels.Dispose(); m_TextureTarget_CPU.UnMap(0, 0); // Assign result viewportPanelResult.Image = m_BitmapResult; } catch (Exception _e) { MessageBox("An error occurred during generation!\r\n\r\nDetails: ", _e); } finally { panelParameters.Enabled = true; } }