Skip to content

Commit fed495b

Browse files
committed
Merge branch 'main' into render-target-component
2 parents 382fd10 + 89579d2 commit fed495b

File tree

111 files changed

+6081
-855
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+6081
-855
lines changed

Cargo.toml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ keywords = ["game", "engine", "gamedev", "graphics", "bevy"]
1010
license = "MIT OR Apache-2.0"
1111
repository = "https://github.com/bevyengine/bevy"
1212
documentation = "https://docs.rs/bevy"
13-
rust-version = "1.88.0"
13+
rust-version = "1.89.0"
1414

1515
[workspace]
1616
resolver = "2"
@@ -3491,6 +3491,18 @@ description = "Illustrates how to access `winit::window::Window`'s `hittest` fun
34913491
category = "UI (User Interface)"
34923492
wasm = false
34933493

3494+
[[example]]
3495+
name = "vertical_slider"
3496+
path = "examples/ui/vertical_slider.rs"
3497+
doc-scrape-examples = true
3498+
required-features = ["experimental_bevy_ui_widgets"]
3499+
3500+
[package.metadata.example.vertical_slider]
3501+
name = "Vertical Slider"
3502+
description = "Simple example showing vertical and horizontal slider widgets with snap behavior and value labels"
3503+
category = "UI (User Interface)"
3504+
wasm = true
3505+
34943506
[[example]]
34953507
name = "font_atlas_debug"
34963508
path = "examples/ui/font_atlas_debug.rs"
@@ -4888,3 +4900,26 @@ name = "Pan Camera"
48884900
description = "Example Pan-Camera Styled Camera Controller for 2D scenes"
48894901
category = "Camera"
48904902
wasm = true
4903+
4904+
[[example]]
4905+
name = "clustered_decal_maps"
4906+
path = "examples/3d/clustered_decal_maps.rs"
4907+
doc-scrape-examples = true
4908+
required-features = ["pbr_clustered_decals", "https"]
4909+
4910+
[package.metadata.example.clustered_decal_maps]
4911+
name = "Clustered Decal Maps"
4912+
description = "Demonstrates normal and metallic-roughness maps of decals"
4913+
category = "3D Rendering"
4914+
wasm = false
4915+
4916+
[[example]]
4917+
name = "mirror"
4918+
path = "examples/3d/mirror.rs"
4919+
doc-scrape-examples = true
4920+
4921+
[package.metadata.example.mirror]
4922+
name = "Mirror"
4923+
description = "Demonstrates how to create a mirror with a second camera"
4924+
category = "3D Rendering"
4925+
wasm = true

assets/shaders/array_texture.wgsl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#import bevy_pbr::{
22
forward_io::VertexOutput,
3+
mesh_functions,
34
mesh_view_bindings::view,
45
pbr_types::{STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT, PbrInput, pbr_input_new},
56
pbr_functions as fns,
@@ -15,7 +16,9 @@ fn fragment(
1516
@builtin(front_facing) is_front: bool,
1617
mesh: VertexOutput,
1718
) -> @location(0) vec4<f32> {
18-
let layer = i32(mesh.world_position.x) & 0x3;
19+
// Determine which layer of the array texture to sample from based on the
20+
// mesh tag which originates from the MeshTag component on the entity.
21+
let layer = mesh_functions::get_tag(mesh.instance_index);
1922

2023
// Prepare a 'processed' StandardMaterial by sampling all textures to resolve
2124
// the material members

assets/shaders/custom_clustered_decal.wgsl

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@ fn fragment(
2222
pbr_input.material.base_color = alpha_discard(pbr_input.material, pbr_input.material.base_color);
2323

2424
// Apply the normal decals.
25-
pbr_input.material.base_color = clustered::apply_decal_base_color(
26-
in.world_position.xyz,
27-
in.position.xy,
28-
pbr_input.material.base_color
29-
);
25+
clustered::apply_decals(&pbr_input);
3026

3127
// Here we tint the color based on the tag of the decal.
3228
// We could optionally do other things, such as adjust the normal based on a normal map.
@@ -42,7 +38,7 @@ fn fragment(
4238
);
4339
while (clustered::clustered_decal_iterator_next(&decal_iterator)) {
4440
var decal_base_color = textureSampleLevel(
45-
mesh_view_bindings::clustered_decal_textures[decal_iterator.texture_index],
41+
mesh_view_bindings::clustered_decal_textures[decal_iterator.base_color_texture_index],
4642
mesh_view_bindings::clustered_decal_sampler,
4743
decal_iterator.uv,
4844
0.0
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// A shader that samples its emissive texture at screen space positions rather
2+
// than UVs.
3+
//
4+
// This is used for the mirror example: `examples/3d/mirror.rs`.
5+
6+
#import bevy_pbr::{
7+
forward_io::{VertexOutput, FragmentOutput},
8+
pbr_bindings::emissive_texture,
9+
pbr_fragment::pbr_input_from_standard_material,
10+
pbr_functions::{alpha_discard, apply_pbr_lighting, main_pass_post_lighting_processing}
11+
}
12+
13+
// This is unused, but it's here to satisfy `ExtendedMaterial` requirements.
14+
// See the comment in `ScreenSpaceTextureExtension` in `examples/3d/mirror.rs`
15+
// for more information.
16+
struct ScreenSpaceTextureMaterial {
17+
// An unused value.
18+
dummy: f32,
19+
}
20+
21+
@group(#{MATERIAL_BIND_GROUP}) @binding(100) var<uniform> material: ScreenSpaceTextureMaterial;
22+
23+
@fragment
24+
fn fragment(in: VertexOutput, @builtin(front_facing) is_front: bool) -> FragmentOutput {
25+
var pbr_input = pbr_input_from_standard_material(in, is_front);
26+
27+
// Use zero alpha to avoid multiplying the emissive by the view exposure.
28+
pbr_input.material.emissive = vec4(
29+
textureLoad(emissive_texture, vec2<i32>(floor(in.position.xy)), 0).rgb,
30+
0.0
31+
);
32+
33+
var out: FragmentOutput;
34+
out.color = apply_pbr_lighting(pbr_input);
35+
out.color = main_pass_post_lighting_processing(pbr_input, out.color);
36+
return out;
37+
}

crates/bevy_anti_alias/src/contrast_adaptive_sharpening/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ use bevy_camera::Camera;
44
use bevy_core_pipeline::{
55
core_2d::graph::{Core2d, Node2d},
66
core_3d::graph::{Core3d, Node3d},
7+
schedule::{Core2dSchedule, Core2dSystems},
78
FullscreenShader,
89
};
10+
use crate::fxaa::fxaa;
911
use bevy_ecs::{prelude::*, query::QueryItem};
1012
use bevy_image::BevyDefault as _;
1113
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
@@ -26,6 +28,7 @@ use bevy_utils::default;
2628
mod node;
2729

2830
pub use node::CasNode;
31+
pub(crate) use node::cas;
2932

3033
/// Applies a contrast adaptive sharpening (CAS) filter to the camera.
3134
///
@@ -150,6 +153,11 @@ impl Plugin for CasPlugin {
150153
Node2d::ContrastAdaptiveSharpening,
151154
Node2d::EndMainPassPostProcessing,
152155
),
156+
)
157+
.add_systems(
158+
Core2dSchedule,
159+
cas.after(fxaa)
160+
.before(Core2dSystems::EndMainPassPostProcessing),
153161
);
154162
}
155163
}

crates/bevy_anti_alias/src/contrast_adaptive_sharpening/node.rs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use bevy_render::{
1010
BindGroup, BindGroupEntries, BufferId, Operations, PipelineCache,
1111
RenderPassColorAttachment, RenderPassDescriptor, TextureViewId,
1212
},
13-
renderer::RenderContext,
13+
renderer::{CurrentView, RenderContext, RenderContextParam},
1414
view::{ExtractedView, ViewTarget},
1515
};
1616

@@ -124,3 +124,87 @@ impl Node for CasNode {
124124
Ok(())
125125
}
126126
}
127+
128+
// =============================================================================
129+
// Schedule-based system (new approach)
130+
// =============================================================================
131+
132+
/// Render system for Contrast Adaptive Sharpening.
133+
///
134+
/// This is the schedule-based replacement for [`CasNode`].
135+
pub(crate) fn cas(
136+
view: CurrentView,
137+
view_query: Query<
138+
(
139+
&ViewTarget,
140+
&ViewCasPipeline,
141+
&DynamicUniformIndex<CasUniform>,
142+
),
143+
With<ExtractedView>,
144+
>,
145+
sharpening_pipeline: Res<CasPipeline>,
146+
pipeline_cache: Res<PipelineCache>,
147+
uniforms: Res<ComponentUniforms<CasUniform>>,
148+
mut ctx: RenderContextParam,
149+
mut cached_bind_group: Local<Option<(BufferId, TextureViewId, BindGroup)>>,
150+
) {
151+
let view_entity = view.entity();
152+
153+
let Ok((target, pipeline, uniform_index)) = view_query.get(view_entity) else {
154+
return;
155+
};
156+
157+
let uniforms_id = uniforms.buffer().unwrap().id();
158+
let Some(uniforms_binding) = uniforms.binding() else {
159+
return;
160+
};
161+
162+
let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline.0) else {
163+
return;
164+
};
165+
166+
let view_target = target.post_process_write();
167+
let source = view_target.source;
168+
let destination = view_target.destination;
169+
170+
let bind_group = match &mut *cached_bind_group {
171+
Some((buffer_id, texture_id, bind_group))
172+
if source.id() == *texture_id && uniforms_id == *buffer_id =>
173+
{
174+
bind_group
175+
}
176+
cached => {
177+
let bind_group = ctx.render_device().create_bind_group(
178+
"cas_bind_group",
179+
&pipeline_cache.get_bind_group_layout(&sharpening_pipeline.texture_bind_group),
180+
&BindGroupEntries::sequential((
181+
view_target.source,
182+
&sharpening_pipeline.sampler,
183+
uniforms_binding,
184+
)),
185+
);
186+
187+
let (_, _, bind_group) = cached.insert((uniforms_id, source.id(), bind_group));
188+
bind_group
189+
}
190+
};
191+
192+
let pass_descriptor = RenderPassDescriptor {
193+
label: Some("contrast_adaptive_sharpening"),
194+
color_attachments: &[Some(RenderPassColorAttachment {
195+
view: destination,
196+
depth_slice: None,
197+
resolve_target: None,
198+
ops: Operations::default(),
199+
})],
200+
depth_stencil_attachment: None,
201+
timestamp_writes: None,
202+
occlusion_query_set: None,
203+
};
204+
205+
let mut render_pass = ctx.command_encoder().begin_render_pass(&pass_descriptor);
206+
207+
render_pass.set_pipeline(pipeline);
208+
render_pass.set_bind_group(0, bind_group, &[uniform_index.index()]);
209+
render_pass.draw(0..3, 0..1);
210+
}

crates/bevy_anti_alias/src/fxaa/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use bevy_camera::Camera;
44
use bevy_core_pipeline::{
55
core_2d::graph::{Core2d, Node2d},
66
core_3d::graph::{Core3d, Node3d},
7+
schedule::{Core2dSchedule, Core2dSystems},
8+
tonemapping::tonemapping,
79
FullscreenShader,
810
};
911
use bevy_ecs::prelude::*;
@@ -26,6 +28,7 @@ use bevy_utils::default;
2628
mod node;
2729

2830
pub use node::FxaaNode;
31+
pub(crate) use node::fxaa;
2932

3033
#[derive(Debug, Reflect, Eq, PartialEq, Hash, Clone, Copy)]
3134
#[reflect(PartialEq, Hash, Clone)]
@@ -117,6 +120,11 @@ impl Plugin for FxaaPlugin {
117120
Node2d::Fxaa,
118121
Node2d::EndMainPassPostProcessing,
119122
),
123+
)
124+
.add_systems(
125+
Core2dSchedule,
126+
fxaa.after(tonemapping)
127+
.before(Core2dSystems::EndMainPassPostProcessing),
120128
);
121129
}
122130
}

crates/bevy_anti_alias/src/fxaa/node.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use bevy_render::{
99
BindGroup, BindGroupEntries, Operations, PipelineCache, RenderPassColorAttachment,
1010
RenderPassDescriptor, TextureViewId,
1111
},
12-
renderer::RenderContext,
12+
renderer::{CurrentView, RenderContext, RenderContextParam},
1313
view::ViewTarget,
1414
};
1515

@@ -90,3 +90,69 @@ impl ViewNode for FxaaNode {
9090
Ok(())
9191
}
9292
}
93+
94+
// =============================================================================
95+
// Schedule-based system (new approach)
96+
// =============================================================================
97+
98+
/// Render system for FXAA anti-aliasing.
99+
///
100+
/// This is the schedule-based replacement for [`FxaaNode`].
101+
pub(crate) fn fxaa(
102+
view: CurrentView,
103+
view_query: Query<(&ViewTarget, &CameraFxaaPipeline, &Fxaa)>,
104+
fxaa_pipeline: Res<FxaaPipeline>,
105+
pipeline_cache: Res<PipelineCache>,
106+
mut ctx: RenderContextParam,
107+
mut cached_bind_group: Local<Option<(TextureViewId, BindGroup)>>,
108+
) {
109+
let view_entity = view.entity();
110+
111+
let Ok((target, pipeline, fxaa)) = view_query.get(view_entity) else {
112+
return;
113+
};
114+
115+
if !fxaa.enabled {
116+
return;
117+
}
118+
119+
let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline_id) else {
120+
return;
121+
};
122+
123+
let post_process = target.post_process_write();
124+
let source = post_process.source;
125+
let destination = post_process.destination;
126+
let bind_group = match &mut *cached_bind_group {
127+
Some((id, bind_group)) if source.id() == *id => bind_group,
128+
cached => {
129+
let bind_group = ctx.render_device().create_bind_group(
130+
None,
131+
&pipeline_cache.get_bind_group_layout(&fxaa_pipeline.texture_bind_group),
132+
&BindGroupEntries::sequential((source, &fxaa_pipeline.sampler)),
133+
);
134+
135+
let (_, bind_group) = cached.insert((source.id(), bind_group));
136+
bind_group
137+
}
138+
};
139+
140+
let pass_descriptor = RenderPassDescriptor {
141+
label: Some("fxaa"),
142+
color_attachments: &[Some(RenderPassColorAttachment {
143+
view: destination,
144+
depth_slice: None,
145+
resolve_target: None,
146+
ops: Operations::default(),
147+
})],
148+
depth_stencil_attachment: None,
149+
timestamp_writes: None,
150+
occlusion_query_set: None,
151+
};
152+
153+
let mut render_pass = ctx.command_encoder().begin_render_pass(&pass_descriptor);
154+
155+
render_pass.set_pipeline(pipeline);
156+
render_pass.set_bind_group(0, bind_group, &[]);
157+
render_pass.draw(0..3, 0..1);
158+
}

0 commit comments

Comments
 (0)