render: add MSAA support
This commit is contained in:
parent
a2c1a90695
commit
ca87359c6e
@ -63,6 +63,10 @@ path = "examples/2d/texture_atlas.rs"
|
|||||||
name = "load_model"
|
name = "load_model"
|
||||||
path = "examples/3d/load_model.rs"
|
path = "examples/3d/load_model.rs"
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "msaa"
|
||||||
|
path = "examples/3d/msaa.rs"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "parenting"
|
name = "parenting"
|
||||||
path = "examples/3d/parenting.rs"
|
path = "examples/3d/parenting.rs"
|
||||||
|
|||||||
@ -15,6 +15,7 @@ pub use once_cell;
|
|||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
base::Msaa,
|
||||||
color::Color,
|
color::Color,
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
entity::*,
|
entity::*,
|
||||||
@ -26,6 +27,7 @@ pub mod prelude {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use base::Msaa;
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_asset::AddAsset;
|
use bevy_asset::AddAsset;
|
||||||
use bevy_ecs::{IntoQuerySystem, IntoThreadLocalSystem};
|
use bevy_ecs::{IntoQuerySystem, IntoThreadLocalSystem};
|
||||||
@ -131,10 +133,15 @@ impl AppPlugin for RenderPlugin {
|
|||||||
shader::clear_shader_defs_system.system(),
|
shader::clear_shader_defs_system.system(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if app.resources().get::<Msaa>().is_none() {
|
||||||
|
app.init_resource::<Msaa>();
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ref config) = self.base_render_graph_config {
|
if let Some(ref config) = self.base_render_graph_config {
|
||||||
let resources = app.resources();
|
let resources = app.resources();
|
||||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||||
render_graph.add_base_graph(config);
|
let msaa = resources.get::<Msaa>().unwrap();
|
||||||
|
render_graph.add_base_graph(config, &msaa);
|
||||||
let mut active_cameras = resources.get_mut::<ActiveCameras>().unwrap();
|
let mut active_cameras = resources.get_mut::<ActiveCameras>().unwrap();
|
||||||
if config.add_3d_camera {
|
if config.add_3d_camera {
|
||||||
active_cameras.add(base::camera::CAMERA3D);
|
active_cameras.add(base::camera::CAMERA3D);
|
||||||
|
|||||||
@ -7,11 +7,23 @@ use bevy_asset::{Assets, Handle};
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Debug, Default)]
|
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||||
pub struct PipelineSpecialization {
|
pub struct PipelineSpecialization {
|
||||||
pub shader_specialization: ShaderSpecialization,
|
pub shader_specialization: ShaderSpecialization,
|
||||||
pub primitive_topology: PrimitiveTopology,
|
pub primitive_topology: PrimitiveTopology,
|
||||||
pub dynamic_bindings: Vec<DynamicBinding>,
|
pub dynamic_bindings: Vec<DynamicBinding>,
|
||||||
|
pub sample_count: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PipelineSpecialization {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
sample_count: 1,
|
||||||
|
shader_specialization: Default::default(),
|
||||||
|
primitive_topology: Default::default(),
|
||||||
|
dynamic_bindings: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PipelineSpecialization {
|
impl PipelineSpecialization {
|
||||||
@ -145,6 +157,8 @@ impl PipelineCompiler {
|
|||||||
Some(vertex_buffer_descriptors),
|
Some(vertex_buffer_descriptors),
|
||||||
&pipeline_specialization.dynamic_bindings,
|
&pipeline_specialization.dynamic_bindings,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
specialized_descriptor.sample_count = pipeline_specialization.sample_count;
|
||||||
specialized_descriptor.primitive_topology = pipeline_specialization.primitive_topology;
|
specialized_descriptor.primitive_topology = pipeline_specialization.primitive_topology;
|
||||||
|
|
||||||
let specialized_pipeline_handle = pipelines.add(specialized_descriptor);
|
let specialized_pipeline_handle = pipelines.add(specialized_descriptor);
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
use super::{PipelineDescriptor, PipelineSpecialization};
|
use super::{PipelineDescriptor, PipelineSpecialization};
|
||||||
use crate::{
|
use crate::{
|
||||||
draw::{Draw, DrawContext, DrawError, Drawable},
|
draw::{Draw, DrawContext, DrawError, Drawable},
|
||||||
renderer::RenderResourceBindings,
|
renderer::RenderResourceBindings, prelude::Msaa,
|
||||||
};
|
};
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_ecs::{Query, ResMut};
|
use bevy_ecs::{Query, ResMut, Res};
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
#[derive(Properties, Default, Clone)]
|
#[derive(Properties, Default, Clone)]
|
||||||
pub struct RenderPipeline {
|
pub struct RenderPipeline {
|
||||||
@ -104,9 +104,14 @@ impl<'a> Drawable for DrawableRenderPipelines<'a> {
|
|||||||
pub fn draw_render_pipelines_system(
|
pub fn draw_render_pipelines_system(
|
||||||
mut draw_context: DrawContext,
|
mut draw_context: DrawContext,
|
||||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||||
|
msaa: Res<Msaa>,
|
||||||
mut query: Query<(&mut Draw, &mut RenderPipelines)>,
|
mut query: Query<(&mut Draw, &mut RenderPipelines)>,
|
||||||
) {
|
) {
|
||||||
for (mut draw, mut render_pipelines) in &mut query.iter() {
|
for (mut draw, mut render_pipelines) in &mut query.iter() {
|
||||||
|
for pipeline in render_pipelines.pipelines.iter_mut() {
|
||||||
|
pipeline.specialization.sample_count = msaa.samples;
|
||||||
|
}
|
||||||
|
|
||||||
let mut drawable = DrawableRenderPipelines {
|
let mut drawable = DrawableRenderPipelines {
|
||||||
render_pipelines: &mut render_pipelines,
|
render_pipelines: &mut render_pipelines,
|
||||||
render_resource_bindings: &mut render_resource_bindings,
|
render_resource_bindings: &mut render_resource_bindings,
|
||||||
|
|||||||
@ -13,6 +13,18 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use bevy_window::WindowId;
|
use bevy_window::WindowId;
|
||||||
|
|
||||||
|
pub struct Msaa {
|
||||||
|
pub samples: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Msaa {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
samples: 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BaseRenderGraphConfig {
|
pub struct BaseRenderGraphConfig {
|
||||||
pub add_2d_camera: bool,
|
pub add_2d_camera: bool,
|
||||||
pub add_3d_camera: bool,
|
pub add_3d_camera: bool,
|
||||||
@ -28,6 +40,7 @@ pub mod node {
|
|||||||
pub const CAMERA2D: &str = "camera2d";
|
pub const CAMERA2D: &str = "camera2d";
|
||||||
pub const TEXTURE_COPY: &str = "texture_copy";
|
pub const TEXTURE_COPY: &str = "texture_copy";
|
||||||
pub const MAIN_DEPTH_TEXTURE: &str = "main_pass_depth_texture";
|
pub const MAIN_DEPTH_TEXTURE: &str = "main_pass_depth_texture";
|
||||||
|
pub const MAIN_SAMPLED_COLOR_ATTACHMENT: &str = "main_pass_sampled_color_attachment";
|
||||||
pub const MAIN_PASS: &str = "main_pass";
|
pub const MAIN_PASS: &str = "main_pass";
|
||||||
pub const SHARED_BUFFERS: &str = "shared_buffers";
|
pub const SHARED_BUFFERS: &str = "shared_buffers";
|
||||||
}
|
}
|
||||||
@ -53,11 +66,11 @@ impl Default for BaseRenderGraphConfig {
|
|||||||
/// By itself this graph doesn't do much, but it allows Render plugins to interop with each other by having a common
|
/// By itself this graph doesn't do much, but it allows Render plugins to interop with each other by having a common
|
||||||
/// set of nodes. It can be customized using `BaseRenderGraphConfig`.
|
/// set of nodes. It can be customized using `BaseRenderGraphConfig`.
|
||||||
pub trait BaseRenderGraphBuilder {
|
pub trait BaseRenderGraphBuilder {
|
||||||
fn add_base_graph(&mut self, config: &BaseRenderGraphConfig) -> &mut Self;
|
fn add_base_graph(&mut self, config: &BaseRenderGraphConfig, msaa: &Msaa) -> &mut Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseRenderGraphBuilder for RenderGraph {
|
impl BaseRenderGraphBuilder for RenderGraph {
|
||||||
fn add_base_graph(&mut self, config: &BaseRenderGraphConfig) -> &mut Self {
|
fn add_base_graph(&mut self, config: &BaseRenderGraphConfig, msaa: &Msaa) -> &mut Self {
|
||||||
self.add_node(node::TEXTURE_COPY, TextureCopyNode::default());
|
self.add_node(node::TEXTURE_COPY, TextureCopyNode::default());
|
||||||
if config.add_3d_camera {
|
if config.add_3d_camera {
|
||||||
self.add_system_node(node::CAMERA3D, CameraNode::new(camera::CAMERA3D));
|
self.add_system_node(node::CAMERA3D, CameraNode::new(camera::CAMERA3D));
|
||||||
@ -80,7 +93,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
|
|||||||
height: 1,
|
height: 1,
|
||||||
},
|
},
|
||||||
mip_level_count: 1,
|
mip_level_count: 1,
|
||||||
sample_count: 1,
|
sample_count: msaa.samples,
|
||||||
dimension: TextureDimension::D2,
|
dimension: TextureDimension::D2,
|
||||||
format: TextureFormat::Depth32Float, // PERF: vulkan docs recommend using 24 bit depth for better performance
|
format: TextureFormat::Depth32Float, // PERF: vulkan docs recommend using 24 bit depth for better performance
|
||||||
usage: TextureUsage::OUTPUT_ATTACHMENT,
|
usage: TextureUsage::OUTPUT_ATTACHMENT,
|
||||||
@ -90,15 +103,29 @@ impl BaseRenderGraphBuilder for RenderGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.add_main_pass {
|
if config.add_main_pass {
|
||||||
let mut main_pass_node = PassNode::<&MainPass>::new(PassDescriptor {
|
let color_attachment = if msaa.samples > 1 {
|
||||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
RenderPassColorAttachmentDescriptor {
|
||||||
attachment: TextureAttachment::Input("color".to_string()),
|
attachment: TextureAttachment::Input("color_attachment".to_string()),
|
||||||
|
resolve_target: Some(TextureAttachment::Input(
|
||||||
|
"color_resolve_target".to_string(),
|
||||||
|
)),
|
||||||
|
ops: Operations {
|
||||||
|
load: LoadOp::Clear(Color::rgb(0.1, 0.1, 0.1)),
|
||||||
|
store: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RenderPassColorAttachmentDescriptor {
|
||||||
|
attachment: TextureAttachment::Input("color_attachment".to_string()),
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: Operations {
|
ops: Operations {
|
||||||
load: LoadOp::Clear(Color::rgb(0.1, 0.1, 0.1)),
|
load: LoadOp::Clear(Color::rgb(0.1, 0.1, 0.1)),
|
||||||
store: true,
|
store: true,
|
||||||
},
|
},
|
||||||
}],
|
}
|
||||||
|
};
|
||||||
|
let mut main_pass_node = PassNode::<&MainPass>::new(PassDescriptor {
|
||||||
|
color_attachments: vec![color_attachment],
|
||||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||||
attachment: TextureAttachment::Input("depth".to_string()),
|
attachment: TextureAttachment::Input("depth".to_string()),
|
||||||
depth_ops: Some(Operations {
|
depth_ops: Some(Operations {
|
||||||
@ -107,7 +134,7 @@ impl BaseRenderGraphBuilder for RenderGraph {
|
|||||||
}),
|
}),
|
||||||
stencil_ops: None,
|
stencil_ops: None,
|
||||||
}),
|
}),
|
||||||
sample_count: 1,
|
sample_count: msaa.samples,
|
||||||
});
|
});
|
||||||
|
|
||||||
main_pass_node.use_default_clear_color(0);
|
main_pass_node.use_default_clear_color(0);
|
||||||
@ -146,7 +173,40 @@ impl BaseRenderGraphBuilder for RenderGraph {
|
|||||||
node::PRIMARY_SWAP_CHAIN,
|
node::PRIMARY_SWAP_CHAIN,
|
||||||
WindowSwapChainNode::OUT_TEXTURE,
|
WindowSwapChainNode::OUT_TEXTURE,
|
||||||
node::MAIN_PASS,
|
node::MAIN_PASS,
|
||||||
"color",
|
if msaa.samples > 1 {
|
||||||
|
"color_resolve_target"
|
||||||
|
} else {
|
||||||
|
"color_attachment"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if msaa.samples > 1 {
|
||||||
|
self.add_node(
|
||||||
|
node::MAIN_SAMPLED_COLOR_ATTACHMENT,
|
||||||
|
WindowTextureNode::new(
|
||||||
|
WindowId::primary(),
|
||||||
|
TextureDescriptor {
|
||||||
|
size: Extent3d {
|
||||||
|
depth: 1,
|
||||||
|
width: 1,
|
||||||
|
height: 1,
|
||||||
|
},
|
||||||
|
mip_level_count: 1,
|
||||||
|
sample_count: msaa.samples,
|
||||||
|
dimension: TextureDimension::D2,
|
||||||
|
format: TextureFormat::Bgra8UnormSrgb,
|
||||||
|
usage: TextureUsage::OUTPUT_ATTACHMENT,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.add_slot_edge(
|
||||||
|
node::MAIN_SAMPLED_COLOR_ATTACHMENT,
|
||||||
|
WindowSwapChainNode::OUT_TEXTURE,
|
||||||
|
node::MAIN_PASS,
|
||||||
|
"color_attachment",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ pub struct PassNode<Q: HecsQuery> {
|
|||||||
inputs: Vec<ResourceSlotInfo>,
|
inputs: Vec<ResourceSlotInfo>,
|
||||||
cameras: Vec<CameraInfo>,
|
cameras: Vec<CameraInfo>,
|
||||||
color_attachment_input_indices: Vec<Option<usize>>,
|
color_attachment_input_indices: Vec<Option<usize>>,
|
||||||
|
color_resolve_target_indices: Vec<Option<usize>>,
|
||||||
depth_stencil_attachment_input_index: Option<usize>,
|
depth_stencil_attachment_input_index: Option<usize>,
|
||||||
default_clear_color_inputs: Vec<usize>,
|
default_clear_color_inputs: Vec<usize>,
|
||||||
camera_bind_group_descriptor: BindGroupDescriptor,
|
camera_bind_group_descriptor: BindGroupDescriptor,
|
||||||
@ -34,26 +35,37 @@ impl<Q: HecsQuery> PassNode<Q> {
|
|||||||
pub fn new(descriptor: PassDescriptor) -> Self {
|
pub fn new(descriptor: PassDescriptor) -> Self {
|
||||||
let mut inputs = Vec::new();
|
let mut inputs = Vec::new();
|
||||||
let mut color_attachment_input_indices = Vec::new();
|
let mut color_attachment_input_indices = Vec::new();
|
||||||
|
let mut color_resolve_target_indices = Vec::new();
|
||||||
for color_attachment in descriptor.color_attachments.iter() {
|
for color_attachment in descriptor.color_attachments.iter() {
|
||||||
if let TextureAttachment::Input(ref name) = color_attachment.attachment {
|
if let TextureAttachment::Input(ref name) = color_attachment.attachment {
|
||||||
|
color_attachment_input_indices.push(Some(inputs.len()));
|
||||||
inputs.push(ResourceSlotInfo::new(
|
inputs.push(ResourceSlotInfo::new(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
RenderResourceType::Texture,
|
RenderResourceType::Texture,
|
||||||
));
|
));
|
||||||
color_attachment_input_indices.push(Some(inputs.len() - 1));
|
|
||||||
} else {
|
} else {
|
||||||
color_attachment_input_indices.push(None);
|
color_attachment_input_indices.push(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(TextureAttachment::Input(ref name)) = color_attachment.resolve_target {
|
||||||
|
color_resolve_target_indices.push(Some(inputs.len()));
|
||||||
|
inputs.push(ResourceSlotInfo::new(
|
||||||
|
name.to_string(),
|
||||||
|
RenderResourceType::Texture,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
color_resolve_target_indices.push(None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut depth_stencil_attachment_input_index = None;
|
let mut depth_stencil_attachment_input_index = None;
|
||||||
if let Some(ref depth_stencil_attachment) = descriptor.depth_stencil_attachment {
|
if let Some(ref depth_stencil_attachment) = descriptor.depth_stencil_attachment {
|
||||||
if let TextureAttachment::Input(ref name) = depth_stencil_attachment.attachment {
|
if let TextureAttachment::Input(ref name) = depth_stencil_attachment.attachment {
|
||||||
|
depth_stencil_attachment_input_index = Some(inputs.len());
|
||||||
inputs.push(ResourceSlotInfo::new(
|
inputs.push(ResourceSlotInfo::new(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
RenderResourceType::Texture,
|
RenderResourceType::Texture,
|
||||||
));
|
));
|
||||||
depth_stencil_attachment_input_index = Some(inputs.len() - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,6 +86,7 @@ impl<Q: HecsQuery> PassNode<Q> {
|
|||||||
inputs,
|
inputs,
|
||||||
cameras: Vec::new(),
|
cameras: Vec::new(),
|
||||||
color_attachment_input_indices,
|
color_attachment_input_indices,
|
||||||
|
color_resolve_target_indices,
|
||||||
depth_stencil_attachment_input_index,
|
depth_stencil_attachment_input_index,
|
||||||
default_clear_color_inputs: Vec::new(),
|
default_clear_color_inputs: Vec::new(),
|
||||||
camera_bind_group_descriptor,
|
camera_bind_group_descriptor,
|
||||||
@ -120,6 +133,10 @@ impl<Q: HecsQuery + Send + Sync + 'static> Node for PassNode<Q> {
|
|||||||
color_attachment.attachment =
|
color_attachment.attachment =
|
||||||
TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap());
|
TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap());
|
||||||
}
|
}
|
||||||
|
if let Some(input_index) = self.color_resolve_target_indices[i] {
|
||||||
|
color_attachment.resolve_target =
|
||||||
|
Some(TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(input_index) = self.depth_stencil_attachment_input_index {
|
if let Some(input_index) = self.depth_stencil_attachment_input_index {
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use bevy_render::{
|
|||||||
renderer::{
|
renderer::{
|
||||||
AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings,
|
AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings,
|
||||||
RenderResourceId,
|
RenderResourceId,
|
||||||
},
|
}, prelude::Msaa,
|
||||||
};
|
};
|
||||||
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
|
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
|
||||||
|
|
||||||
@ -38,6 +38,7 @@ pub struct DrawableText<'a> {
|
|||||||
pub container_size: Vec2,
|
pub container_size: Vec2,
|
||||||
pub style: &'a TextStyle,
|
pub style: &'a TextStyle,
|
||||||
pub text: &'a str,
|
pub text: &'a str,
|
||||||
|
pub msaa: &'a Msaa,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Drawable for DrawableText<'a> {
|
impl<'a> Drawable for DrawableText<'a> {
|
||||||
@ -45,8 +46,10 @@ impl<'a> Drawable for DrawableText<'a> {
|
|||||||
context.set_pipeline(
|
context.set_pipeline(
|
||||||
draw,
|
draw,
|
||||||
bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE,
|
bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE,
|
||||||
// TODO: remove this shader def specialization when its easier to manually bind global render resources to specific bind groups
|
&PipelineSpecialization {
|
||||||
&PipelineSpecialization::default(),
|
sample_count: self.msaa.samples,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let render_resource_context = &**context.render_resource_context;
|
let render_resource_context = &**context.render_resource_context;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ use bevy_render::{
|
|||||||
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
||||||
},
|
},
|
||||||
pipeline::*,
|
pipeline::*,
|
||||||
|
prelude::Msaa,
|
||||||
render_graph::{
|
render_graph::{
|
||||||
base, CameraNode, PassNode, RenderGraph, RenderResourcesNode, WindowSwapChainNode,
|
base, CameraNode, PassNode, RenderGraph, RenderResourcesNode, WindowSwapChainNode,
|
||||||
WindowTextureNode,
|
WindowTextureNode,
|
||||||
@ -82,17 +83,31 @@ impl UiRenderGraphBuilder for RenderGraph {
|
|||||||
fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self {
|
fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||||
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
||||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||||
|
let msaa = resources.get::<Msaa>().unwrap();
|
||||||
pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders));
|
pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders));
|
||||||
|
|
||||||
let mut ui_pass_node = PassNode::<&Node>::new(PassDescriptor {
|
let color_attachment = if msaa.samples > 1 {
|
||||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
RenderPassColorAttachmentDescriptor {
|
||||||
attachment: TextureAttachment::Input("color".to_string()),
|
attachment: TextureAttachment::Input("color_attachment".to_string()),
|
||||||
|
resolve_target: Some(TextureAttachment::Input("color_resolve_target".to_string())),
|
||||||
|
ops: Operations {
|
||||||
|
load: LoadOp::Load,
|
||||||
|
store: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RenderPassColorAttachmentDescriptor {
|
||||||
|
attachment: TextureAttachment::Input("color_attachment".to_string()),
|
||||||
resolve_target: None,
|
resolve_target: None,
|
||||||
ops: Operations {
|
ops: Operations {
|
||||||
load: LoadOp::Load,
|
load: LoadOp::Load,
|
||||||
store: true,
|
store: true,
|
||||||
},
|
},
|
||||||
}],
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut ui_pass_node = PassNode::<&Node>::new(PassDescriptor {
|
||||||
|
color_attachments: vec![color_attachment],
|
||||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||||
attachment: TextureAttachment::Input("depth".to_string()),
|
attachment: TextureAttachment::Input("depth".to_string()),
|
||||||
depth_ops: Some(Operations {
|
depth_ops: Some(Operations {
|
||||||
@ -101,7 +116,7 @@ impl UiRenderGraphBuilder for RenderGraph {
|
|||||||
}),
|
}),
|
||||||
stencil_ops: None,
|
stencil_ops: None,
|
||||||
}),
|
}),
|
||||||
sample_count: 1,
|
sample_count: msaa.samples,
|
||||||
});
|
});
|
||||||
ui_pass_node.add_camera(camera::UI_CAMERA);
|
ui_pass_node.add_camera(camera::UI_CAMERA);
|
||||||
self.add_node(node::UI_PASS, ui_pass_node);
|
self.add_node(node::UI_PASS, ui_pass_node);
|
||||||
@ -110,7 +125,11 @@ impl UiRenderGraphBuilder for RenderGraph {
|
|||||||
base::node::PRIMARY_SWAP_CHAIN,
|
base::node::PRIMARY_SWAP_CHAIN,
|
||||||
WindowSwapChainNode::OUT_TEXTURE,
|
WindowSwapChainNode::OUT_TEXTURE,
|
||||||
node::UI_PASS,
|
node::UI_PASS,
|
||||||
"color",
|
if msaa.samples > 1 {
|
||||||
|
"color_resolve_target"
|
||||||
|
} else {
|
||||||
|
"color_attachment"
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -122,6 +141,17 @@ impl UiRenderGraphBuilder for RenderGraph {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
if msaa.samples > 1 {
|
||||||
|
self.add_slot_edge(
|
||||||
|
base::node::MAIN_SAMPLED_COLOR_ATTACHMENT,
|
||||||
|
WindowSwapChainNode::OUT_TEXTURE,
|
||||||
|
node::UI_PASS,
|
||||||
|
"color_attachment",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ensure ui pass runs after main pass
|
// ensure ui pass runs after main pass
|
||||||
self.add_node_edge(base::node::MAIN_PASS, node::UI_PASS)
|
self.add_node_edge(base::node::MAIN_PASS, node::UI_PASS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use bevy_math::Size;
|
|||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
draw::{Draw, DrawContext, Drawable},
|
draw::{Draw, DrawContext, Drawable},
|
||||||
renderer::{AssetRenderResourceBindings, RenderResourceBindings},
|
renderer::{AssetRenderResourceBindings, RenderResourceBindings},
|
||||||
texture::Texture,
|
texture::Texture, prelude::Msaa,
|
||||||
};
|
};
|
||||||
use bevy_sprite::TextureAtlas;
|
use bevy_sprite::TextureAtlas;
|
||||||
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
|
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
|
||||||
@ -51,6 +51,7 @@ pub fn text_system(
|
|||||||
pub fn draw_text_system(
|
pub fn draw_text_system(
|
||||||
mut draw_context: DrawContext,
|
mut draw_context: DrawContext,
|
||||||
fonts: Res<Assets<Font>>,
|
fonts: Res<Assets<Font>>,
|
||||||
|
msaa: Res<Msaa>,
|
||||||
font_atlas_sets: Res<Assets<FontAtlasSet>>,
|
font_atlas_sets: Res<Assets<FontAtlasSet>>,
|
||||||
texture_atlases: Res<Assets<TextureAtlas>>,
|
texture_atlases: Res<Assets<TextureAtlas>>,
|
||||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||||
@ -69,6 +70,7 @@ pub fn draw_text_system(
|
|||||||
render_resource_bindings: &mut render_resource_bindings,
|
render_resource_bindings: &mut render_resource_bindings,
|
||||||
asset_render_resource_bindings: &mut asset_render_resource_bindings,
|
asset_render_resource_bindings: &mut asset_render_resource_bindings,
|
||||||
position,
|
position,
|
||||||
|
msaa: &msaa,
|
||||||
style: &text.style,
|
style: &text.style,
|
||||||
text: &text.value,
|
text: &text.value,
|
||||||
container_size: node.size,
|
container_size: node.size,
|
||||||
|
|||||||
45
examples/3d/msaa.rs
Normal file
45
examples/3d/msaa.rs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
/// This example shows how to configure Multi-Sample Anti-Aliasing. Setting the sample count higher will result in smoother edges,
|
||||||
|
/// but it will also increase the cost to render those edges. The range should generally be somewhere between 1 (no multi sampling,
|
||||||
|
/// but cheap) to 8 (crisp but expensive)
|
||||||
|
fn main() {
|
||||||
|
App::build()
|
||||||
|
.add_resource(Msaa { samples: 4 })
|
||||||
|
.add_default_plugins()
|
||||||
|
.add_startup_system(setup.system())
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set up a simple 3D scene
|
||||||
|
fn setup(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
) {
|
||||||
|
// add entities to the world
|
||||||
|
commands
|
||||||
|
// cube
|
||||||
|
.spawn(PbrComponents {
|
||||||
|
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
|
||||||
|
material: materials.add(StandardMaterial {
|
||||||
|
albedo: Color::rgb(0.5, 0.4, 0.3),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// light
|
||||||
|
.spawn(LightComponents {
|
||||||
|
translation: Translation::new(4.0, 8.0, 4.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// camera
|
||||||
|
.spawn(Camera3dComponents {
|
||||||
|
transform: Transform::new_sync_disabled(Mat4::face_toward(
|
||||||
|
Vec3::new(-3.0, 3.0, 5.0),
|
||||||
|
Vec3::new(0.0, 0.0, 0.0),
|
||||||
|
Vec3::new(0.0, 1.0, 0.0),
|
||||||
|
)),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user