Remove WebGL padding from MotionBlur
(#18727)
## Objective The `MotionBlur` component exposes renderer internals. Users shouldn't have to deal with this. ```rust MotionBlur { shutter_angle: 1.0, samples: 2, #[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))] _webgl2_padding: Default::default(), }, ``` ## Solution The renderer now uses a separate `MotionBlurUniform` struct for its internals. `MotionBlur` no longer needs padding. I was a bit unsure about the name `MotionBlurUniform`. Other modules use a mix of `Uniform` and `Uniforms`. ## Testing ``` cargo run --example motion_blur ``` Tested on Win10/Nvidia across Vulkan, WebGL/Chrome, WebGPU/Chrome.
This commit is contained in:
parent
f3f4e80d87
commit
8f083307c3
@ -9,7 +9,10 @@ use crate::{
|
|||||||
use bevy_app::{App, Plugin};
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_asset::{load_internal_asset, weak_handle, Handle};
|
use bevy_asset::{load_internal_asset, weak_handle, Handle};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
component::Component, query::With, reflect::ReflectComponent, schedule::IntoScheduleConfigs,
|
component::Component,
|
||||||
|
query::{QueryItem, With},
|
||||||
|
reflect::ReflectComponent,
|
||||||
|
schedule::IntoScheduleConfigs,
|
||||||
};
|
};
|
||||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
@ -53,9 +56,8 @@ pub mod pipeline;
|
|||||||
/// ));
|
/// ));
|
||||||
/// # }
|
/// # }
|
||||||
/// ````
|
/// ````
|
||||||
#[derive(Reflect, Component, Clone, ExtractComponent, ShaderType)]
|
#[derive(Reflect, Component, Clone)]
|
||||||
#[reflect(Component, Default, Clone)]
|
#[reflect(Component, Default, Clone)]
|
||||||
#[extract_component_filter(With<Camera>)]
|
|
||||||
#[require(DepthPrepass, MotionVectorPrepass)]
|
#[require(DepthPrepass, MotionVectorPrepass)]
|
||||||
pub struct MotionBlur {
|
pub struct MotionBlur {
|
||||||
/// The strength of motion blur from `0.0` to `1.0`.
|
/// The strength of motion blur from `0.0` to `1.0`.
|
||||||
@ -88,9 +90,6 @@ pub struct MotionBlur {
|
|||||||
/// Setting this to `3` will result in `3 * 2 + 1 = 7` samples. Setting this to `0` is
|
/// Setting this to `3` will result in `3 * 2 + 1 = 7` samples. Setting this to `0` is
|
||||||
/// equivalent to disabling motion blur.
|
/// equivalent to disabling motion blur.
|
||||||
pub samples: u32,
|
pub samples: u32,
|
||||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
|
||||||
// WebGL2 structs must be 16 byte aligned.
|
|
||||||
pub _webgl2_padding: bevy_math::Vec2,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MotionBlur {
|
impl Default for MotionBlur {
|
||||||
@ -98,12 +97,35 @@ impl Default for MotionBlur {
|
|||||||
Self {
|
Self {
|
||||||
shutter_angle: 0.5,
|
shutter_angle: 0.5,
|
||||||
samples: 1,
|
samples: 1,
|
||||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
|
||||||
_webgl2_padding: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExtractComponent for MotionBlur {
|
||||||
|
type QueryData = &'static Self;
|
||||||
|
type QueryFilter = With<Camera>;
|
||||||
|
type Out = MotionBlurUniform;
|
||||||
|
|
||||||
|
fn extract_component(item: QueryItem<Self::QueryData>) -> Option<Self::Out> {
|
||||||
|
Some(MotionBlurUniform {
|
||||||
|
shutter_angle: item.shutter_angle,
|
||||||
|
samples: item.samples,
|
||||||
|
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||||
|
_webgl2_padding: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Component, ShaderType, Clone)]
|
||||||
|
pub struct MotionBlurUniform {
|
||||||
|
shutter_angle: f32,
|
||||||
|
samples: u32,
|
||||||
|
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||||
|
// WebGL2 structs must be 16 byte aligned.
|
||||||
|
_webgl2_padding: bevy_math::Vec2,
|
||||||
|
}
|
||||||
|
|
||||||
pub const MOTION_BLUR_SHADER_HANDLE: Handle<Shader> =
|
pub const MOTION_BLUR_SHADER_HANDLE: Handle<Shader> =
|
||||||
weak_handle!("d9ca74af-fa0a-4f11-b0f2-19613b618b93");
|
weak_handle!("d9ca74af-fa0a-4f11-b0f2-19613b618b93");
|
||||||
|
|
||||||
@ -119,7 +141,7 @@ impl Plugin for MotionBlurPlugin {
|
|||||||
);
|
);
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
ExtractComponentPlugin::<MotionBlur>::default(),
|
ExtractComponentPlugin::<MotionBlur>::default(),
|
||||||
UniformComponentPlugin::<MotionBlur>::default(),
|
UniformComponentPlugin::<MotionBlurUniform>::default(),
|
||||||
));
|
));
|
||||||
|
|
||||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||||
|
@ -15,7 +15,7 @@ use crate::prepass::ViewPrepassTextures;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
pipeline::{MotionBlurPipeline, MotionBlurPipelineId},
|
pipeline::{MotionBlurPipeline, MotionBlurPipelineId},
|
||||||
MotionBlur,
|
MotionBlurUniform,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -26,7 +26,7 @@ impl ViewNode for MotionBlurNode {
|
|||||||
&'static ViewTarget,
|
&'static ViewTarget,
|
||||||
&'static MotionBlurPipelineId,
|
&'static MotionBlurPipelineId,
|
||||||
&'static ViewPrepassTextures,
|
&'static ViewPrepassTextures,
|
||||||
&'static MotionBlur,
|
&'static MotionBlurUniform,
|
||||||
&'static Msaa,
|
&'static Msaa,
|
||||||
);
|
);
|
||||||
fn run(
|
fn run(
|
||||||
@ -42,7 +42,7 @@ impl ViewNode for MotionBlurNode {
|
|||||||
|
|
||||||
let motion_blur_pipeline = world.resource::<MotionBlurPipeline>();
|
let motion_blur_pipeline = world.resource::<MotionBlurPipeline>();
|
||||||
let pipeline_cache = world.resource::<PipelineCache>();
|
let pipeline_cache = world.resource::<PipelineCache>();
|
||||||
let settings_uniforms = world.resource::<ComponentUniforms<MotionBlur>>();
|
let settings_uniforms = world.resource::<ComponentUniforms<MotionBlurUniform>>();
|
||||||
let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline_id.0) else {
|
let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline_id.0) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,7 @@ use bevy_render::{
|
|||||||
|
|
||||||
use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
|
use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
|
||||||
|
|
||||||
use super::{MotionBlur, MOTION_BLUR_SHADER_HANDLE};
|
use super::{MotionBlurUniform, MOTION_BLUR_SHADER_HANDLE};
|
||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct MotionBlurPipeline {
|
pub struct MotionBlurPipeline {
|
||||||
@ -49,7 +49,7 @@ impl MotionBlurPipeline {
|
|||||||
// Linear Sampler
|
// Linear Sampler
|
||||||
sampler(SamplerBindingType::Filtering),
|
sampler(SamplerBindingType::Filtering),
|
||||||
// Motion blur settings uniform input
|
// Motion blur settings uniform input
|
||||||
uniform_buffer_sized(false, Some(MotionBlur::min_size())),
|
uniform_buffer_sized(false, Some(MotionBlurUniform::min_size())),
|
||||||
// Globals uniform input
|
// Globals uniform input
|
||||||
uniform_buffer_sized(false, Some(GlobalsUniform::min_size())),
|
uniform_buffer_sized(false, Some(GlobalsUniform::min_size())),
|
||||||
),
|
),
|
||||||
@ -67,7 +67,7 @@ impl MotionBlurPipeline {
|
|||||||
// Linear Sampler
|
// Linear Sampler
|
||||||
sampler(SamplerBindingType::Filtering),
|
sampler(SamplerBindingType::Filtering),
|
||||||
// Motion blur settings uniform input
|
// Motion blur settings uniform input
|
||||||
uniform_buffer_sized(false, Some(MotionBlur::min_size())),
|
uniform_buffer_sized(false, Some(MotionBlurUniform::min_size())),
|
||||||
// Globals uniform input
|
// Globals uniform input
|
||||||
uniform_buffer_sized(false, Some(GlobalsUniform::min_size())),
|
uniform_buffer_sized(false, Some(GlobalsUniform::min_size())),
|
||||||
),
|
),
|
||||||
@ -155,7 +155,7 @@ pub(crate) fn prepare_motion_blur_pipelines(
|
|||||||
pipeline_cache: Res<PipelineCache>,
|
pipeline_cache: Res<PipelineCache>,
|
||||||
mut pipelines: ResMut<SpecializedRenderPipelines<MotionBlurPipeline>>,
|
mut pipelines: ResMut<SpecializedRenderPipelines<MotionBlurPipeline>>,
|
||||||
pipeline: Res<MotionBlurPipeline>,
|
pipeline: Res<MotionBlurPipeline>,
|
||||||
views: Query<(Entity, &ExtractedView, &Msaa), With<MotionBlur>>,
|
views: Query<(Entity, &ExtractedView, &Msaa), With<MotionBlurUniform>>,
|
||||||
) {
|
) {
|
||||||
for (entity, view, msaa) in &views {
|
for (entity, view, msaa) in &views {
|
||||||
let pipeline_id = pipelines.specialize(
|
let pipeline_id = pipelines.specialize(
|
||||||
|
@ -26,8 +26,6 @@ fn setup_camera(mut commands: Commands) {
|
|||||||
MotionBlur {
|
MotionBlur {
|
||||||
shutter_angle: 1.0,
|
shutter_angle: 1.0,
|
||||||
samples: 2,
|
samples: 2,
|
||||||
#[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))]
|
|
||||||
_webgl2_padding: Default::default(),
|
|
||||||
},
|
},
|
||||||
// MSAA and Motion Blur together are not compatible on WebGL
|
// MSAA and Motion Blur together are not compatible on WebGL
|
||||||
#[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))]
|
#[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||||
|
Loading…
Reference in New Issue
Block a user