-
-
Notifications
You must be signed in to change notification settings - Fork 101
Description
Describe the project you are working on
Third-person, high-fidelity visuals 3d game.
Describe the problem or limitation you are having in your project
Godot doesn't have, and won't have for a long time, if ever, MRTs (Multiple Render Targets). Therefore, enable us to use the second best thing: 32-bit per component frame buffers.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
For starters, it is more efficient to use a single, 32-bit per component frame buffer than using two MRTs. With clever use of custom shaders, it is possible to pack and store more information than just colors inside buffers. 32-bit per component frame buffers are actually 128-bit data buffers. With them, it is be possible to implement advanced features in Godot, such as Motion Vectors for exemple, and thus implement advanced post process effects like TAA and #2933 without having to completely overhaul the underlying rendering backend, and distribute those as user-created add-ons.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
Currently, Godot 3.x only supports up to 16-bit per component frame buffers (GL_RGBA16F
, when the option use_hdr
in a Viewport
is enabled). This proposal aims to add optional 32-bit per component frame buffers (VK_FORMAT_R32G32B32A32_SFLOAT
for Vulkan, GL_RGBA32F
for GLES3) in order to circumvent the lack of MRTs (since enabling this rendermode is far less troublesome than fully implementing MRTs). Due to the nature of what I just said, this is a feature intended for advanced user only, and therefore must be an option in the project settings that must be opt-ed in. Then, the option to use 32-bit per component frame buffers will be available to be enabled on Viewport
s, just like the use_hdr
option.
Using reinterpret casts such as floatBitsToUint
/uintBitsToFloat
and bit manipulation in shaders, it is possible to pack information during the regular geometry rendering in a single pass. For example, Godot 4's DOF post process shader uses the alpha component to store the blur radius. With clever packing and bit manipulation, it is possible to store albedo, depth, normals and lights in a single 128-bit buffer, essentially creating a tiny deferred buffer in a forward renderer. Or, storing colors and motion vectors as the geometry gets rendered. The applications are quite endless.
For reference, I experimented packing colors and depth in a single buffer in Godot 3.x, by packing depth as a 24-bit value and 8-bit per component RGB (by transforming linear RGB to sRGB first), and then reading everything back with a single texture sample, unpacking, and finally enjoying depth in canvas_item
shaders. It works well, but then I lose HDR. My project needs HDR, so this isn't usable. Higher bit-depth frame buffers must be available for that. 16-bit per component (48-bit in total) is enough for color with HDR. 16-bit per component (32-bit in total) are enough for motion vectors (since usual implementations use GL_RG16F
). As you can see, you can pack a lot of data in these buffers. Then, it is the user's responsibility to implement whatever they may need, without having to change the underlying rendering backend. Literature on how to efficiently perform GPU data packing is plenty on the Internet.
A new shader render_mode
will probably be needed for spatial
shaders: disable_alpha
, to be able to write to the alpha component of the buffer without making the geometry go to the transparent pipeline, and therefore enjoy the full 128-bit buffer, but this is a very low-priority requirement; having 96-bits to work with is a good start.
If this enhancement will not be used often, can it be worked around with a few lines of script?
No.
Is there a reason why this should be core and not an add-on in the asset library?
This is core.