Skip to content
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

Vulkan: CameraAttributes depth of field amount is resolution-dependent #56911

Open
Tracked by #65116
Calinou opened this issue Jan 18, 2022 · 3 comments
Open
Tracked by #65116

Vulkan: CameraAttributes depth of field amount is resolution-dependent #56911

Calinou opened this issue Jan 18, 2022 · 3 comments

Comments

@Calinou
Copy link
Member

Calinou commented Jan 18, 2022

Related to #54518.

Godot version

4.0.dev (ce6de71)

System information

Fedora 34, GeForce GTX 1080 (NVIDIA 495.46)

Issue description

The DoF effect's amount is resolution-dependent. This means the depth of field will appear to be stronger as the rendering resolution decreases. This happens regardless of the depth of field bokeh shape and quality selected in the Project Settings.

This means the rendering will change in unintended ways depending on the user's monitor resolution. Also, if we implement dynamic resolution scaling and FSR in the future, we need to make sure every effect is as a resolution-independent as possible.

depth-of-field-resolution-dependent.mp4

Steps to reproduce

  • Add a Camera3D node with a CameraEffects resource.
  • Enable Dof Far and Dof Near on the CameraEffects resource.
  • Create a MeshInstance with a SphereMesh. Move the SphereMesh away from the camera so the depth of field can be visible from the Camera3D preview.
  • Add a StandardMaterial3D on the SphereMesh, with a bright albedo and/or emission value (to make depth of field visible).
  • Decrease the 3D resolution scale factor at run-time using get_viewport().scale_3d -= 0.1.

Minimal reproduction project

https://github.com/Calinou/test_fxaa_supersample_master
Press the Up / Down arrow keys to adjust the 3D rendering scale. When doing so, watch the depth of field become stronger as the resolution decreases.

@ghost
Copy link

ghost commented Jan 22, 2022

Since one would probably want to compare the rendering resolution to the viewport's resolution to fix this issue, any clue why render_width = width & render_height = height when using 3d bilinear scaling?

render_width = width;
render_height = height;

I tried this:

	width = p_viewport->size.width;
	height = p_viewport->size.height;
	render_width = CLAMP(p_viewport->size.width * scaling_3d_scale, 1, 16384);
	render_height = CLAMP(p_viewport->size.height * scaling_3d_scale, 1, 16384);

but it breaks rendering for me (stuff looks untextured). Probably other stuff needs changing but I'm clueless.

@Calinou
Copy link
Member Author

Calinou commented Jan 22, 2022

Since one would probably want to compare the rendering resolution to the viewport's resolution to fix this issue,

That is one way to resolve this issue, but I'm not sure if it's ideal because it does not resolve the use case where the user is resizing the project window (or changing their monitor resolution). On monitors with different resolutions, users will be getting different amounts of depth of field, which makes for an inconsistent experience.

Instead, I think we should compare the current value against a "reference" viewport height (maybe 1080 pixels or so) and use this as a multiplier or divisor for the depth of field amount. This will work well when using the default camera aspect mode (Keep Height), but it won't work when using the Keep Width camera aspect mode. To handle the Keep Width camera aspect mode, the reference viewport width would have to be used instead (maybe 1920 pixels or so).

Using the project window size configured in the project settings (1024×600 by default) could be an alternative to hardcoding a reference resolution. The downside is that it will cause the depth of field amount to change unexpectedly if you adjust this default project window size in the future.

To give an example:

  • We decide to hardcode a reference resolution of 1920×1080. In the example below, we'll assume the camera is using the Keep Height aspect mode, which means only the viewport height is taken into account for depth of field factor calculations. This ensures multiple aspect ratios are supported seamlessly, without the developer having to do anything.
  • User 1 plays the game in a 1920×1080 window at 100% render scale. Viewport resolution is 1920×1080. They get the original depth of field amount.
  • User 2 plays the game in a 1920×1080 window at 50% render scale. Viewport resolution is 960×540. They get an halved depth of field amount, so that the amount of blur looks identical to what it looks like in a 1920×1080 viewport.
  • User 3 plays the game in a 3840×2160 window at 100% render scale. Viewport resolution is 3840×2160. They get a doubled depth of field amount, so that the amount of blur looks identical to what it looks like in a 1920×1080 viewport.

@ghost
Copy link

ghost commented Jan 22, 2022

You're right about using a reference resolution for scale. Good catch!

@clayjohn clayjohn modified the milestones: 4.0, 4.x Feb 23, 2023
@Calinou Calinou changed the title Vulkan: CameraEffects depth of field amount is resolution-dependent Vulkan: CameraAttributes depth of field amount is resolution-dependent May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants