-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Enable post process with full precision using SubViewport #61667
Conversation
A few things to keep in mind as your work to clean this up:
|
67f3d41
to
a9d996c
Compare
a9d996c
to
f581353
Compare
Made a first pass of refactor on that. Remove the whole |
7619be1
to
2493b38
Compare
af003b3
to
9d7f97e
Compare
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.
At some point, it might be good to make tonemapping entirely optional for the linear case...my assumption is you will pass this linear texture into another viewport at some point. if it runs tonemapping twice, that might look wrong. Furthermore, it would mean we can save a full-screen render pass on these linear targets which would improve performance.
There's a lot of plumbing here. My biggest concern is how these color_format and color_format_srgb are passed around everywhere and pollute the API, especially when they are often the same. It seems like much of the code is written under the assumption that those two formats are different. in the case of SFLOAT, from what I can tell, _update_render_target
is still creating the alias for "color_format_srgb" despite it being the same format.
[ I'm talking about this code:
tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color);
if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) {
view.format_override = rt->color_format_srgb;
tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color);
}
]
since color_format_srgb is not RD::DATA_FORMAT_MAX in the linear case. (and if it were, that might cause other bugs)
perhaps it would be better to move the linear flag here, and keep the current code otherwise. that way we wouldn't need those color format functions and all the duplicate code that picks both formats.
Overall, a lot of this change is plumbing. I'm not a rendering team lead, but the main problem I see with it is from making the color format code more confusing.
(there's also a question about do we really need another 128 bits of push constants for a single boolean? Well, there are already many other booleans being passed in this way, so I guess it's just an optimization job for another day.
@lyuma For Tonemapping in this case i left the implementation as is. Linear is not doing anything. |
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.
Great work! You are getting much closer to a working implementation.
Now is the time for us to solidify exactly what the API should look like as I can see you and I have differing ideas.
My thinking was to just expose two booleans keep_3d_linear
(2D is always sRGB), and force_high_precision
.
keep_3d_linear
would be assigned to the render_target and would disable linear->sRGB in the tonemapper. You have this nearly implemented now and it should be fine.
For force_high_precision
my idea was that it would also get assigned to the render_target and then during allocation, the rendertarget would select between two formats based on what force_high_precision
is set to.
In my opinion, the above is about as simple as we can make this feature (it also worked similarly in 3.x).
However, I can see you are going in a slightly different direction, one which would provide the user with a little more flexibility by allowing them to override the default precision. I like this idea as well, and it aligns with our goal of giving users more control in 4.0.
Accordingly, if you want to expose the ability to set the color format directly I would do it as follows:
- Still have
keep_3d_linear
(this is needed in any case) - do not create
force_high_precision
instead create anoverride_color_format
variable in Viewport which would callrender_target_set_override_color_format
(the same as your currentrender_target_set_color_format
). Then inupdate_render_target
you check and see ifoverride_color_format
is used, if it is, then you setcolor_format
,color_format_srgb
, andimage_format
based onoverride_color_format
, if not, you just use the default. - render_target would of course need a boolean
use_override_color_format
which is set to true ifrender_target_set_override_color_format
is called with an argument that is notRD::DATA_FORMAT_R8G8B8A8_UNORM
Thanks for the detailed feedbacks. Both review converge for the |
c80cc03
to
2c4b1de
Compare
Did a second pass on that, removed the whole exposing |
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.
Looks mostly good! I left a few comments on style changes and documentation changes. But it is very close to being done.
I think before merging, we should also have the settings working in the GLES3 renderer. It will work the exact same as in the RD renderer, so it should not be much more work. You can look at the GLES3 renderer in 3.x for the naming of the color format.
88054ca
to
21ceab5
Compare
I did the requested changes. The only thing left is the behavior in edior for GLES3. I think this is due to other issue not related to this PR. |
This comment was marked as outdated.
This comment was marked as outdated.
I might be inclined to agree that this needn't wait for GLES3. My guess is that there is not any work needed for GLES3. Note that GLES3 is a low-end renderer (much like GLES2 was in Godot 3.x), so it likely uses gamma rendering in non-HDR It might be good to have an explicit half- or full-precision float render target mode for GLES3 (useful for calculations / simulation viewports), but that should be proposed and then added as a separate PR if there is demand, I think. |
Actually the feature works in GLES3 with the same behavior than in Vulkan. I just noticed that the behavior in editor is not the same. When changing the flags, the viewport does not update properly sometimes. I also had the case where the |
e99aef1
to
eb0bded
Compare
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.
My apologies, I missed a few things on my last review. After this change it should be good to go!
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 happy with this implementation. Would be nice for @BastiaanOlij and @reduz to weigh in before merging as this is a big change.
As for making it work as we did in Godot 3 this seems sound, but I've never really found we're on the right track with this to begin with. Possibly something to discuss in more detail in a render meeting when we have more time. The core issue here are the assumptions that: None of these assumptions are true and how we render our content differs greatly. Even 2D output can be valid input as a texture used in 3D where colors are not sRGB or where we even don't want RGBA8 as our texture format. Think of rendering noise or height map data. Now in Vulkan we do have more control over how we treat color data both when writing out and when reading but I think we need far more control over configuring the data type of our (sub)viewport and what sort of rendering we're doing. This comes back down to my issue with having Anyway, enough ranting :) |
As a side note, the commits will need to be squashed before merging (see PR workflow). |
Toggles allowing to change the buffer format to higher precision and output raw data (no tonemapping) using a viewport. Implement in both Vulkan and GLES3. Co-authored-by: Clay John <[email protected]>
4b58401
to
350b188
Compare
I don't think this is the right way to tackle this problem to be honest.
I think this is stuff that we need to discuss properly and that will most likely be done for 4.1, the time to add this sort of features has run out for 4.0. |
Totally agree on the fact that this a hack. I still think that it's better than nothing. The fact that this hack was (kind of) available in 3.x version may be an issue for some people. |
@JonqsGames reduz and I discussed his view further in the rendering channel in Rocketchat. The main problems with the current approach (that you and I decided on) is that it conflicts with eventually adding proper HDR support for HDR monitors. For that, we need to add a viewport option that tonemaps 3D into the proper color space and then renders 2D in the proper color space (most likely linear with a tonemapping operator at the end). This current design would end up having to be removed leading to breaking changes. Instead what reduz suggests (and I now agree) is the best approach is to expose the 3D rendering buffer through the viewport API so users can select whether they want their final texture to be the 2D render target, or the 3D render buffer. This has the added benefit that the entire 2D rendering pipeline can be skipped if the user just wants the 3D render buffer (the tonemap shader won't even run). We already do something similar for XR with the
|
Superseded by #70970 |
Fixes #54122
I was facing #54122 when trying to port a post effect i did in 3.4.4
This quick fix make the subviewport keep the
DATA_FORMAT_R16G16B16A16_SFLOAT
precision and disable tonemapping and linearization in the tonemapper shader.The current implementation i did looks really bad but i'll try to clean it later.
keep_linear_3d
checkbox in SubViewport parameterskeep_linear_3d
through SubViewports property to the render targetEdit:
I made a quick test project for this feature :
TestShaderPostProcess.zip
Each cube is using the same shader that has a
float
uniform that is put into the color value.Cube value of main scene are (-1.0, 0.0, 0.5, 1.0, 50.0).
Post process is simply putting a random color based on retrieved color value.
Base result (both
keep_linear
andforce_high_precision
disabled)Result with both flag enabled (Vulkan):