mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
Move Msaa
to component (#14273)
Switches `Msaa` from being a globally configured resource to a per camera view component. Closes #7194 # Objective Allow individual views to describe their own MSAA settings. For example, when rendering to different windows or to different parts of the same view. ## Solution Make `Msaa` a component that is required on all camera bundles. ## Testing Ran a variety of examples to ensure that nothing broke. TODO: - [ ] Make sure android still works per previous comment in `extract_windows`. --- ## Migration Guide `Msaa` is no longer configured as a global resource, and should be specified on each spawned camera if a non-default setting is desired. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: François Mockers <francois.mockers@vleue.com>
This commit is contained in:
parent
462da1e49d
commit
03fd1b46ef
33 changed files with 222 additions and 218 deletions
|
@ -2,6 +2,7 @@ use crate::core_2d::graph::Core2d;
|
|||
use crate::tonemapping::{DebandDither, Tonemapping};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_render::prelude::Msaa;
|
||||
use bevy_render::{
|
||||
camera::{
|
||||
Camera, CameraMainTextureUsages, CameraProjection, CameraRenderGraph,
|
||||
|
@ -35,6 +36,7 @@ pub struct Camera2dBundle {
|
|||
pub tonemapping: Tonemapping,
|
||||
pub deband_dither: DebandDither,
|
||||
pub main_texture_usages: CameraMainTextureUsages,
|
||||
pub msaa: Msaa,
|
||||
}
|
||||
|
||||
impl Default for Camera2dBundle {
|
||||
|
@ -58,6 +60,7 @@ impl Default for Camera2dBundle {
|
|||
tonemapping: Tonemapping::None,
|
||||
deband_dither: DebandDither::Disabled,
|
||||
main_texture_usages: Default::default(),
|
||||
msaa: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +93,7 @@ impl Camera2dBundle {
|
|||
tonemapping: Tonemapping::None,
|
||||
deband_dither: DebandDither::Disabled,
|
||||
main_texture_usages: Default::default(),
|
||||
msaa: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::{
|
|||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_render::view::Msaa;
|
||||
use bevy_render::{
|
||||
camera::{Camera, CameraMainTextureUsages, CameraRenderGraph, Exposure, Projection},
|
||||
extract_component::ExtractComponent,
|
||||
|
@ -152,6 +153,7 @@ pub struct Camera3dBundle {
|
|||
pub color_grading: ColorGrading,
|
||||
pub exposure: Exposure,
|
||||
pub main_texture_usages: CameraMainTextureUsages,
|
||||
pub msaa: Msaa,
|
||||
}
|
||||
|
||||
// NOTE: ideally Perspective and Orthographic defaults can share the same impl, but sadly it breaks rust's type inference
|
||||
|
@ -171,6 +173,7 @@ impl Default for Camera3dBundle {
|
|||
exposure: Default::default(),
|
||||
main_texture_usages: Default::default(),
|
||||
deband_dither: DebandDither::Enabled,
|
||||
msaa: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -610,16 +610,21 @@ pub fn extract_camera_prepass_phase(
|
|||
pub fn prepare_core_3d_depth_textures(
|
||||
mut commands: Commands,
|
||||
mut texture_cache: ResMut<TextureCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_device: Res<RenderDevice>,
|
||||
opaque_3d_phases: Res<ViewBinnedRenderPhases<Opaque3d>>,
|
||||
alpha_mask_3d_phases: Res<ViewBinnedRenderPhases<AlphaMask3d>>,
|
||||
transmissive_3d_phases: Res<ViewSortedRenderPhases<Transmissive3d>>,
|
||||
transparent_3d_phases: Res<ViewSortedRenderPhases<Transparent3d>>,
|
||||
views_3d: Query<(Entity, &ExtractedCamera, Option<&DepthPrepass>, &Camera3d)>,
|
||||
views_3d: Query<(
|
||||
Entity,
|
||||
&ExtractedCamera,
|
||||
Option<&DepthPrepass>,
|
||||
&Camera3d,
|
||||
&Msaa,
|
||||
)>,
|
||||
) {
|
||||
let mut render_target_usage = HashMap::default();
|
||||
for (view, camera, depth_prepass, camera_3d) in &views_3d {
|
||||
for (view, camera, depth_prepass, camera_3d, _msaa) in &views_3d {
|
||||
if !opaque_3d_phases.contains_key(&view)
|
||||
|| !alpha_mask_3d_phases.contains_key(&view)
|
||||
|| !transmissive_3d_phases.contains_key(&view)
|
||||
|
@ -641,13 +646,13 @@ pub fn prepare_core_3d_depth_textures(
|
|||
}
|
||||
|
||||
let mut textures = HashMap::default();
|
||||
for (entity, camera, _, camera_3d) in &views_3d {
|
||||
for (entity, camera, _, camera_3d, msaa) in &views_3d {
|
||||
let Some(physical_target_size) = camera.physical_target_size else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let cached_texture = textures
|
||||
.entry(camera.target.clone())
|
||||
.entry((camera.target.clone(), msaa))
|
||||
.or_insert_with(|| {
|
||||
// The size of the depth texture
|
||||
let size = Extent3d {
|
||||
|
@ -779,11 +784,8 @@ pub fn prepare_core_3d_transmission_textures(
|
|||
}
|
||||
|
||||
// Disable MSAA and warn if using deferred rendering
|
||||
pub fn check_msaa(
|
||||
mut msaa: ResMut<Msaa>,
|
||||
deferred_views: Query<Entity, (With<Camera>, With<DeferredPrepass>)>,
|
||||
) {
|
||||
if !deferred_views.is_empty() {
|
||||
pub fn check_msaa(mut deferred_views: Query<&mut Msaa, (With<Camera>, With<DeferredPrepass>)>) {
|
||||
for mut msaa in deferred_views.iter_mut() {
|
||||
match *msaa {
|
||||
Msaa::Off => (),
|
||||
_ => {
|
||||
|
@ -799,7 +801,6 @@ pub fn check_msaa(
|
|||
pub fn prepare_prepass_textures(
|
||||
mut commands: Commands,
|
||||
mut texture_cache: ResMut<TextureCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_device: Res<RenderDevice>,
|
||||
opaque_3d_prepass_phases: Res<ViewBinnedRenderPhases<Opaque3dPrepass>>,
|
||||
alpha_mask_3d_prepass_phases: Res<ViewBinnedRenderPhases<AlphaMask3dPrepass>>,
|
||||
|
@ -808,6 +809,7 @@ pub fn prepare_prepass_textures(
|
|||
views_3d: Query<(
|
||||
Entity,
|
||||
&ExtractedCamera,
|
||||
&Msaa,
|
||||
Has<DepthPrepass>,
|
||||
Has<NormalPrepass>,
|
||||
Has<MotionVectorPrepass>,
|
||||
|
@ -819,8 +821,15 @@ pub fn prepare_prepass_textures(
|
|||
let mut deferred_textures = HashMap::default();
|
||||
let mut deferred_lighting_id_textures = HashMap::default();
|
||||
let mut motion_vectors_textures = HashMap::default();
|
||||
for (entity, camera, depth_prepass, normal_prepass, motion_vector_prepass, deferred_prepass) in
|
||||
&views_3d
|
||||
for (
|
||||
entity,
|
||||
camera,
|
||||
msaa,
|
||||
depth_prepass,
|
||||
normal_prepass,
|
||||
motion_vector_prepass,
|
||||
deferred_prepass,
|
||||
) in &views_3d
|
||||
{
|
||||
if !opaque_3d_prepass_phases.contains_key(&entity)
|
||||
&& !alpha_mask_3d_prepass_phases.contains_key(&entity)
|
||||
|
|
|
@ -515,11 +515,10 @@ impl FromWorld for DepthOfFieldGlobalBindGroupLayout {
|
|||
/// specific to each view.
|
||||
pub fn prepare_depth_of_field_view_bind_group_layouts(
|
||||
mut commands: Commands,
|
||||
view_targets: Query<(Entity, &DepthOfFieldSettings)>,
|
||||
msaa: Res<Msaa>,
|
||||
view_targets: Query<(Entity, &DepthOfFieldSettings, &Msaa)>,
|
||||
render_device: Res<RenderDevice>,
|
||||
) {
|
||||
for (view, dof_settings) in view_targets.iter() {
|
||||
for (view, dof_settings, msaa) in view_targets.iter() {
|
||||
// Create the bind group layout for the passes that take one input.
|
||||
let single_input = render_device.create_bind_group_layout(
|
||||
Some("depth of field bind group layout (single input)"),
|
||||
|
@ -646,16 +645,16 @@ pub fn prepare_depth_of_field_pipelines(
|
|||
mut commands: Commands,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<DepthOfFieldPipeline>>,
|
||||
msaa: Res<Msaa>,
|
||||
global_bind_group_layout: Res<DepthOfFieldGlobalBindGroupLayout>,
|
||||
view_targets: Query<(
|
||||
Entity,
|
||||
&ExtractedView,
|
||||
&DepthOfFieldSettings,
|
||||
&ViewDepthOfFieldBindGroupLayouts,
|
||||
&Msaa,
|
||||
)>,
|
||||
) {
|
||||
for (entity, view, dof_settings, view_bind_group_layouts) in view_targets.iter() {
|
||||
for (entity, view, dof_settings, view_bind_group_layouts, msaa) in view_targets.iter() {
|
||||
let dof_pipeline = DepthOfFieldPipeline {
|
||||
view_bind_group_layouts: view_bind_group_layouts.clone(),
|
||||
global_bind_group_layout: global_bind_group_layout.layout.clone(),
|
||||
|
|
|
@ -27,12 +27,13 @@ impl ViewNode for MotionBlurNode {
|
|||
&'static MotionBlurPipelineId,
|
||||
&'static ViewPrepassTextures,
|
||||
&'static MotionBlur,
|
||||
&'static Msaa,
|
||||
);
|
||||
fn run(
|
||||
&self,
|
||||
_graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
(view_target, pipeline_id, prepass_textures, settings): QueryItem<Self::ViewQuery>,
|
||||
(view_target, pipeline_id, prepass_textures, settings, msaa): QueryItem<Self::ViewQuery>,
|
||||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
if settings.samples == 0 || settings.shutter_angle <= 0.0 {
|
||||
|
@ -60,7 +61,6 @@ impl ViewNode for MotionBlurNode {
|
|||
|
||||
let post_process = view_target.post_process_write();
|
||||
|
||||
let msaa = world.resource::<Msaa>();
|
||||
let layout = if msaa.samples() == 1 {
|
||||
&motion_blur_pipeline.layout
|
||||
} else {
|
||||
|
|
|
@ -153,10 +153,9 @@ pub(crate) fn prepare_motion_blur_pipelines(
|
|||
pipeline_cache: Res<PipelineCache>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<MotionBlurPipeline>>,
|
||||
pipeline: Res<MotionBlurPipeline>,
|
||||
msaa: Res<Msaa>,
|
||||
views: Query<(Entity, &ExtractedView), With<MotionBlur>>,
|
||||
views: Query<(Entity, &ExtractedView, &Msaa), With<MotionBlur>>,
|
||||
) {
|
||||
for (entity, view) in &views {
|
||||
for (entity, view, msaa) in &views {
|
||||
let pipeline_id = pipelines.specialize(
|
||||
&pipeline_cache,
|
||||
&pipeline,
|
||||
|
|
|
@ -6,9 +6,11 @@ use crate::{
|
|||
use bevy_app::{App, Plugin};
|
||||
use bevy_color::LinearRgba;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_ecs::query::QueryItem;
|
||||
use bevy_render::render_graph::{ViewNode, ViewNodeRunner};
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
render_graph::{Node, NodeRunError, RenderGraphApp, RenderGraphContext},
|
||||
render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext},
|
||||
renderer::RenderContext,
|
||||
view::{Msaa, ViewTarget},
|
||||
Render, RenderSet,
|
||||
|
@ -30,90 +32,87 @@ impl Plugin for MsaaWritebackPlugin {
|
|||
);
|
||||
{
|
||||
render_app
|
||||
.add_render_graph_node::<MsaaWritebackNode>(Core2d, Node2d::MsaaWriteback)
|
||||
.add_render_graph_node::<ViewNodeRunner<MsaaWritebackNode>>(
|
||||
Core2d,
|
||||
Node2d::MsaaWriteback,
|
||||
)
|
||||
.add_render_graph_edge(Core2d, Node2d::MsaaWriteback, Node2d::StartMainPass);
|
||||
}
|
||||
{
|
||||
render_app
|
||||
.add_render_graph_node::<MsaaWritebackNode>(Core3d, Node3d::MsaaWriteback)
|
||||
.add_render_graph_node::<ViewNodeRunner<MsaaWritebackNode>>(
|
||||
Core3d,
|
||||
Node3d::MsaaWriteback,
|
||||
)
|
||||
.add_render_graph_edge(Core3d, Node3d::MsaaWriteback, Node3d::StartMainPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MsaaWritebackNode {
|
||||
cameras: QueryState<(&'static ViewTarget, &'static MsaaWritebackBlitPipeline)>,
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct MsaaWritebackNode;
|
||||
|
||||
impl FromWorld for MsaaWritebackNode {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
Self {
|
||||
cameras: world.query(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ViewNode for MsaaWritebackNode {
|
||||
type ViewQuery = (
|
||||
&'static ViewTarget,
|
||||
&'static MsaaWritebackBlitPipeline,
|
||||
&'static Msaa,
|
||||
);
|
||||
|
||||
impl Node for MsaaWritebackNode {
|
||||
fn update(&mut self, world: &mut World) {
|
||||
self.cameras.update_archetypes(world);
|
||||
}
|
||||
|
||||
fn run(
|
||||
fn run<'w>(
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
world: &World,
|
||||
_graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(target, blit_pipeline_id, msaa): QueryItem<'w, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
if *world.resource::<Msaa>() == Msaa::Off {
|
||||
if *msaa == Msaa::Off {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let view_entity = graph.view_entity();
|
||||
if let Ok((target, blit_pipeline_id)) = self.cameras.get_manual(world, view_entity) {
|
||||
let blit_pipeline = world.resource::<BlitPipeline>();
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
let Some(pipeline) = pipeline_cache.get_render_pipeline(blit_pipeline_id.0) else {
|
||||
return Ok(());
|
||||
};
|
||||
let blit_pipeline = world.resource::<BlitPipeline>();
|
||||
let pipeline_cache = world.resource::<PipelineCache>();
|
||||
let Some(pipeline) = pipeline_cache.get_render_pipeline(blit_pipeline_id.0) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// The current "main texture" needs to be bound as an input resource, and we need the "other"
|
||||
// unused target to be the "resolve target" for the MSAA write. Therefore this is the same
|
||||
// as a post process write!
|
||||
let post_process = target.post_process_write();
|
||||
// The current "main texture" needs to be bound as an input resource, and we need the "other"
|
||||
// unused target to be the "resolve target" for the MSAA write. Therefore this is the same
|
||||
// as a post process write!
|
||||
let post_process = target.post_process_write();
|
||||
|
||||
let pass_descriptor = RenderPassDescriptor {
|
||||
label: Some("msaa_writeback"),
|
||||
// The target's "resolve target" is the "destination" in post_process.
|
||||
// We will indirectly write the results to the "destination" using
|
||||
// the MSAA resolve step.
|
||||
color_attachments: &[Some(RenderPassColorAttachment {
|
||||
// If MSAA is enabled, then the sampled texture will always exist
|
||||
view: target.sampled_main_texture_view().unwrap(),
|
||||
resolve_target: Some(post_process.destination),
|
||||
ops: Operations {
|
||||
load: LoadOp::Clear(LinearRgba::BLACK.into()),
|
||||
store: StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
};
|
||||
let pass_descriptor = RenderPassDescriptor {
|
||||
label: Some("msaa_writeback"),
|
||||
// The target's "resolve target" is the "destination" in post_process.
|
||||
// We will indirectly write the results to the "destination" using
|
||||
// the MSAA resolve step.
|
||||
color_attachments: &[Some(RenderPassColorAttachment {
|
||||
// If MSAA is enabled, then the sampled texture will always exist
|
||||
view: target.sampled_main_texture_view().unwrap(),
|
||||
resolve_target: Some(post_process.destination),
|
||||
ops: Operations {
|
||||
load: LoadOp::Clear(LinearRgba::BLACK.into()),
|
||||
store: StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
};
|
||||
|
||||
let bind_group = render_context.render_device().create_bind_group(
|
||||
None,
|
||||
&blit_pipeline.texture_bind_group,
|
||||
&BindGroupEntries::sequential((post_process.source, &blit_pipeline.sampler)),
|
||||
);
|
||||
let bind_group = render_context.render_device().create_bind_group(
|
||||
None,
|
||||
&blit_pipeline.texture_bind_group,
|
||||
&BindGroupEntries::sequential((post_process.source, &blit_pipeline.sampler)),
|
||||
);
|
||||
|
||||
let mut render_pass = render_context
|
||||
.command_encoder()
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
let mut render_pass = render_context
|
||||
.command_encoder()
|
||||
.begin_render_pass(&pass_descriptor);
|
||||
|
||||
render_pass.set_pipeline(pipeline);
|
||||
render_pass.set_bind_group(0, &bind_group, &[]);
|
||||
render_pass.draw(0..3, 0..1);
|
||||
}
|
||||
render_pass.set_pipeline(pipeline);
|
||||
render_pass.set_bind_group(0, &bind_group, &[]);
|
||||
render_pass.draw(0..3, 0..1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -127,10 +126,9 @@ fn prepare_msaa_writeback_pipelines(
|
|||
pipeline_cache: Res<PipelineCache>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<BlitPipeline>>,
|
||||
blit_pipeline: Res<BlitPipeline>,
|
||||
view_targets: Query<(Entity, &ViewTarget, &ExtractedCamera)>,
|
||||
msaa: Res<Msaa>,
|
||||
view_targets: Query<(Entity, &ViewTarget, &ExtractedCamera, &Msaa)>,
|
||||
) {
|
||||
for (entity, view_target, camera) in view_targets.iter() {
|
||||
for (entity, view_target, camera, msaa) in view_targets.iter() {
|
||||
// only do writeback if writeback is enabled for the camera and this isn't the first camera in the target,
|
||||
// as there is nothing to write back for the first camera.
|
||||
if msaa.samples() > 1 && camera.msaa_writeback && camera.sorted_camera_index_for_target > 0
|
||||
|
|
|
@ -245,10 +245,9 @@ fn prepare_skybox_pipelines(
|
|||
pipeline_cache: Res<PipelineCache>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<SkyboxPipeline>>,
|
||||
pipeline: Res<SkyboxPipeline>,
|
||||
msaa: Res<Msaa>,
|
||||
views: Query<(Entity, &ExtractedView), With<Skybox>>,
|
||||
views: Query<(Entity, &ExtractedView, &Msaa), With<Skybox>>,
|
||||
) {
|
||||
for (entity, view) in &views {
|
||||
for (entity, view, msaa) in &views {
|
||||
let pipeline_id = pipelines.specialize(
|
||||
&pipeline_cache,
|
||||
&pipeline,
|
||||
|
|
|
@ -116,11 +116,10 @@ pub fn prepare_skybox_prepass_pipelines(
|
|||
mut commands: Commands,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<SkyboxPrepassPipeline>>,
|
||||
msaa: Res<Msaa>,
|
||||
pipeline: Res<SkyboxPrepassPipeline>,
|
||||
views: Query<(Entity, Has<NormalPrepass>), (With<Skybox>, With<MotionVectorPrepass>)>,
|
||||
views: Query<(Entity, Has<NormalPrepass>, &Msaa), (With<Skybox>, With<MotionVectorPrepass>)>,
|
||||
) {
|
||||
for (entity, normal_prepass) in &views {
|
||||
for (entity, normal_prepass, msaa) in &views {
|
||||
let pipeline_key = SkyboxPrepassPipelineKey {
|
||||
samples: msaa.samples(),
|
||||
normal_prepass,
|
||||
|
|
|
@ -34,6 +34,7 @@ use bevy_render::{
|
|||
view::{ExtractedView, Msaa, ViewTarget},
|
||||
ExtractSchedule, MainWorld, Render, RenderApp, RenderSet,
|
||||
};
|
||||
use bevy_utils::tracing::warn;
|
||||
|
||||
const TAA_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(656865235226276);
|
||||
|
||||
|
@ -46,8 +47,7 @@ impl Plugin for TemporalAntiAliasPlugin {
|
|||
fn build(&self, app: &mut App) {
|
||||
load_internal_asset!(app, TAA_SHADER_HANDLE, "taa.wgsl", Shader::from_wgsl);
|
||||
|
||||
app.insert_resource(Msaa::Off)
|
||||
.register_type::<TemporalAntiAliasSettings>();
|
||||
app.register_type::<TemporalAntiAliasSettings>();
|
||||
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
|
@ -162,17 +162,23 @@ impl ViewNode for TemporalAntiAliasNode {
|
|||
&'static TemporalAntiAliasHistoryTextures,
|
||||
&'static ViewPrepassTextures,
|
||||
&'static TemporalAntiAliasPipelineId,
|
||||
&'static Msaa,
|
||||
);
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
(camera, view_target, taa_history_textures, prepass_textures, taa_pipeline_id): QueryItem<
|
||||
(camera, view_target, taa_history_textures, prepass_textures, taa_pipeline_id, msaa): QueryItem<
|
||||
Self::ViewQuery,
|
||||
>,
|
||||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
if *msaa != Msaa::Off {
|
||||
warn!("Temporal anti-aliasing requires MSAA to be disabled");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let (Some(pipelines), Some(pipeline_cache)) = (
|
||||
world.get_resource::<TaaPipeline>(),
|
||||
world.get_resource::<PipelineCache>(),
|
||||
|
|
|
@ -255,15 +255,14 @@ fn queue_line_gizmos_2d(
|
|||
pipeline: Res<LineGizmoPipeline>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<LineGizmoPipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
line_gizmos: Query<(Entity, &Handle<LineGizmo>, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
|
||||
mut views: Query<(Entity, &ExtractedView, Option<&RenderLayers>)>,
|
||||
mut views: Query<(Entity, &ExtractedView, &Msaa, Option<&RenderLayers>)>,
|
||||
) {
|
||||
let draw_function = draw_functions.read().get_id::<DrawLineGizmo2d>().unwrap();
|
||||
|
||||
for (view_entity, view, render_layers) in &mut views {
|
||||
for (view_entity, view, msaa, render_layers) in &mut views {
|
||||
let Some(transparent_phase) = transparent_render_phases.get_mut(&view_entity) else {
|
||||
continue;
|
||||
};
|
||||
|
@ -309,18 +308,17 @@ fn queue_line_joint_gizmos_2d(
|
|||
pipeline: Res<LineJointGizmoPipeline>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<LineJointGizmoPipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
line_gizmos: Query<(Entity, &Handle<LineGizmo>, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
|
||||
mut views: Query<(Entity, &ExtractedView, Option<&RenderLayers>)>,
|
||||
mut views: Query<(Entity, &ExtractedView, &Msaa, Option<&RenderLayers>)>,
|
||||
) {
|
||||
let draw_function = draw_functions
|
||||
.read()
|
||||
.get_id::<DrawLineJointGizmo2d>()
|
||||
.unwrap();
|
||||
|
||||
for (view_entity, view, render_layers) in &mut views {
|
||||
for (view_entity, view, msaa, render_layers) in &mut views {
|
||||
let Some(transparent_phase) = transparent_render_phases.get_mut(&view_entity) else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
@ -280,13 +280,13 @@ fn queue_line_gizmos_3d(
|
|||
pipeline: Res<LineGizmoPipeline>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<LineGizmoPipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
line_gizmos: Query<(Entity, &Handle<LineGizmo>, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent3d>>,
|
||||
mut views: Query<(
|
||||
Entity,
|
||||
&ExtractedView,
|
||||
&Msaa,
|
||||
Option<&RenderLayers>,
|
||||
(
|
||||
Has<NormalPrepass>,
|
||||
|
@ -301,6 +301,7 @@ fn queue_line_gizmos_3d(
|
|||
for (
|
||||
view_entity,
|
||||
view,
|
||||
msaa,
|
||||
render_layers,
|
||||
(normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass),
|
||||
) in &mut views
|
||||
|
@ -368,13 +369,13 @@ fn queue_line_joint_gizmos_3d(
|
|||
pipeline: Res<LineJointGizmoPipeline>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<LineJointGizmoPipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
line_gizmos: Query<(Entity, &Handle<LineGizmo>, &GizmoMeshConfig)>,
|
||||
line_gizmo_assets: Res<RenderAssets<GpuLineGizmo>>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent3d>>,
|
||||
mut views: Query<(
|
||||
Entity,
|
||||
&ExtractedView,
|
||||
&Msaa,
|
||||
Option<&RenderLayers>,
|
||||
(
|
||||
Has<NormalPrepass>,
|
||||
|
@ -392,6 +393,7 @@ fn queue_line_joint_gizmos_3d(
|
|||
for (
|
||||
view_entity,
|
||||
view,
|
||||
msaa,
|
||||
render_layers,
|
||||
(normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass),
|
||||
) in &mut views
|
||||
|
|
|
@ -536,7 +536,6 @@ pub fn queue_material_meshes<M: Material>(
|
|||
material_pipeline: Res<MaterialPipeline<M>>,
|
||||
mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipeline<M>>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_meshes: Res<RenderAssets<RenderMesh>>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial<M>>>,
|
||||
render_mesh_instances: Res<RenderMeshInstances>,
|
||||
|
@ -551,6 +550,7 @@ pub fn queue_material_meshes<M: Material>(
|
|||
Entity,
|
||||
&ExtractedView,
|
||||
&VisibleEntities,
|
||||
&Msaa,
|
||||
Option<&Tonemapping>,
|
||||
Option<&DebandDither>,
|
||||
Option<&ShadowFilteringMethod>,
|
||||
|
@ -576,6 +576,7 @@ pub fn queue_material_meshes<M: Material>(
|
|||
view_entity,
|
||||
view,
|
||||
visible_entities,
|
||||
msaa,
|
||||
tonemapping,
|
||||
dither,
|
||||
shadow_filter_method,
|
||||
|
@ -691,9 +692,14 @@ pub fn queue_material_meshes<M: Material>(
|
|||
continue;
|
||||
};
|
||||
|
||||
let mut mesh_pipeline_key_bits = material.properties.mesh_pipeline_key_bits;
|
||||
mesh_pipeline_key_bits.insert(alpha_mode_pipeline_key(
|
||||
material.properties.alpha_mode,
|
||||
msaa,
|
||||
));
|
||||
let mut mesh_key = view_key
|
||||
| MeshPipelineKey::from_bits_retain(mesh.key_bits.bits())
|
||||
| material.properties.mesh_pipeline_key_bits;
|
||||
| mesh_pipeline_key_bits;
|
||||
|
||||
let lightmap_image = render_lightmaps
|
||||
.render_lightmaps
|
||||
|
@ -906,12 +912,11 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
|
|||
SRes<FallbackImage>,
|
||||
SRes<MaterialPipeline<M>>,
|
||||
SRes<DefaultOpaqueRendererMethod>,
|
||||
SRes<Msaa>,
|
||||
);
|
||||
|
||||
fn prepare_asset(
|
||||
material: Self::SourceAsset,
|
||||
(render_device, images, fallback_image, pipeline, default_opaque_render_method, msaa): &mut SystemParamItem<Self::Param>,
|
||||
(render_device, images, fallback_image, pipeline, default_opaque_render_method): &mut SystemParamItem<Self::Param>,
|
||||
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
|
||||
match material.as_bind_group(
|
||||
&pipeline.material_layout,
|
||||
|
@ -930,7 +935,6 @@ impl<M: Material> RenderAsset for PreparedMaterial<M> {
|
|||
MeshPipelineKey::READS_VIEW_TRANSMISSION_TEXTURE,
|
||||
material.reads_view_transmission_texture(),
|
||||
);
|
||||
mesh_pipeline_key_bits.insert(alpha_mode_pipeline_key(material.alpha_mode(), msaa));
|
||||
|
||||
Ok(PreparedMaterial {
|
||||
bindings: prepared.bindings,
|
||||
|
|
|
@ -172,7 +172,6 @@ impl Plugin for MeshletPlugin {
|
|||
|
||||
app.init_asset::<MeshletMesh>()
|
||||
.register_asset_loader(MeshletMeshSaverLoader)
|
||||
.insert_resource(Msaa::Off)
|
||||
.add_systems(
|
||||
PostUpdate,
|
||||
check_visibility::<WithMeshletMesh>.in_set(VisibilitySystems::CheckVisibility),
|
||||
|
@ -282,15 +281,20 @@ fn configure_meshlet_views(
|
|||
mut views_3d: Query<(
|
||||
Entity,
|
||||
&mut Camera3d,
|
||||
&Msaa,
|
||||
Has<NormalPrepass>,
|
||||
Has<MotionVectorPrepass>,
|
||||
Has<DeferredPrepass>,
|
||||
)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, mut camera_3d, normal_prepass, motion_vector_prepass, deferred_prepass) in
|
||||
for (entity, mut camera_3d, msaa, normal_prepass, motion_vector_prepass, deferred_prepass) in
|
||||
&mut views_3d
|
||||
{
|
||||
if *msaa != Msaa::Off {
|
||||
panic!("MeshletPlugin can't be used. MSAA is not supported.");
|
||||
}
|
||||
|
||||
let mut usages: TextureUsages = camera_3d.depth_texture_usages.into();
|
||||
usages |= TextureUsages::TEXTURE_BINDING;
|
||||
camera_3d.depth_texture_usages = usages.into();
|
||||
|
|
|
@ -679,7 +679,6 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
|||
prepass_pipeline: Res<PrepassPipeline<M>>,
|
||||
mut pipelines: ResMut<SpecializedMeshPipelines<PrepassPipeline<M>>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_meshes: Res<RenderAssets<RenderMesh>>,
|
||||
render_mesh_instances: Res<RenderMeshInstances>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial<M>>>,
|
||||
|
@ -693,6 +692,7 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
|||
(
|
||||
Entity,
|
||||
&VisibleEntities,
|
||||
&Msaa,
|
||||
Option<&DepthPrepass>,
|
||||
Option<&NormalPrepass>,
|
||||
Option<&MotionVectorPrepass>,
|
||||
|
@ -722,6 +722,7 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
|||
for (
|
||||
view,
|
||||
visible_entities,
|
||||
msaa,
|
||||
depth_prepass,
|
||||
normal_prepass,
|
||||
motion_vector_prepass,
|
||||
|
@ -780,7 +781,7 @@ pub fn queue_prepass_material_meshes<M: Material>(
|
|||
let alpha_mode = material.properties.alpha_mode;
|
||||
match alpha_mode {
|
||||
AlphaMode::Opaque | AlphaMode::AlphaToCoverage | AlphaMode::Mask(_) => {
|
||||
mesh_key |= alpha_mode_pipeline_key(alpha_mode, &msaa);
|
||||
mesh_key |= alpha_mode_pipeline_key(alpha_mode, msaa);
|
||||
}
|
||||
AlphaMode::Blend
|
||||
| AlphaMode::Premultiplied
|
||||
|
|
|
@ -456,6 +456,7 @@ pub fn prepare_mesh_view_bind_groups(
|
|||
Entity,
|
||||
&ViewShadowBindings,
|
||||
&ViewClusterBindings,
|
||||
&Msaa,
|
||||
Option<&ScreenSpaceAmbientOcclusionTextures>,
|
||||
Option<&ViewPrepassTextures>,
|
||||
Option<&ViewTransmissionTexture>,
|
||||
|
@ -469,7 +470,6 @@ pub fn prepare_mesh_view_bind_groups(
|
|||
Res<FallbackImage>,
|
||||
Res<FallbackImageZero>,
|
||||
),
|
||||
msaa: Res<Msaa>,
|
||||
globals_buffer: Res<GlobalsBuffer>,
|
||||
tonemapping_luts: Res<TonemappingLuts>,
|
||||
light_probes_buffer: Res<LightProbesBuffer>,
|
||||
|
@ -501,6 +501,7 @@ pub fn prepare_mesh_view_bind_groups(
|
|||
entity,
|
||||
shadow_bindings,
|
||||
cluster_bindings,
|
||||
msaa,
|
||||
ssao_textures,
|
||||
prepass_textures,
|
||||
transmission_texture,
|
||||
|
|
|
@ -484,17 +484,16 @@ fn extract_ssao_settings(
|
|||
mut commands: Commands,
|
||||
cameras: Extract<
|
||||
Query<
|
||||
(Entity, &Camera, &ScreenSpaceAmbientOcclusionSettings),
|
||||
(Entity, &Camera, &ScreenSpaceAmbientOcclusionSettings, &Msaa),
|
||||
(With<Camera3d>, With<DepthPrepass>, With<NormalPrepass>),
|
||||
>,
|
||||
>,
|
||||
msaa: Extract<Res<Msaa>>,
|
||||
) {
|
||||
for (entity, camera, ssao_settings) in &cameras {
|
||||
if **msaa != Msaa::Off {
|
||||
for (entity, camera, ssao_settings, msaa) in &cameras {
|
||||
if *msaa != Msaa::Off {
|
||||
error!(
|
||||
"SSAO is being used which requires Msaa::Off, but Msaa is currently set to Msaa::{:?}",
|
||||
**msaa
|
||||
*msaa
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -307,6 +307,7 @@ impl ViewNode for VolumetricFogNode {
|
|||
Read<ViewVolumetricFog>,
|
||||
Read<MeshViewBindGroup>,
|
||||
Read<ViewScreenSpaceReflectionsUniformOffset>,
|
||||
Read<Msaa>,
|
||||
Read<ViewEnvironmentMapUniformOffset>,
|
||||
);
|
||||
|
||||
|
@ -325,6 +326,7 @@ impl ViewNode for VolumetricFogNode {
|
|||
view_fog_volumes,
|
||||
view_bind_group,
|
||||
view_ssr_offset,
|
||||
msaa,
|
||||
view_environment_map_offset,
|
||||
): QueryItem<'w, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
|
@ -333,7 +335,6 @@ impl ViewNode for VolumetricFogNode {
|
|||
let volumetric_lighting_pipeline = world.resource::<VolumetricFogPipeline>();
|
||||
let volumetric_lighting_uniform_buffers = world.resource::<VolumetricFogUniformBuffer>();
|
||||
let image_assets = world.resource::<RenderAssets<GpuImage>>();
|
||||
let msaa = world.resource::<Msaa>();
|
||||
let mesh_allocator = world.resource::<MeshAllocator>();
|
||||
|
||||
// Fetch the uniform buffer and binding.
|
||||
|
@ -594,6 +595,7 @@ pub fn prepare_volumetric_fog_pipelines(
|
|||
(
|
||||
Entity,
|
||||
&ExtractedView,
|
||||
&Msaa,
|
||||
Has<NormalPrepass>,
|
||||
Has<DepthPrepass>,
|
||||
Has<MotionVectorPrepass>,
|
||||
|
@ -601,13 +603,19 @@ pub fn prepare_volumetric_fog_pipelines(
|
|||
),
|
||||
With<VolumetricFogSettings>,
|
||||
>,
|
||||
msaa: Res<Msaa>,
|
||||
meshes: Res<RenderAssets<RenderMesh>>,
|
||||
) {
|
||||
let plane_mesh = meshes.get(&PLANE_MESH).expect("Plane mesh not found!");
|
||||
|
||||
for (entity, view, normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass) in
|
||||
view_targets.iter()
|
||||
for (
|
||||
entity,
|
||||
view,
|
||||
msaa,
|
||||
normal_prepass,
|
||||
depth_prepass,
|
||||
motion_vector_prepass,
|
||||
deferred_prepass,
|
||||
) in view_targets.iter()
|
||||
{
|
||||
// Create a mesh pipeline view layout key corresponding to the view.
|
||||
let mut mesh_pipeline_view_key = MeshPipelineViewLayoutKey::from(*msaa);
|
||||
|
|
|
@ -5,12 +5,12 @@ use bevy_asset::{load_internal_asset, Handle};
|
|||
pub use visibility::*;
|
||||
pub use window::*;
|
||||
|
||||
use crate::extract_component::ExtractComponentPlugin;
|
||||
use crate::{
|
||||
camera::{
|
||||
CameraMainTextureUsages, ClearColor, ClearColorConfig, Exposure, ExtractedCamera,
|
||||
ManualTextureViews, MipBias, TemporalJitter,
|
||||
},
|
||||
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
||||
prelude::Shader,
|
||||
primitives::Frustum,
|
||||
render_asset::RenderAssets,
|
||||
|
@ -28,6 +28,7 @@ use bevy_color::LinearRgba;
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_math::{mat3, vec2, vec3, Mat3, Mat4, UVec4, Vec2, Vec3, Vec4, Vec4Swizzles};
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render_macros::ExtractComponent;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bevy_utils::HashMap;
|
||||
use std::{
|
||||
|
@ -107,10 +108,9 @@ impl Plugin for ViewPlugin {
|
|||
.register_type::<Visibility>()
|
||||
.register_type::<VisibleEntities>()
|
||||
.register_type::<ColorGrading>()
|
||||
.init_resource::<Msaa>()
|
||||
// NOTE: windows.is_changed() handles cases where a window was resized
|
||||
.add_plugins((
|
||||
ExtractResourcePlugin::<Msaa>::default(),
|
||||
ExtractComponentPlugin::<Msaa>::default(),
|
||||
VisibilityPlugin,
|
||||
VisibilityRangePlugin,
|
||||
));
|
||||
|
@ -139,24 +139,26 @@ impl Plugin for ViewPlugin {
|
|||
|
||||
/// Configuration resource for [Multi-Sample Anti-Aliasing](https://en.wikipedia.org/wiki/Multisample_anti-aliasing).
|
||||
///
|
||||
/// The number of samples to run for Multi-Sample Anti-Aliasing. Higher numbers result in
|
||||
/// smoother edges.
|
||||
/// Defaults to 4 samples.
|
||||
/// The number of samples to run for Multi-Sample Anti-Aliasing for a given camera. Higher numbers
|
||||
/// result in smoother edges.
|
||||
///
|
||||
/// Defaults to 4 samples. Some advanced rendering features may require that MSAA be disabled.
|
||||
///
|
||||
/// Note that web currently only supports 1 or 4 samples.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use bevy_app::prelude::App;
|
||||
/// # use bevy_render::prelude::Msaa;
|
||||
/// App::new()
|
||||
/// .insert_resource(Msaa::default())
|
||||
/// .run();
|
||||
/// ```
|
||||
#[derive(
|
||||
Resource, Default, Clone, Copy, ExtractResource, Reflect, PartialEq, PartialOrd, Eq, Hash, Debug,
|
||||
Component,
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
ExtractComponent,
|
||||
Reflect,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
Eq,
|
||||
Hash,
|
||||
Debug,
|
||||
)]
|
||||
#[reflect(Resource, Default)]
|
||||
#[reflect(Component, Default)]
|
||||
pub enum Msaa {
|
||||
Off = 1,
|
||||
Sample2 = 2,
|
||||
|
@ -797,7 +799,6 @@ pub fn prepare_view_targets(
|
|||
mut commands: Commands,
|
||||
windows: Res<ExtractedWindows>,
|
||||
images: Res<RenderAssets<GpuImage>>,
|
||||
msaa: Res<Msaa>,
|
||||
clear_color_global: Res<ClearColor>,
|
||||
render_device: Res<RenderDevice>,
|
||||
mut texture_cache: ResMut<TextureCache>,
|
||||
|
@ -806,12 +807,13 @@ pub fn prepare_view_targets(
|
|||
&ExtractedCamera,
|
||||
&ExtractedView,
|
||||
&CameraMainTextureUsages,
|
||||
&Msaa,
|
||||
)>,
|
||||
manual_texture_views: Res<ManualTextureViews>,
|
||||
) {
|
||||
let mut textures = HashMap::default();
|
||||
let mut output_textures = HashMap::default();
|
||||
for (entity, camera, view, texture_usage) in cameras.iter() {
|
||||
for (entity, camera, view, texture_usage, msaa) in cameras.iter() {
|
||||
let (Some(target_size), Some(target)) = (camera.physical_target_size, &camera.target)
|
||||
else {
|
||||
continue;
|
||||
|
@ -847,7 +849,7 @@ pub fn prepare_view_targets(
|
|||
};
|
||||
|
||||
let (a, b, sampled, main_texture) = textures
|
||||
.entry((camera.target.clone(), view.hdr))
|
||||
.entry((camera.target.clone(), view.hdr, msaa))
|
||||
.or_insert_with(|| {
|
||||
let descriptor = TextureDescriptor {
|
||||
label: None,
|
||||
|
|
|
@ -30,8 +30,6 @@ use screenshot::{
|
|||
ScreenshotManager, ScreenshotPlugin, ScreenshotPreparedState, ScreenshotToScreenPipeline,
|
||||
};
|
||||
|
||||
use super::Msaa;
|
||||
|
||||
pub struct WindowRenderPlugin;
|
||||
|
||||
impl Plugin for WindowRenderPlugin {
|
||||
|
@ -250,11 +248,9 @@ pub fn prepare_windows(
|
|||
mut windows: ResMut<ExtractedWindows>,
|
||||
mut window_surfaces: ResMut<WindowSurfaces>,
|
||||
render_device: Res<RenderDevice>,
|
||||
render_adapter: Res<RenderAdapter>,
|
||||
screenshot_pipeline: Res<ScreenshotToScreenPipeline>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<ScreenshotToScreenPipeline>>,
|
||||
mut msaa: ResMut<Msaa>,
|
||||
#[cfg(target_os = "linux")] render_instance: Res<RenderInstance>,
|
||||
) {
|
||||
for window in windows.windows.values_mut() {
|
||||
|
@ -263,35 +259,6 @@ pub fn prepare_windows(
|
|||
continue;
|
||||
};
|
||||
|
||||
// This is an ugly hack to work around drivers that don't support MSAA.
|
||||
// This should be removed once https://github.com/bevyengine/bevy/issues/7194 lands and we're doing proper
|
||||
// feature detection for MSAA.
|
||||
// When removed, we can also remove the `.after(prepare_windows)` of `prepare_core_3d_depth_textures` and `prepare_prepass_textures`
|
||||
let sample_flags = render_adapter
|
||||
.get_texture_format_features(surface_data.configuration.format)
|
||||
.flags;
|
||||
|
||||
if !sample_flags.sample_count_supported(msaa.samples()) {
|
||||
let fallback = if sample_flags.sample_count_supported(Msaa::default().samples()) {
|
||||
Msaa::default()
|
||||
} else {
|
||||
Msaa::Off
|
||||
};
|
||||
|
||||
let fallback_str = if fallback == Msaa::Off {
|
||||
"disabling MSAA".to_owned()
|
||||
} else {
|
||||
format!("MSAA {}x", fallback.samples())
|
||||
};
|
||||
|
||||
bevy_utils::tracing::warn!(
|
||||
"MSAA {}x is not supported on this device. Falling back to {}.",
|
||||
msaa.samples(),
|
||||
fallback_str,
|
||||
);
|
||||
*msaa = fallback;
|
||||
}
|
||||
|
||||
// A recurring issue is hitting `wgpu::SurfaceError::Timeout` on certain Linux
|
||||
// mesa driver implementations. This seems to be a quirk of some drivers.
|
||||
// We'd rather keep panicking when not on Linux mesa, because in those case,
|
||||
|
|
|
@ -369,7 +369,6 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
material2d_pipeline: Res<Material2dPipeline<M>>,
|
||||
mut pipelines: ResMut<SpecializedMeshPipelines<Material2dPipeline<M>>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_meshes: Res<RenderAssets<RenderMesh>>,
|
||||
render_materials: Res<RenderAssets<PreparedMaterial2d<M>>>,
|
||||
mut render_mesh_instances: ResMut<RenderMesh2dInstances>,
|
||||
|
@ -379,6 +378,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
Entity,
|
||||
&ExtractedView,
|
||||
&VisibleEntities,
|
||||
&Msaa,
|
||||
Option<&Tonemapping>,
|
||||
Option<&DebandDither>,
|
||||
)>,
|
||||
|
@ -389,7 +389,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
|
|||
return;
|
||||
}
|
||||
|
||||
for (view_entity, view, visible_entities, tonemapping, dither) in &mut views {
|
||||
for (view_entity, view, visible_entities, msaa, tonemapping, dither) in &mut views {
|
||||
let Some(transparent_phase) = transparent_render_phases.get_mut(&view_entity) else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
@ -472,26 +472,25 @@ pub fn queue_sprites(
|
|||
sprite_pipeline: Res<SpritePipeline>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<SpritePipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
extracted_sprites: Res<ExtractedSprites>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
|
||||
mut views: Query<(
|
||||
Entity,
|
||||
&VisibleEntities,
|
||||
&ExtractedView,
|
||||
&Msaa,
|
||||
Option<&Tonemapping>,
|
||||
Option<&DebandDither>,
|
||||
)>,
|
||||
) {
|
||||
let msaa_key = SpritePipelineKey::from_msaa_samples(msaa.samples());
|
||||
|
||||
let draw_sprite_function = draw_functions.read().id::<DrawSprite>();
|
||||
|
||||
for (view_entity, visible_entities, view, tonemapping, dither) in &mut views {
|
||||
for (view_entity, visible_entities, view, msaa, tonemapping, dither) in &mut views {
|
||||
let Some(transparent_phase) = transparent_render_phases.get_mut(&view_entity) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let msaa_key = SpritePipelineKey::from_msaa_samples(msaa.samples());
|
||||
let mut view_key = SpritePipelineKey::from_hdr(view.hdr) | msaa_key;
|
||||
|
||||
if !view.hdr {
|
||||
|
|
|
@ -351,17 +351,16 @@ pub fn queue_colored_mesh2d(
|
|||
colored_mesh2d_pipeline: Res<ColoredMesh2dPipeline>,
|
||||
mut pipelines: ResMut<SpecializedRenderPipelines<ColoredMesh2dPipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
msaa: Res<Msaa>,
|
||||
render_meshes: Res<RenderAssets<RenderMesh>>,
|
||||
render_mesh_instances: Res<RenderColoredMesh2dInstances>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
|
||||
mut views: Query<(Entity, &VisibleEntities, &ExtractedView)>,
|
||||
mut views: Query<(Entity, &VisibleEntities, &ExtractedView, &Msaa)>,
|
||||
) {
|
||||
if render_mesh_instances.is_empty() {
|
||||
return;
|
||||
}
|
||||
// Iterate each view (a camera is a view)
|
||||
for (view_entity, visible_entities, view) in &mut views {
|
||||
for (view_entity, visible_entities, view, msaa) in &mut views {
|
||||
let Some(transparent_phase) = transparent_render_phases.get_mut(&view_entity) else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
@ -29,7 +29,6 @@ const HIGH_RES_LAYERS: RenderLayers = RenderLayers::layer(1);
|
|||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))
|
||||
.insert_resource(Msaa::Off)
|
||||
.add_systems(Startup, (setup_camera, setup_sprite, setup_mesh))
|
||||
.add_systems(Update, (rotate, fit_canvas))
|
||||
.run();
|
||||
|
@ -131,6 +130,7 @@ fn setup_camera(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
|
|||
target: RenderTarget::Image(image_handle.clone()),
|
||||
..default()
|
||||
},
|
||||
msaa: Msaa::Off,
|
||||
..default()
|
||||
},
|
||||
InGameCamera,
|
||||
|
@ -149,7 +149,14 @@ fn setup_camera(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
|
|||
|
||||
// the "outer" camera renders whatever is on `HIGH_RES_LAYERS` to the screen.
|
||||
// here, the canvas and one of the sample sprites will be rendered by this camera
|
||||
commands.spawn((Camera2dBundle::default(), OuterCamera, HIGH_RES_LAYERS));
|
||||
commands.spawn((
|
||||
Camera2dBundle {
|
||||
msaa: Msaa::Off,
|
||||
..default()
|
||||
},
|
||||
OuterCamera,
|
||||
HIGH_RES_LAYERS,
|
||||
));
|
||||
}
|
||||
|
||||
/// Rotates entities to demonstrate grid snapping.
|
||||
|
|
|
@ -23,7 +23,6 @@ use bevy::{
|
|||
|
||||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(Msaa::Off)
|
||||
.add_plugins((DefaultPlugins, TemporalAntiAliasPlugin))
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, (modify_aa, modify_sharpening, update_ui))
|
||||
|
@ -38,13 +37,13 @@ fn modify_aa(
|
|||
Option<&mut Fxaa>,
|
||||
Option<&mut SmaaSettings>,
|
||||
Option<&TemporalAntiAliasSettings>,
|
||||
&mut Msaa,
|
||||
),
|
||||
With<Camera>,
|
||||
>,
|
||||
mut msaa: ResMut<Msaa>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
let (camera_entity, fxaa, smaa, taa) = camera.single_mut();
|
||||
let (camera_entity, fxaa, smaa, taa, mut msaa) = camera.single_mut();
|
||||
let mut camera = commands.entity(camera_entity);
|
||||
|
||||
// No AA
|
||||
|
@ -176,13 +175,13 @@ fn update_ui(
|
|||
Option<&SmaaSettings>,
|
||||
Option<&TemporalAntiAliasSettings>,
|
||||
&ContrastAdaptiveSharpeningSettings,
|
||||
&Msaa,
|
||||
),
|
||||
With<Camera>,
|
||||
>,
|
||||
msaa: Res<Msaa>,
|
||||
mut ui: Query<&mut Text>,
|
||||
) {
|
||||
let (fxaa, smaa, taa, cas_settings) = camera.single();
|
||||
let (fxaa, smaa, taa, cas_settings, msaa) = camera.single();
|
||||
|
||||
let mut ui = ui.single_mut();
|
||||
let ui = &mut ui.sections[0].value;
|
||||
|
|
|
@ -17,7 +17,6 @@ use bevy::{
|
|||
|
||||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(Msaa::Off)
|
||||
.insert_resource(DefaultOpaqueRendererMethod::deferred())
|
||||
.insert_resource(DirectionalLightShadowMap { size: 4096 })
|
||||
.add_plugins(DefaultPlugins)
|
||||
|
@ -42,6 +41,8 @@ fn setup(
|
|||
},
|
||||
transform: Transform::from_xyz(0.7, 0.7, 1.0)
|
||||
.looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y),
|
||||
// MSAA needs to be off for Deferred rendering
|
||||
msaa: Msaa::Off,
|
||||
..default()
|
||||
},
|
||||
FogSettings {
|
||||
|
|
|
@ -98,7 +98,6 @@ fn main() {
|
|||
// reflections at this time. Disable multisampled antialiasing, as deferred
|
||||
// rendering doesn't support that.
|
||||
App::new()
|
||||
.insert_resource(Msaa::Off)
|
||||
.insert_resource(DefaultOpaqueRendererMethod::deferred())
|
||||
.init_resource::<AppSettings>()
|
||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||
|
@ -236,6 +235,7 @@ fn spawn_camera(commands: &mut Commands, asset_server: &AssetServer) {
|
|||
hdr: true,
|
||||
..default()
|
||||
},
|
||||
msaa: Msaa::Off,
|
||||
..default()
|
||||
})
|
||||
.insert(EnvironmentMapLight {
|
||||
|
|
|
@ -57,8 +57,7 @@ fn main() {
|
|||
// it _greatly enhances_ the look of the resulting blur effects.
|
||||
// Sadly, it's not available under WebGL.
|
||||
#[cfg(not(all(feature = "webgl2", target_arch = "wasm32")))]
|
||||
app.insert_resource(Msaa::Off)
|
||||
.add_plugins(TemporalAntiAliasPlugin);
|
||||
app.add_plugins(TemporalAntiAliasPlugin);
|
||||
|
||||
app.run();
|
||||
}
|
||||
|
@ -352,6 +351,8 @@ fn setup(
|
|||
},
|
||||
tonemapping: Tonemapping::TonyMcMapface,
|
||||
exposure: Exposure { ev100: 6.0 },
|
||||
#[cfg(not(all(feature = "webgl2", target_arch = "wasm32")))]
|
||||
msaa: Msaa::Off,
|
||||
..default()
|
||||
},
|
||||
#[cfg(not(all(feature = "webgl2", target_arch = "wasm32")))]
|
||||
|
|
|
@ -6,7 +6,6 @@ use bevy::prelude::*;
|
|||
|
||||
fn main() {
|
||||
App::new()
|
||||
.insert_resource(Msaa::default())
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, fade_transparency)
|
||||
|
@ -100,6 +99,7 @@ fn setup(
|
|||
// Camera
|
||||
commands.spawn(Camera3dBundle {
|
||||
transform: Transform::from_xyz(-2.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
msaa: Msaa::Off,
|
||||
..default()
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,14 +23,8 @@ fn main() {
|
|||
..default()
|
||||
}))
|
||||
.add_systems(Startup, (setup_scene, setup_music))
|
||||
.add_systems(Update, (touch_camera, button_handler, handle_lifetime));
|
||||
|
||||
// MSAA makes some Android devices panic, this is under investigation
|
||||
// https://github.com/bevyengine/bevy/issues/8229
|
||||
#[cfg(target_os = "android")]
|
||||
app.insert_resource(Msaa::Off);
|
||||
|
||||
app.run();
|
||||
.add_systems(Update, (touch_camera, button_handler, handle_lifetime))
|
||||
.run();
|
||||
}
|
||||
|
||||
fn touch_camera(
|
||||
|
@ -109,6 +103,10 @@ fn setup_scene(
|
|||
// camera
|
||||
commands.spawn(Camera3dBundle {
|
||||
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
// MSAA makes some Android devices panic, this is under investigation
|
||||
// https://github.com/bevyengine/bevy/issues/8229
|
||||
#[cfg(target_os = "android")]
|
||||
msaa: Msaa::Off,
|
||||
..default()
|
||||
});
|
||||
|
||||
|
|
|
@ -233,11 +233,10 @@ fn prepare_custom_phase_item_buffers(mut commands: Commands) {
|
|||
fn queue_custom_phase_item(
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
custom_phase_pipeline: Res<CustomPhasePipeline>,
|
||||
msaa: Res<Msaa>,
|
||||
mut opaque_render_phases: ResMut<ViewBinnedRenderPhases<Opaque3d>>,
|
||||
opaque_draw_functions: Res<DrawFunctions<Opaque3d>>,
|
||||
mut specialized_render_pipelines: ResMut<SpecializedRenderPipelines<CustomPhasePipeline>>,
|
||||
views: Query<(Entity, &VisibleEntities), With<ExtractedView>>,
|
||||
views: Query<(Entity, &VisibleEntities, &Msaa), With<ExtractedView>>,
|
||||
) {
|
||||
let draw_custom_phase_item = opaque_draw_functions
|
||||
.read()
|
||||
|
@ -246,7 +245,7 @@ fn queue_custom_phase_item(
|
|||
// Render phases are per-view, so we need to iterate over all views so that
|
||||
// the entity appears in them. (In this example, we have only one view, but
|
||||
// it's good practice to loop over all views anyway.)
|
||||
for (view_entity, view_visible_entities) in views.iter() {
|
||||
for (view_entity, view_visible_entities, msaa) in views.iter() {
|
||||
let Some(opaque_phase) = opaque_render_phases.get_mut(&view_entity) else {
|
||||
continue;
|
||||
};
|
||||
|
|
|
@ -116,24 +116,23 @@ struct InstanceData {
|
|||
fn queue_custom(
|
||||
transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>,
|
||||
custom_pipeline: Res<CustomPipeline>,
|
||||
msaa: Res<Msaa>,
|
||||
mut pipelines: ResMut<SpecializedMeshPipelines<CustomPipeline>>,
|
||||
pipeline_cache: Res<PipelineCache>,
|
||||
meshes: Res<RenderAssets<RenderMesh>>,
|
||||
render_mesh_instances: Res<RenderMeshInstances>,
|
||||
material_meshes: Query<Entity, With<InstanceMaterialData>>,
|
||||
mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent3d>>,
|
||||
mut views: Query<(Entity, &ExtractedView)>,
|
||||
mut views: Query<(Entity, &ExtractedView, &Msaa)>,
|
||||
) {
|
||||
let draw_custom = transparent_3d_draw_functions.read().id::<DrawCustom>();
|
||||
|
||||
let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples());
|
||||
|
||||
for (view_entity, view) in &mut views {
|
||||
for (view_entity, view, msaa) in &mut views {
|
||||
let Some(transparent_phase) = transparent_render_phases.get_mut(&view_entity) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples());
|
||||
|
||||
let view_key = msaa_key | MeshPipelineKey::from_hdr(view.hdr);
|
||||
let rangefinder = view.rangefinder3d();
|
||||
for entity in &material_meshes {
|
||||
|
|
|
@ -34,8 +34,6 @@ fn main() {
|
|||
))
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, (rotate, toggle_prepass_view))
|
||||
// Disabling MSAA for maximum compatibility. Shader prepass with MSAA needs GPU capability MULTISAMPLED_SHADING
|
||||
.insert_resource(Msaa::Off)
|
||||
.run();
|
||||
}
|
||||
|
||||
|
@ -52,6 +50,8 @@ fn setup(
|
|||
commands.spawn((
|
||||
Camera3dBundle {
|
||||
transform: Transform::from_xyz(-2.0, 3., 5.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||
// Disabling MSAA for maximum compatibility. Shader prepass with MSAA needs GPU capability MULTISAMPLED_SHADING
|
||||
msaa: Msaa::Off,
|
||||
..default()
|
||||
},
|
||||
// To enable the prepass you need to add the components associated with the ones you need
|
||||
|
|
Loading…
Add table
Reference in a new issue