-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add View Bobbing to Camera #665
base: master
Are you sure you want to change the base?
Conversation
I think it feels kind of weird, but I might be biased since I've played this game without any view bobbing for a while. Maybe someone else could take a look. Also make sure you fix the formatting. |
I will take a look |
Here's a few issues I found:
2024-09-03.15-30-45.mp42024-09-03.15-29-31.mp4 |
The teleport is caused by walking backwards. |
https://github.com/user-attachments/assets/8a83f2d8-bcdb-4d05-87f3-fb2bac8116d4 |
Thanks for the feedback. To address each of the original points:
|
Also, the sinking isn't caused by my changes. It also happens on commit before any of my changes. It also seems to only happen if you're looking below the horizon. |
Makes sense, I should have double checked that it didn't happen before. |
I'm not a fan of view bobbing in any game. I don't think it adds to immersion, and at worst it can cause motion sickness. Regardless, setting View Bobbing to 0 doesn't seem to actually turn it off. |
Fixed the issue with view bobbing 0 not turning it off. I'm a big fan of view bobbing personally. For me it feels massively jarring without it, but there's always the option of just defaulting it to be off if most people prefer that. |
Could make the block selection ray and camera separate. Like player separate from camera. Also, here is footage of Minecraft to prove that it's separate. 2024-09-03.23-17-53.mp4 |
Also, intensity of view bobbing should change with speed. More speed=more bobbing? Try it! |
I agree with @ikabod-kee that the focus point should be stable, and not move. Our eyes do this as well when we walk around. This should also be better for people with motion sickness. As for how this could be implemented: |
I would personally just separate the camera from the raycast. |
I've changed it so that the selected block isn't affected by the bobbing. Also, we no longer have view bobbing if you are stuck on a wall (view only bobs when you are actually moving, instead of it being based on input). The magnitude of the motion also increases slightly when moving faster as the bobbing motion felt weaker when sprinting compared to walking (guessing some kind of optical illusion or weird way our brains see motion). |
I will check it out! |
The bobbing effect seems very different now. It's as if you're walking with a limp now instead of step by step, which doesn't feel very satisfying. The bug fixes are very good though! |
Also agree that the current implementation feels weird. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change view bobbing to look more like walking, and preferably less roll.
Any chance you'll get back to this PR? @AlexDavies8 |
Yeah, sorry, was away for the weekend so couldn't work on it for a few days. I'm planning on taking a better look at reworking the movement to feel more natural tomorrow. :) |
Excellent :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While reviewing I found that many of your math expressions are unnecessarily complicated and could be simplified by applying some trigonometric identities.
Additionally one thing I would like you to think about: You have set a limit of 1.2 to bobMag.
This seems like it would cause further problems down the line. In the game I think it would be nice to have variable player hitboxes. Because of that I would like to have a generic limit to bobMag that guarantees that the camera won't ever go outside of the players bounding box.
@@ -556,7 +569,7 @@ pub const MenuBackGround = struct { | |||
// Draw to frame buffer. | |||
buffer.bind(); | |||
c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT); | |||
main.renderer.render(game.Player.getEyePosBlocking()); | |||
main.renderer.render(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that your method will now always apply bobbing to any render call.
This call however requires a stable camera, otherwise the recorded background image will contain seems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not quite sure what you mean here in terms of background seams, but yes, view bobbing will apply to all render calls that also render the world, although shouldn't happen on the title screen as that's a different code path. The only thing I can think that could be done differently would be to let the camera store its own position, so no player-related data needs to be passed to the renderer, and then handle the special case of the block selection somehow as we don't want to have view bobbing affect it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, decoupling the player and the camera position might be a good idea generally, as it would allow for third person/spectator and other camera effects to be handled in some update loop instead of directly in the rendering code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, decoupling the player and the camera position might be a good idea generally, as it would allow for third person/spectator and other camera effects to be handled in some update loop instead of directly in the rendering code.
Hard agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not quite sure what you mean here in terms of background seams
If you press Ctrl+print screen, then the game records a background image at your location. This is done by rendering the screen 4 times with a 90° angle in between. If your camera is angled from view bobbing, then this means that these 4 images are rotated, and don't fit together seamlessly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh and also please fix the merge conflict. |
It's clamped to be equal (roughly) to the magnitude caused by sprinting (just realised this is actually the wrong number, is fixed now), so going faster won't cause the camera to freak out. However, even at max view bobbing strength, it would only risk exiting the bounds if it was clamped at something pretty high like 4. I could probably enforce the limit earlier on, though, so it's clearer why it exists. It shouldn't be hard to scale it by the size of the player's hitbox either - the height would probably be best. |
Addressed feedback as much as I can without decoupling the camera position from player position. |
src/renderer.zig
Outdated
@@ -199,9 +212,9 @@ pub fn renderWorld(world: *World, ambientLight: Vec3f, skyColor: Vec3f, playerPo | |||
const meshes = mesh_storage.updateAndGetRenderChunks(world.conn, playerPos, settings.renderDistance); | |||
|
|||
gpu_performance_measuring.startQuery(.chunk_rendering_preparation); | |||
const direction = crosshairDirection(game.camera.viewMatrix, lastFov, lastWidth, lastHeight); | |||
const direction = crosshairDirection(baseViewMatrix, lastFov, lastWidth, lastHeight); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we are using crosshairDirection
instead of just game.camera.direction
? game.camera.direction
seems to do the same without having to extract the direction from the view matrix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#323
Try moving the crosshair in menu mode. Check if block selection is still accurate after removing this code.
Finally got around to decoupling the camera from the player. It turned out to not be that much work. I've also moved the camera to it's own file and put the viewbobbing in there instead of inside of the Player struct to keep it cleaner. In the future, the logic for third person/first person camera control, or camera shake (such as on taking damage or maybe is there's some kind of explosion) could also go in this file. To me this feels a lot easier to work with. It might also be good to redo some of the block selection stuff, as it seems like we are selecting the block during rendering and then reusing that result to place/remove blocks. To me, that is game logic, and should be done before rendering inside of the update loop, and then the renderer doesn't need to update the selected block itself. I haven't done that here, but I have swapped over to using |
Legend! Hope this PR can get concluded :) |
Also I think the crosshair was a seperate thing because the crosshair is movable (for some reason?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's difficult to review this PR due to all the unintentional formatting changes. Please revert them.
Also again please fix the merge conflicts.
src/game.zig
Outdated
// Maximum magnitude when sprinting (2x walking speed) | ||
Player.bobMag = @sqrt(@min(Player.bobVel, 2)) * settings.viewBobStrength; | ||
// Maximum magnitude when sprinting (2x walking speed). Magnitude is scaled by player bounding box height | ||
Player.bobMag = @sqrt(@min(Player.bobVel, 2)) * settings.viewBobStrength * Player.outerBoundingBoxExtent[2]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not that simple, the camera is not at the center of the bounding box, it can be anywhere inside the eyeBox.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still confused about what you mean about the eyeBox in relation to view bobbing. Scaling by the bounding box height should scale the view bobbing by player height, so scaling the player up or down should cause the view bobbing to appear the same relative to the player's size. Is there a plan to have characters with tiny legs and a huge hat or something, where the eyes and view bobbing should be ow but the bounding box tall?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scaling the bobbing by player height is fine, but
Let's say you sprint jump through a narrow tunnel.
I need you to guarantee that under no circumstances the camera will clip into the terrain.
The camera can be anywhere inside the eyeBox The eyeBox should always be smaller than the collision box. But your code adds a value to that cameraPosition, so you might push it outside the eyeBox.
Please ensure that the resulting position is never outside the collision box, which could make it clip into the terrain. It probably shouldn't even get too close to the collision box, because OpenGL doesn't render triangles at depth 0.
Now you have probably tested this scenario and everything works fine, but all these parameters, like the hitboxes and how often the camera actually gets close to the bounds of the eyeBox, may change.
@@ -556,7 +569,7 @@ pub const MenuBackGround = struct { | |||
// Draw to frame buffer. | |||
buffer.bind(); | |||
c.glClear(c.GL_DEPTH_BUFFER_BIT | c.GL_STENCIL_BUFFER_BIT | c.GL_COLOR_BUFFER_BIT); | |||
main.renderer.render(game.Player.getEyePosBlocking()); | |||
main.renderer.render(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not quite sure what you mean here in terms of background seams
If you press Ctrl+print screen, then the game records a background image at your location. This is done by rendering the screen 4 times with a 90° angle in between. If your camera is angled from view bobbing, then this means that these 4 images are rotated, and don't fit together seamlessly.
Fixed the formatting stuff, think I did it by accident while merging. The background image isn't affected by view bobbing as the camera now has the view bobbing applied in the renderer. At the moment this is essentially hard-coded to the renderer, but if there are more effects in the future such as camera shaking such as on taking damage or explosions etc, it might be better to move this to some kind of function on the camera such as |
The background image is still broken, and there's also ensuring that the camera stays inside the bounding box.
We definitely want the camera physics to affect block selection, otherwise it would be completely broken when climbing stairs, the camera physics is important for smoothing out movement. |
View bobbing will scale down as it gets closer to eyeBox edges, and will hard clamp if needed.
Finally got around to fixing the last little bits. The view bobbing shouldn't be able to escape the eyeBox anymore. It will scale down the view bobbing if the camera is already near the edge (such as due to camera physics), and will clamp the final view bobbing to always remain inside eyeBox to catch the case where the view bobbing alone would be outside the eyeBox. |
It appears to be broken: video-2024-09-26_19.23.09.mp4 |
Oops 😅, forgot to reset view bobbing strength after testing out the eyeBox clamping. Should be fixed now. |
Please do more thorough testing in the future. Stairs and stepping in general is broken: video-2024-09-27_20.15.50.mp4 |
View bobbing can make movement feel more natural. I've added view bobbing to the camera while walking on the ground. The strength of it can be changed in the graphics section of the settings menu.