Skip to content

Conversation

@IceSentry
Copy link
Contributor

@IceSentry IceSentry commented Aug 4, 2025

Objective

  • Users often want to run a fullscreen shader but the current solution involves copying the custom_post_processing example which is a 350 line file with a lot of low level wgpu complexity. Users shouldn't have to deal with that just to make a fullscreen shader

Solution

  • Introduce a new FullscreenMaterial trait and FullscsreenMaterialPlugin
  • This new material will run a fullscreen triangle with the specified shader. It builds on top of the existing FullscreenShader infrastructure
  • It lets user customize the node ordering. There's no defaults right now becausae it's intended as a bit of a primitive plugin. Eventually we could have some kind of default for custom post processing

Testing

Made a new fullscreen_material example and made sure it works

Follow up

Once this is merged there are various things that should be done to improve it. Add the option to bind the depth texture, offer defaults for post processing, use a full AsBindGroup, add a way to bind the gbuffer.

@alice-i-cecile alice-i-cecile added the M-Release-Note Work that should be called out in the blog due to impact label Aug 4, 2025
@alice-i-cecile alice-i-cecile added this to the 0.18 milestone Aug 4, 2025
@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible A-Rendering Drawing game state to the screen labels Aug 4, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Aug 4, 2025

It looks like your PR has been selected for a highlight in the next release blog post, but you didn't provide a release note.

Please review the instructions for writing release notes, then expand or revise the content in the release notes directory to showcase your changes.

@alice-i-cecile alice-i-cecile added S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Uncontroversial This work is generally agreed upon labels Aug 4, 2025
@IceSentry IceSentry force-pushed the fullscreen_material branch from b0f9763 to 70e61bd Compare August 9, 2025 03:15
@IceSentry IceSentry marked this pull request as ready for review August 9, 2025 03:39
@brianreavis
Copy link
Contributor

As a 2D user, when I first read “FullscreenMaterial“ I thought this was for ergonomically inserting a fullscreen non-mesh into an existing render pass – which would be handy for applying a vignette or film w/o the cost of a new render pass.

I’d lean into the PostProcess naming in this PR: PostProcessMaterial / PostProcessMaterialPlugin.

@IceSentry
Copy link
Contributor Author

I disagree the main goal of this api is to be a general purpose fullscreen render pass. The main feature is that it can be inserted in any order because some people don't want a post process effect, they just want to do something like render their entire game in a fullscreen shader in the main pass. Like I mentioned in the notes. A post processing version of this would be built on top of the same api but with pre configured ordering.

@hukasu
Copy link
Contributor

hukasu commented Sep 4, 2025

does it make it easy to render the game to a small resolution and then upscale?

@IceSentry
Copy link
Contributor Author

does it make it easy to render the game to a small resolution and then upscale?

Not really in it's current state since it doesn't let you bind arbitrary textures to it. Eventually I do want to let users set a full bind group so that would let users bind a low res texture and then just write a small shader to sample it and it will be "upscaled" that way.

Copy link
Contributor

@HugoPeters1024 HugoPeters1024 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work! This is super helpful <3

Copy link
Member

@tychedelia tychedelia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments, but they can also be improved in a 0.18 follow up. I think that we should push to move this justtt a bit closer to other materials, i.e. by allowing AsBindGroup. But this is an awesome footprint to establish. Happy to land this right at the beginning of 0.18 and iterate. Tysm for doing this!

/// ]
/// ```
///
/// This tell the render graph to run your fullscreen effect after the tonemapping pass but
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's correct? It's just explaining the code snippet just above it.

@JMS55
Copy link
Contributor

JMS55 commented Oct 19, 2025

We should consider copying some of the code from RenderTask #21603. We should probably have the same node setup across both APIs.

@IceSentry
Copy link
Contributor Author

Alright, I did a bit more work on this PR. The node_label is now optional and we use the type name as the default label. The sub_graph is also optional and we try to guess if it should go on a 3d or 2d camera depending on how it was spawned.

I could make the node order optional too and default it to post processing but I'm not sure yet if I want to do that.

The next step is to figure out how to use AsBindGroup to let users provide custom bind groups. I would also like to make the default bindings in group 0 include the depth texture if there is one. I could also add the Globals to that group. Maybe it should just include the same bindings as a mesh material. In the future I'm also tempted to make it fully optional if someone simply wants a fullscreen shader that ignores the other passes.

@JMS55
Copy link
Contributor

JMS55 commented Nov 11, 2025

The next step is to figure out how to use AsBindGroup to let users provide custom bind groups. I would also like to make the default bindings in group 0 include the depth texture if there is one. I could also add the Globals to that group. Maybe it should just include the same bindings as a mesh material. In the future I'm also tempted to make it fully optional if someone simply wants a fullscreen shader that ignores the other passes.

If users want custom bindings, RenderTask might make more sense for them. Imo this PR should stick to a preset bind group of just the depth/globals/whatever.

@IceSentry
Copy link
Contributor Author

I think the main issue is that I fully expect users to want to have access to at least one texture or storage buffer otherwise this is a very limiting api. Also, I'm trying to make this as flexible as possible and to be more general purpose than just post processing.

);

// We can't use add_render_graph_edges because it doesn't accept a Vec<RenderLabel>
if let Some(mut render_graph) = render_app.world_mut().get_resource_mut::<RenderGraph>()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you see what I did in #21603 ? I think we should adopt those changes.

warn!("Failed to add edges for FullscreenMaterial");
};
} else {
// If there was no sub_graph specify we try to determine the graph based on the camera
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// If there was no sub_graph specify we try to determine the graph based on the camera
// If there was no sub_graph specified we try to determine the graph based on the camera

ShaderRef::Default => {
// TODO not sure what an actual fallback should be. An empty shader or output a solid
// color to indicate a missing shader?
unimplemented!("No default fallback for FullscreenMaterial shader")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unimplemented!("No default fallback for FullscreenMaterial shader")
unimplemented!("FullscreenMaterial::fragment_shader() must not return ShaderRef::Default")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible M-Release-Note Work that should be called out in the blog due to impact S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Uncontroversial This work is generally agreed upon

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

8 participants