godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.14k stars 96 forks source link

Add a nearest-neighbor scaling option to Viewport's Scaling 3D Mode property #4697

Open Calinou opened 2 years ago

Calinou commented 2 years ago

Note: This proposal was discussed with reduz a few months ago and is probably fine to implement.

Related to https://github.com/godotengine/godot/issues/45081.

Describe the project you are working on

The Godot editor :slightly_smiling_face:

Describe the problem or limitation you are having in your project

Godot 4.0's Vulkan renderer allows for changing the 3D rendering resolution independently of the 2D rendering resolution, without using a separate Viewport for 3D rendering. This makes it easier to set up something like this, and also performs better compared to using two Viewports. However, only bilinear filtering and FSR 1.0 are currently available.

There are a few scenarios where nearest-neighbor filtering is desired:

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add a nearest-neighbor scaling option to Viewport's Scaling 3D Mode property.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Changing this sampler to use RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST instead of RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR does the trick in the Vulkan Clustered backend:

https://github.com/godotengine/godot/blob/4366f8bcd455714a5cd29374726d83b674ff0430/servers/rendering/renderer_rd/effects/tone_mapper.cpp#L135

image

However, doing so will break various effects, so we need to use a different sampler only for the one that actually draws the 3D rendering to the viewport.

This sampler should be adjustable via a new enum option in the rendering/scaling_3d/mode project setting and scaling_3d_mode Viewport property. I suggest adding a SCALING_3D_MODE_NEAREST option as the first option of the Viewport::Scaling3DMode enum. In the Project Settings, the option names would look like this:

(There is usually no performance difference between nearest-neighbor and bilinear filtering nowadays.)

If this enhancement will not be used often, can it be worked around with a few lines of script?

No, but you can use a second Viewport to display 2D elements at a higher resolution while still using nearest-neighbor filtering. However, by doing so, you lose on some performance compared to using a single Viewport for everything.

Is there a reason why this should be core and not an add-on in the asset library?

This is about improving performance without decreasing quality too much when FSR is too expensive on a given GPU.

jitspoe commented 2 weeks ago

Oops, looks like this issue already exists and I created a new one, so I closed that other one and I'll just comment here:

In Godot 3, you could set the scale on the viewport to get this effect, but in 4, the scale got moved to the viewport container, which I don't think is easily accessible (if it even exists) in Godot 4.

I'm building a retro FPS, so it would be nice to be able to scale the resolution down with unfiltered pixels to get that chunky retro look. Also, it seems the game runs poorly at 4K resolution, so that's another reason I'd like to scale it down.

jotson commented 1 week ago

@Calinou I've been watching this issue for a while now and note that the PR's been waiting for review since May. It seems like a review is the only thing holding it up. Is there anything we can do to help get this one over the finish line?

Calinou commented 1 week ago

@Calinou I've been watching this issue for a while now and note that the PR's been waiting for review since May. It seems like a review is the only thing holding it up. Is there anything we can do to help get this one over the finish line?

The code is complete on my end; it just needs a rendering maintainer to review it. GodotCon is happening this week, so maintainers are busy and can't look at PRs.