stride3d / stride

Stride (formerly Xenko), a free and open-source cross-platform C# game engine.
https://stride3d.net
MIT License
6.61k stars 953 forks source link

Screen Tearing In Window Mode #2216

Closed jhimes144 closed 7 months ago

jhimes144 commented 7 months ago

Release Type: Official Release

Version: 4.2.0.2122

Platform(s): Windows 11

Describe the bug When running the fps template in window mode, screen tearing occurs (tested on a 100hz monitor, and 60hz monitor)

Per @Doprez, I tried the following code:

            WindowMinimumUpdateRate.MinimumElapsedTime = TimeSpan.FromMilliseconds(100f / 60f);
            MinimizedMinimumUpdateRate.MinimumElapsedTime = TimeSpan.FromMilliseconds(100f / 60f);

I've also tried changing PresenterInterval options. Having two selected still creates screen tearing, but its more, how do I say... steppy.

To Reproduce Steps to reproduce the behavior:

  1. Create an empty project based off the FPS template.
  2. Create a TestGame with the following code
    public class TestGame : Game
    {
        protected override void BeginRun()
        {
            base.BeginRun();

            WindowMinimumUpdateRate.MinimumElapsedTime = TimeSpan.FromMilliseconds(1000f / 100f); // set to screen refresh rate
            MinimizedMinimumUpdateRate.MinimumElapsedTime = TimeSpan.FromMilliseconds(1000f / 100f); // set to screen refresh rate

            Window.IsBorderLess = true;
            Window.Position = new Stride.Core.Mathematics.Int2(0, 0);

            Settings.Configurations.Get<RenderingSettings>().DefaultBackBufferHeight = 1440; // set to screen res
            Settings.Configurations.Get<RenderingSettings>().DefaultBackBufferHeight = 3440; // set to screen res
        }
    }
  1. Observe screen tearing when running game.

Expected behavior No screen tearing occurs, like when in exclusive full screen.

Additional context I've also tried setting 0 for throttle limits on window update rate. I've also tried WindowMinimumUpdateRate.SetToPreciseAuto(), no dice.

Doprez commented 7 months ago

Oh, its it the bad jitter in the FPS tempalte? whenever you move around and look at something it looks like bad FPS?

jhimes144 commented 7 months ago

So I'm new to stride so I haven't use any other template, but yes - especially when you strafe right or left and move your mouse to keep looking at an object - you get horrible screen tearing. In fullscreen mode, you don't get it at all.

EDIT: Just pulled up the third person template - also get the screen tearing. Although, its less noticeable because of how the camera moves.

Doprez commented 7 months ago

Ok, assuming I understand what the problem is this time lol I have dealt with the same issue. It had to do with the Camera being directly attached in some way to the Physics body and updating its transforms based on that update interval.

The way I fixed it was the below steps:

What I had to do was create a SmoothFollowAndRotate script that just lerped between 2 entities at a certain speed.

[ComponentCategory("Utils")]
[DataContract("SmoothFollowAndRotate")]
public class SmoothFollowAndRotate : SyncScript
{
    public Entity EntityToFollow { get; set; }
    public float Speed { get; set; } = 1;

    public override void Update()
    {
        var deltaTime = (float)this.Game.UpdateTime.Elapsed.TotalSeconds;
        var currentPosition = Entity.Transform.Position;
        var currentRotation = Entity.Transform.Rotation;

        EntityToFollow.Transform.GetWorldTransformation(out var otherPosition, out var otherRotation, out var _);

        var newPosition = Vector3.Lerp(currentPosition, otherPosition, Speed * deltaTime);
        Entity.Transform.Position = newPosition;

        Quaternion.Slerp(ref currentRotation, ref otherRotation, Speed * deltaTime, out var newRotation);
        Entity.Transform.Rotation = newRotation;
    }
}

Then in your scene you have to unparent the camera from the player controller and add that smooth follow and rotate component to follow a new pivot point on your character controller. image

This will break things in certain scripts since they use direct references to a CameraComponent but I will list the fixes below.

PlayerInput.cs

change public CameraComponent Camera { get; set; } to public Entity Camera { get; set; }

Utils.cs

change CameraComponent camera to Entity camera, and change

camera.Update();
var inverseView = Matrix.Invert(camera.ViewMatrix);

to var inverseView = camera.Transform.WorldMatrix;

FpsCamera.cs

Remove


        /// <summary>
        /// Gets the camera component used to visualized the scene.
        /// </summary>
        private Entity Component;

and change

        private void UpdateViewMatrix()
        {
            var camera = Component;
            if (camera == null) return;
            var rotation = Quaternion.RotationYawPitchRoll(Yaw, Pitch, 0);

            Entity.Transform.Rotation = rotation;
        }

to

private void UpdateViewMatrix()
{
    var rotation = Quaternion.RotationYawPitchRoll(Yaw, Pitch, 0);

    Entity.Transform.Rotation = rotation;
}
jhimes144 commented 7 months ago

@Doprez

Thank you for all of this, looks like you accidently copied and paste twice here, mind if you correct it? I got the rest of the changes in.

and change

    private void UpdateViewMatrix()
    {
        var camera = Component;
        if (camera == null) return;
        var rotation = Quaternion.RotationYawPitchRoll(Yaw, Pitch, 0);

        Entity.Transform.Rotation = rotation;
    }

to

    private void UpdateViewMatrix()
    {
        var camera = Entity;
        if (camera == null) return;
        var rotation = Quaternion.RotationYawPitchRoll(Yaw, Pitch, 0);

        Entity.Transform.Rotation = rotation;

}

Doprez commented 7 months ago

Ah yep, fixed!

Also worth mentioning that my best speed for for the follow script is 25, seems to be the smoothest without falling behind.

jhimes144 commented 7 months ago

Whoa. Well, I think I definitely screwed it up somewhere because I'm getting wild behavior.

I'm going to come back tonight and just rewrite the camera and movement system, while taking in your smooth lerping technique into account. For me, I think the player control and camera should all be in one script. Thanks a ton for the help! If you have a sample project with these changes let me know as well.

Sounds like this is probably not a v-sync issue.

Doprez commented 7 months ago

Here is the project with the fixes included: https://github.com/Doprez/smooth-fps-template/tree/main

It also had a change with some light shafts that cause an initial lag on loading the game but it should clear up after 2-3 seconds.

jhimes144 commented 7 months ago

@Doprez You are a saint! That fixed it. It was a bit laggy at first, but then when I also set the MinimumElapsedTime to Zero - it became butter smooth, and the experience is now identical to fullscreen mode. This really should be the new FPS 1st person template too, its much much smoother.

Its full steam ahead for my wpf/avalonia overlay. I think I definitely will open source it. The other wpf/avalonia solutions involve the attempt of rendering the UI framework in Stride, mine just uses win32 apis to get it to work.

EDIT: The only thing not working in this code is that gun shots do not hit when you are moving the character, I'm sure i can figure out a fix to that though.

VaclavElias commented 7 months ago

@Doprez, do we need to document this?

Doprez commented 7 months ago

@Doprez, do we need to document this?

Probably wouldnt hurt, I know this isnt the first time I have seen someone with this issue and even when I first started this drove me nuts because I didnt know why lol.

VaclavElias commented 7 months ago

Let's do it. Do we have a relevant section in the manual? Should it go to UI section? Wouldn't you mind creating a PR, maybe just simply summarising the subject?

Doprez commented 7 months ago

Yep, I can take some time later to do this. I am not sure where would be the right spot though.. maybe Physics?

VaclavElias commented 7 months ago

Thank you. Let's put it under Physics. I will assist with the rest, I can check with others if it is the right location. Also, you can just dump content to the new docs page, and I can align and format further, just to save your time :)