How do I GET the screen refresh Hz in C# UWP? - c#

Does anyone know how to get the monitor Screen Refresh Rate (Hz) in a C# UWP app?
...that will be valid to publish to the Microsoft Store (ie, no HWNDs?).
The reason for the question is that when writing a game, it's good to base movement on elapsed time between updates. To get smooth frame timing it's useful to know how often we're drawing to the screen and so time our frame updates to be in sync with that.
For example, if you know the Refresh Rate is 120Hz then it's optimal to set a fixed game time:
TargetElapsedTime = TimeSpan.FromTicks((long)(TimeSpan.TicksPerSecond / 120L));
Which results in consistent frame timing and smooth motion.

Unbound the process timing using IsFixedTimeStep = false; in Game1.
The default of graphics.SynchronizeWithVerticalRetrace = true; should cap the FPS to match the refresh rate.
It should work according to the source code comments:
The first argument instructs DXGI to block until VSync, putting the application to sleep until the next VSync. This ensures we don't waste any cycles rendering frames that will never be displayed to the screen.
If you still need the actual refresh rate in Hz, calculate the average of (1000/gameTime.ElapsedTime.TotalMilliseconds) in update.

Related

Animation clip taking unexpectedly long time to finish

I am trying to solve this problem which is really surprise for me. I have imported some max animation (different train object Animations). I am firing Below method on GUI click which attached to all train object. This code simultaneously run/fire on different trains Object. Some trains work correctly and animation complete timely while some take long time for animation completion.
public void HourSwitcher(string playShunt)
{
gameObject.GetComponent<Animation>().Play(playShunt);
gameObject.GetComponent<Animation>()[playShunt].speed = 20f;
}
I have also attach my debug logs. As u can see in log 1 image
train12 to 16 animation running running while the time 0(surprisingly).
and in image two train 17 worked correcly but train20-21 running and running
Refer to my this question and answer. It were much disappointing that no one able to identify the problem (maybe lack of much attention to this question). After working 4/5 days finally I got this.
It were mainly animation Culling type Problem. *For future use and help for the beginners like myself I am going to answer my own question.
Answer:
My animation culling type were selected to BasedOnRenderers which means that 'Animation is disabled when renderers are not visible'. i.e., my code were showing me that animation is playing but nothing acutal happening in my scene as my animation were far from camera view.
I solved this problem by selecting animation culling type to AlwaysAnimate (refer to this). It means that 'object is animated even when offscreen'.
My some animation were working correctly because they were coming under the view of camera while some animations were not working (while code showing that it is in play mode) and playing continuously/taking long time because they were far from my camera view.
Hope it will help others
Refer to this Questions also which I were asked (tightly associated with this problem):
Animation unexpected behaviour - Why animation becomes complete If my camera walk through the scene
Does culling affect animation.

Wpf:MediaElement pause & play again disables speed ratio

I have a mediaElement. I change its speedratio according to my will 1x,2x,3x... It works the very first time but when I pause and play again it simply does not work. It starts playing in 1x speed. Is there anything I am missing?
I have encountered the same problem.
After some experimentation I found setting the SpeedRatio back to 1.0 before calling Play() again then waiting for the Position to change (typically using a timer) and setting SpeedRatio back to the old value seems to work.

Set position in mediaElement (ScrubbingEnabled alternative in WP8.1)

I am trying to set position of video while video is paused.
In WPF it is simple with ScrubbingEnabled
property.
But there is nothing like this for windows phone.
So I use:
_mediaElement.Play();
_mediaElement.Position += new TimeSpan(0,0,0,0,50);//move video 50 milisecond forward
_mediaElement.Pause();
It is "working", but when I am trying to go (about)5 miliseconds back, it is moving forward and it is not clear solution...
How can I replace ScrubbingEnabled property on windows phone?
Edit
Code for 5ms back:
_mediaElement.Play();
_mediaElement.Position -= new TimeSpan(0,0,0,0,5);
_mediaElement.Pause();
Even assuming that your video is running at 60 frames per second, there's only one frame every 16.67 ms. So to move 5 ms should probably do nothing in many cases.
That would also explain why when you ask it to move 50 ms, it doesn't move by that exact amount, but rather goes to the time of the closest frame.
(if you move position by only a few frames, due to how digital video compression works it might not work as you expect either)
Ok. This is not exactly the answer, but today WP8.1 is obsolete and setting position with mediaElement on Windows 10 work pretty fine without Play-Pause hack.
So:
_mediaElement.Position -= new TimeSpan(0,0,0,0,33);
is moving video 1 frame back (30 FPS video), and
_mediaElement.Position -= new TimeSpan(0,0,0,0,5);
is not moving anywhere.
One interesting thing:
To move 1 frame you need to change position at least one half of frame time.
_mediaElement.Position -= new TimeSpan(0,0,0,0,16);//not moving
_mediaElement.Position -= new TimeSpan(0,0,0,0,17);//moving every 2nd "click"
Frame time for 30 FPS video is 1000/30 = 33.333 ms

XNA performance on WP7

I'm trying to get the frame rate of my XNA game on WP7 up to 60 fps. It appears to be locked at around the 30fps mark. I've tried the change of but makes little difference.
PresentationParameters.PresentationInterval = PresentInterval.One
Any thoughts?
You can change the fixed time step that XNA defaults to:
// 166666 ticks is 16.6ms, which is 60hz
game.TargetElapsedTime = new TimeSpan(166666) // 'game' refers to your instance of XNA.Game
Here's documentation on the feature:
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.targetelapsedtime.aspx
Or, if you just want to turn off the fixed timestep, try setting fixed time step to false:
game.IsFixedTimeStep = false // 'game' refers to your instance of XNA.Game
Here's documentation on the feature:
http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.isfixedtimestep.aspx
This is set to true by default in XNA, so you will see a fixed time-step until you set it otherwise.
Of course there is also the chance that performance problems are keeping you around 30 fps. You could be seeing V-sync holding up the frame to sync with the phone's display, either the display may be limited to 30 fps (not likely), or if your game is taking longer than 16.6ms per frame, the V-sync might be holding it to 30 fps to keep it in sync with the display. At 30 fps your game would render every other frame that the display refreshes. But if V-sync was disabled and your game was running at something like 50 fps, your game would only partially be done rendering by the time the display refreshed, and you'd end up with screen tearing.

How can I get rid of jerkiness in WinForms scrolling animation?

I'm writing a simple control in C# that works like a picture box, except the image is constantly scrolling upwards (and re-appearing from the bottom). The animation effect is driven by a timer (System.Threading.Timer) which copies from the cached image (in two parts) to a hidden buffer, which is then drawn to the control's surface in its Paint event.
The problem is that this scrolling animation effect is slightly jerky when run at a high frame rate of 20+ frames per second (at lower frame rates the effect is too small to be perceived). I suspect that this jerkiness is because the animation is not synchronized in any way with my monitor's refresh rate, which means that each frame stays on the screen for a variable length of time instead of for exactly 25 milliseconds.
Is there any way I can get this animation to scroll smoothly?
You can download a sample application here (run it and click "start"), and the source code is here. It doesn't look horribly jerky, but if you look at it closely you can see the hiccups.
WARNING: this animation produces a pretty weird optical illusion effect which might make you a little sick. If you watch it for awhile and then turn it off, it will look as if your screen is stretching itself vertically.
UPDATE: as an experiment, I tried creating an AVI file with my scrolling bitmaps. The result was less jerky than my WinForms animation, but still unacceptable (and it still made me sick to my stomach to watch it for too long). I think I'm running into a fundamental problem of not being synced with the refresh rate, so I may have to stick to making people sick with my looks and personality.
You would need to wait for a VSYNC before you draw the buffered image.
There is a CodeProject article that suggests using a multimedia timer and DirectX' method IDirectDraw::GetScanLine().
I'm quite sure you can use that method via Managed DirectX from C#.
EDIT:
After some more research and googling I come to the conclusion that drawing via GDI doesn't happen in realtime and even if you're drawing in the exact right moment it might actually happen too late and you will have tearing.
So, with GDI this seems not to be possible.
(http://www.vcskicks.com/animated-windows-form.html)
This link has an animation and they explain the way they accomplish it. There is also a sample project that you can download to see it in action.
Use double buffering. Here are two articles: 1 2.
Another factor to ponder is that using a timer doesn't guarantee you to be called at exactly the right time. The correct way to do this is to look at the time passed since the last draw and calculate the correct distance to move smoothly.
I had a similar problem a couple of months ago, and solved them by switching to WPF. The animated control ran a lot smoother than with a standard timer-based solution and I didn't have to take care of synchronization any more.
You might want to give it a try.
You need to stop relying on the timer event firing exactly when you ask it to, and work out the time difference instead, and then work out the distance to move. This is what games, and WPF do, which is why they can achieve smooth scrolling.
Let's say you know you need to move 100 pixels in 1 second (to sync with the music), then you calculate the time since your last timer event was fired (let's say it was 20ms) and work out the distance to move as a fraction of the total (20 ms / 1000 ms * 100 pixels = 2 pixels).
Rough sample code (not tested):
Image image = Image.LoadFromFile(...);
DateTime lastEvent = DateTime.Now;
float x = 0, y = 0;
float dy = -100f; // distance to move per second
void Update(TimeSpan elapsed) {
y += (elapsed.TotalMilliseconds * dy / 1000f);
if (y <= -image.Height) y += image.Height;
}
void OnTimer(object sender, EventArgs e) {
TimeSpan elapsed = DateTime.Now.Subtract(lastEvent);
lastEvent = DateTime.Now;
Update(elapsed);
this.Refresh();
}
void OnPaint(object sender, PaintEventArgs e) {
e.Graphics.DrawImage(image, x, y);
e.Graphics.DrawImage(image, x, y + image.Height);
}
Some ideas (not all good!):
When using a threading timer, check that your rendering time is considerably less than one frame interval (from the sound of your program, you should be fine). If rendering takes longer than 1 frame, you will get re-entrant calls and will start rendering a new frame before you've finished the last. One solution to this is to register for only a single callback at startup. Then in your callback, set up a new callback (rather than just asking to be called repeatedly every n milliseconds). That way you can guarantee that you only schedule a new frame when you've finished rendering the current one.
Instead of using a thread timer, which will call you back after an indeterminate amount of time (the only guarantee is that it is greater than or equal to the interval you specified), run your animation on a separate thread and simply wait (busy wait loop or spinwait) until it is time for the next frame. You can use Thread.Sleep to sleep for shorter periods to avoid using 100% CPU or Thread.Sleep(0) simply to yield and get another timeslice as soon as possible. This will help you to get much more consistent frame intervals.
As mentioned above, use the time between frames to calculate the distance to scroll, so that the scroll speed is independent of the frame rate. But note that you will get temporal sampling/aliasing effects if you try to scroll by a non-pixel rate (e.g. if you need to scroll by 1.4 pixels in a frame, the best you can do is 1 pixel, which will give a 40% speed error). A workaround for this would be to use a larger offscreen bitmap for scrolling and then scale it down when blitting to screen, so you can effectively scroll by sub-pixel amounts.
Use a higher thread priority. (really nasty, but may help!)
Use something a bit more controllable (DirectX) rather than GDI for rendering. This can be set up to swap the offscreen buffer on a vsync. (I'm not sure if Forms' double buffering bothers with syncing)
I had the same problem before and found it to be a video card issue.
Are you sure your video card can handle it?
I modified your example to use a multimedia timer that has a precision down to 1 ms, and most of the jerkiness went away. However, there is still some little tearing left, depending on where exactly you drag the window vertically. If you want a complete and perfect solution, GDI/GDI+ is probably not your way, because (AFAIK) it gives you no control over vertical sync.
Well, if you wanted to run the timer at a lower speed, you can always change the ammount the image is scrolled in the view. This gives better preformance, but makes the effect look kinda jerky.
Just change the _T += 1; line to add the new step...
Actually, you could even add a property to the control to adjust the step ammount.

Categories