private void RenderButton_OnClick(object sender, RoutedEventArgs e) { UpdateCamera(); var stopwatch = new Stopwatch(); stopwatch.Start(); BitmapWidth = (int)ImageBorder.ActualWidth; BitmapHeight = (int)ImageBorder.ActualHeight; _viewport3D.Width = BitmapWidth; _viewport3D.Height = BitmapHeight; _viewport3D.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); _viewport3D.Arrange(new Rect(0, 0, _viewport3D.DesiredSize.Width, _viewport3D.DesiredSize.Height)); _camera.Refresh(); Ab3d.Utilities.LinesUpdater.Instance.Refresh(); BitmapSource renderBitmap = _dxViewportView.RenderToBitmap(width: BitmapWidth, height: BitmapHeight, preferedMultisampling: 2, // when -1 is used, then the currently used multisampling is used dpiX: BitmapDpiX, // 96 is the default value and can be changed if needed dpiY: BitmapDpiY); // Display render time (note that the first time the scene is rendered the time is bigger because of additional initializations) stopwatch.Stop(); InfoTextBlock.Text = string.Format("Render time: {0:0.0}ms", stopwatch.Elapsed.TotalMilliseconds); if (_isFirstRender) { InfoTextBlock.Text += " (note: render time of the first image is longer then the time to render other images)"; _isFirstRender = false; } RenderedImage.Source = renderBitmap; //SaveBitmap(renderBitmap, @"c:\temp\DXEngineRender.png"); }
private void RenderButton_OnClick(object sender, RoutedEventArgs e) { // Update camera based on the HeadingSlider value UpdateCamera(); var stopwatch = new Stopwatch(); stopwatch.Start(); BitmapWidth = (int)ImageBorder.ActualWidth; BitmapHeight = (int)ImageBorder.ActualHeight; double dpiScaleX, dpiScaleY; DXView.GetDpiScale(this, out dpiScaleX, out dpiScaleY); double dpiX = 96.0 * dpiScaleX; // 96 is the default dpi value without any scaling double dpiY = 96.0 * dpiScaleY; // The following 6 lines are not needed because the DXViewportView is not shown: _viewport3D.Width = BitmapWidth; _viewport3D.Height = BitmapHeight; // Because DXViewportView is not actually show, we need to call Measure and Arrange _viewport3D.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); _viewport3D.Arrange(new Rect(0, 0, _viewport3D.DesiredSize.Width, _viewport3D.DesiredSize.Height)); // Update camera _camera.Refresh(); // Update 3D lines Ab3d.Utilities.LinesUpdater.Instance.Refresh(); int multiSamplingCount, superSamplingCount; GetAntiAliasingSettings(out multiSamplingCount, out superSamplingCount); var convertToNonPreMultipledAlpha = ConvertToNonPremultipliedAlphaCheckBox.IsChecked ?? false; if (ReuseWriteableBitmapCheckBox.IsChecked ?? false) { // Create only one instance of WriteableBitmap, then reuse it with other calls to RenderToBitmap if (_writeableBitmap == null) // we would also need to recreate the WriteableBitmap in case the size changes { int finalBitmapWidth = (int)(BitmapWidth * dpiScaleX); int finalBitmapHeight = (int)(BitmapHeight * dpiScaleY); // When using WriteableBitmap, the RenderToBitmap will use pre-multiplied alpha // or non pre-multiplied alpha based on the pixel format (Pbgra32 for pre-multiplied alpha). // // When the rendered image is shown in WPF, then it is recommended to use Pbgra32 (pre-multiplied alpha) // because this is also what is internally used by WPF. // // But when the image is saved to png image, then the image should be non pre-multiplied // because png does not support pre-multiplied image. var pixelFormat = convertToNonPreMultipledAlpha ? PixelFormats.Bgra32 : PixelFormats.Pbgra32; _writeableBitmap = new WriteableBitmap(finalBitmapWidth, finalBitmapHeight, 96, 96, pixelFormat, null); // always use 96 as dpi for WriteableBitmap otherwise the bitmap will be shown too small } _dxViewportView.RenderToBitmap(_writeableBitmap, multiSamplingCount, superSamplingCount); _renderBitmap = _writeableBitmap; } else { // When we do not need to reuse the WriteableBitmap, we can use the following RenderToBitmap method: _renderBitmap = _dxViewportView.RenderToBitmap(width: (int)(BitmapWidth * dpiScaleX), height: (int)(BitmapHeight * dpiScaleY), preferedMultisampling: multiSamplingCount, // when -1 is used, then the currently used multisampling is used supersamplingCount: superSamplingCount, dpiX: dpiX, dpiY: dpiY, convertToNonPreMultipledAlpha: convertToNonPreMultipledAlpha); // pixel format of the returned image will be Pbgra32 (when convertToNonPreMultipledAlpha is false) or Bgra32 when true. } // Display render time (note that the first time the scene is rendered the time is bigger because of additional initializations) stopwatch.Stop(); InfoTextBlock.Text = string.Format("Render time: {0:0.0}ms", stopwatch.Elapsed.TotalMilliseconds); if (_isFirstRender) { InfoTextBlock.Text += " (note: render time of the first image is longer then the time to render other images)"; _isFirstRender = false; } RenderedImage.Source = _renderBitmap; TipTextBlock.Visibility = Visibility.Collapsed; SaveButton.Visibility = Visibility.Visible; }