WPF 2D in 3D view Animations : Performance issue - c#

I've put a TextBlock in a 3D panel (Planerator) and I used a Storyboard to animate it. (as crawl text)
When the field of view is 1 everything works fine, But if I set the field of view to more than 50 the frame rate will drop sharply and rendering will be choppy.
I used theCompositionTarget.rendering.
Please see the following images:
I need to 2D animations in 3d view with good performance.
Please tell me how can I solve this problem? Should I leave WPF and go to the DirectX?
UPDATE 1 :
I just want to move ONE 2Dtext in 3D space , but the performance is poor.(rendering isn't smooth it is choppy)
This is a sample project.
UPDATE 2:
This is the sample project updated version based on cokeman19's answer. (the performance have been improved ~10 frames, But I need to perfect rendering)
UPDATE 3 :
Finally, I got an acceptable performance with the help of the cokeman19's answer and the contents of this page.

I'm not sure if it's just a byproduct of the sample app, but under Planerator.CreateVisualChild(), it doesn't seem to be necessary to set the GeometryModel3D.BackMaterial. For reference:
VisualBrush vb = new VisualBrush(_logicalChild);
SetCachingForObject(vb); // big perf wins by caching!!
Material backMaterial = new DiffuseMaterial(vb);
...
GeometryModel3D backModel = new GeometryModel3D() { ..., BackMaterial = backMaterial };
The BackMaterial is a VisualBrush wrapper around the logical child, which doesn't belong to the visual tree, so rendering doesn't seem to make sense here. Moreover, the logical child (the LayoutInvalidationCatcher class), is in turn a wrapper around the visual child, which is already rendered (using _logicalChild) in setting frontModel.Visual.
Removing the code for the creation and setting of BackMaterial brings the FPS up to ~55.
In addition, if it's an option, setting the following brings the FPS back up to 60, with no noticeable degradation in quality.
RenderOptions.SetEdgeMode(_viewport3d, EdgeMode.Aliased);
Update:
The only other gain I was able to make was to set the CacheMode to BitmapCache, which may not be appliable for your needs.
frontModel.CacheMode = new BitmapCache(20) { EnableClearType = false };
Even on my slowest machine, this allowed for maximum FPS, but there are some drawbacks. Because the zoom level is so high on the text element, and this technique creates a picture to use in the animation (instead of animating the UIElement itself), I had to set the scale level to 20 before it became almost visually imperceptible. This of course has memory implications, as well.

Related

Dynamical rectangle plot c# wpf

I want to create a plot that dynamically displays active elements as rectangles. I have achieved a first version that is actually ok using OxyPlot.Annotations.RectangleAnnotation which I add to myPlotModel.Annotations, you can see it in the image hereafter:
Example of wanted display
The thing is that after a while, the amount of drawn rectangles make the update not smooth as I update the shown timewindow (which is set to 15 seconds). I have already set a maximum of drawn elements that suffice to cover the displayed window (i.e. the rectangles get removed as they are too far in the past), but the rendering is still jerky. I draw the rectangles by allocating them to an equal fraction of the Y-axis, that is the third one from the top gets:
rowNumber= 3.0
minimumY = maximalY - maximalY / totalElements * rowNumber
maximumY = maximalY - maximalY / totalElements * (rowNumber + 1.0)
And the Y-axis is hidden.
My question:
Is there a smarter way of creating such a display that would be less computationally heavy, and therefore allow a smoother update? I do not have to stick to OxyPlot, it is simply the easiest way that I found to obtain what I wanted.
Thanks for your answers!
Technically, the answer to your question is "Yes".
There are a number of ways to do this.
You could have a vertical itemscontrol that had an itemscontrol in it's template. That could have a canvas as it's itemspresenter and you could bind canvas.top and canvas.left to properties in it's content. Template each into a rectangle and bind height and width.
And of course do something about the scale on the bottom and the column of activity labels or whatever you want to call them there.
Unless you're using an absolutely ancient machine, that'd just fly.
It's quite a lot of work but it would probably be quicker to write that than to search through a load of alternative packages and decide which was optimal.

SwapChainPanel performance issues

I'm using a SwapChainPanel to render a control. The render method attaches to the CompositionTarget.Rendering event.
Also, RenderTarget.CreateCompatibleTarget is called to create an offscreen target. The compatibleTarget.Bitmap property is called to create a cached bitmap that can be blitted onscreen.
During each frame:
BeginDrawing() is called on the onscreen target.
If the scene has been invalidated by program logic, it is redrawn to the offscreen target.
The onscreen target is cleared using the background color. Without this, successive frames are somehow blended into each other.
The offscreen bitmap (cached above) is drawn onto the onscreen target using onscreenTarget.DrawBitmap(cachedBitmap), with opacity set to 1.
onScreenTarget.Flush() is called to flush the contents.
EndDrawing() is called on the onscreen target.
I find that this gives a very low frame rate.
Comparison with WindowRenderTarget
For comparison, I tested the exact same scene code in a WinForms app using a WindowRenderTarget. (SharpDX makes this possible since it works on UWP as well as desktop.) This gives a much higher frame rate, and zero steady-state CPU consumption.
Questions:
Why does SwapChainPanel produce such a low frame rate compared to WindowRenderTarget?
Why is it necessary to clear the onscreen target each frame before drawing the bitmap in step 4 even when the opacity is 1?
Can I avoid steps 1-6 if nothing has changed? This consumes around 7% CPU.
I don't think there should be too much performance difference between SwapChainPanel & WindowRenderTarget, because both of them are almost directly based on DirectX components. You could compare their settings to investigate the performance differences: Is the SwapChainPanel related with D2D device? Any differences among the configuration of devicecontext, swapchain description, and WindowRenderTarget's renderTargetProperty; Are there any difference between the bitmap processing methods?
THe opacity is set for the image you are drawing. However, the clear() if for the overall rendering view.
When you mean "if nothing changed", I supposed you mean you have nothing to draw. Then of course you can do nothing. Otherwise, the step from 1 to 6 are necessary.
Besides, you can find a good documented SwapChainPanel example here. Some settings in this example are for performance improving.

WPF Performance with text

I am creating a WPF application with a Viewport3D and inside the viewport I have meshes with text on them. The text is different for each of the mesh. (This means that I can have a single reference for a material for the regular meshes, but for the text I need to create different materials every time.)
I have also froze all the regular meshes since they are static.
However I can create any number of meshes, with a SolidColorBrush, that I want and the performance stays stable. (I have tried up to about 700 - 800 meshes)
However if I implement the text meshes the performance drops drastically. For example when I have around 200 regular Meshes and 200 text Meshes, the performance is very bad.
I have tried two different ways to render text;
- I have tried rendering text as a Viewport2DVisual3D. (However I presume this is a terrible way, since it means in my prior example there are 200 viewports additional to the Viewport3D itself.)
- I have tried rendering text as a GeometryModel3D, so the creation is the same as the regular brushes. However the material consists of a VisualBrush instead of a SolidColorBrush. (This does enhance the performance quite a bit, but still not perfect)
Does anyone have solutions to further enhance my performance with rendering text, so that I can render many more?
(I already followed most of the performance guidelines on the following site:
https://msdn.microsoft.com/en-us/library/bb613553%28v=vs.110%29.aspx)
#edit:
I have found that if I do the following with a visualbrush:
VisualBrush v = new VisualBrush(Text.createCubeStackText(text1));
RenderOptions.SetCachingHint(v, CachingHint.Cache);
viewport.Material = new DiffuseMaterial(v);
It improves the performance really much. I have tried, and can now render 700 regular meshes and 300 text meshes without any performance problems. Performance starts to drop with 550 text meshes and 550 regular meshes.
(I would still like any other suggestion though.)
Text in 3D can be very slow due to the tessellation that is needed to render the text. You might want to consider:
Remove the 3D rendering of text by overlaying the 3DViewport with a canvas and calculate the proper location of the text and render the text as a 2D overlay. You could even change the font size dependent on the Z value of the text's position
Render the text to a (transparent) bitmap and add the text as a texture to a billboard in the 3D scene
Use IsHitTestVisible=false to click-through the overlay and project the 3D position of the text to the canvas by using this: Projecting a 3D point to a 2D screen coordinate

More than 2 millions rectangles in a WPF canvas

I am creating a custom control for semiconductor wafermap
Each of those small rectangle need to satisfy following requirements;
1) Tooltip to show the index
2) clickable to include or exclude from the wafermap definition.
no of dies in the wafermap may cross 2 millions in the case of 1400 x 1450 dies.
at certain point i need to show all the dies in a window (most of the clicking will happen in zoomed view).
Currently I am adding each die separately using Rectangle shape and store the coordinate information (index like (10,10)) for the tooltip as an attached property.
I use different style to each die; depending on certain calculation and position of the die.
DieStyle1 = new Style { TargetType = typeof(Rectangle) };
DieStyle1.Setters.Add(new Setter(Shape.FillProperty, Brushes.MediumSlateBlue));
DieStyle1.Setters.Add(new Setter(Shape.StrokeProperty, Brushes.White));
DieStyle1.Setters.Add(new EventSetter(MouseDownEvent, new MouseButtonEventHandler(DieStyle1_MouseDown)));
this approach is slow and use high memory too. so suggest a better way to achieve this in WPF?
In creating a designer for christmas tree lights, I ran into the same problem. Using UIElement or Shapes is way too slow when you get to 100+ items. The best approach to handle a very large number of items entails using double-buffering with your own managed buffer of the image and a structure to handle the clicks. I have posted my project which should give you a good start. It can be obtained at:
http://sourceforge.net/projects/xlightsdesigner/
You are interested in the Controls\ChannelitemsCanvas.cs. It can be modified to suit your needs and uses a quad-tree to store the rectangles so that click events can be quickly determined.

WPF canvas performance- children.add called many times

I'm drawing a lot of lines on a long canvas (think stripchart) and have it tuned fairly well for performance, using the low-level geometry classes and freezing them, etc. This improved performance dramatically, but it still takes a few seconds to load a few thousand items into the canvas. I ran a performance analysis on the application, and it looks like a big percentage of the time is taken by each call to canvas.children.add(). I've read that this should be a lightweight call, and since I'm calling it numerous times in one method, it shouldn't be trying to do anything heavy inbetween... Could there possibly be any other reason this might be taking so much time? And any way I might speed it up?
The performance is not terrible, but I fear it could become more of a problem later when I need to deal with larger sets of data.
Just for reference, it looks like it is called 1400 times in this sample, and it taking almost 3 seconds of CPU time on a modern/fast laptop.
The canvas is contained in a hierachy of other controls though, so I'm curious if they might be contributing to this.
Extra note: I'm also not setting a specific height on the canvas, as it is set to fill the grid parent container. Could this be a source of the problems?
Main problem is that Children.Add is always a slow operation, even if you use StreamGeometry objects. I faced the same problem recently and concluded the following:
If you put a bunch of objects into a new canvas and nest it into the main canvas, the performance of the addition operation will be increased dramatically.
So, instead of adding 1400 elements, put 200 elements in 7 canvases and add those 7 canvases to the main canvas.
Since all objects now belong to different canvases, you will need to adjust your app a bit, but this would be a less drastical solution than moving to an alternative solution like DrawingVisual
Just to add about the hierarchy of controls the canvas is within, and the height of the canvas:
the Canvas always takes as much space as its given, and no matter what children u add to it - it NEVER triggers a new Measuer/Arrange passes on its parents. therefor whatever u do inside a canvas could never affect the visual tree it is contained in.
To sum it up - the problem cannot come from there, and the suggestion about the StreamGeomatry is exactly right- this is what causing u the performance issues, and switching to streamgeormatry would solve it.
I would suggest that you draw your shapes directly into an image instead of adding them as children.
Rendering children has a HUGE overhead (as you can see).
There's a similar question with a reference to some helpful articles:
How to draw line of ten thousands of points with WPF within 0.5 second?

Categories