Remove Shader weak_handles from bevy_core_pipeline (except two). (#19395)

# Objective

- Related to #19024

## Solution

- Use the new `load_shader_library` macro for the shader libraries and
`embedded_asset`/`load_embedded_asset` for the "shader binaries" in
`bevy_core_pipeline`.

## Testing

- `bloom_3d` example still works.
- `motion_blur` example still works.
- `meshlet` example still works (it uses a shader from core).

P.S. I don't think this needs a migration guide. Technically users could
be using the `pub` weak handles, but there's no actual good use for
them, so omitting it seems fine. Alternatively, we could mix this in
with the migration guide notes for #19137.
This commit is contained in:
andriyDev 2025-05-27 15:32:27 -07:00 committed by GitHub
parent a8376e982e
commit 57588eb7eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 99 additions and 162 deletions

View File

@ -1,12 +1,12 @@
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, AssetApp, Assets, Handle}; use bevy_asset::{embedded_asset, AssetApp, Assets, Handle};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_render::{ use bevy_render::{
extract_component::ExtractComponentPlugin, extract_component::ExtractComponentPlugin,
render_asset::RenderAssetPlugin, render_asset::RenderAssetPlugin,
render_graph::RenderGraphApp, render_graph::RenderGraphApp,
render_resource::{ render_resource::{
Buffer, BufferDescriptor, BufferUsages, PipelineCache, Shader, SpecializedComputePipelines, Buffer, BufferDescriptor, BufferUsages, PipelineCache, SpecializedComputePipelines,
}, },
renderer::RenderDevice, renderer::RenderDevice,
ExtractSchedule, Render, RenderApp, RenderSystems, ExtractSchedule, Render, RenderApp, RenderSystems,
@ -21,9 +21,7 @@ mod settings;
use buffers::{extract_buffers, prepare_buffers, AutoExposureBuffers}; use buffers::{extract_buffers, prepare_buffers, AutoExposureBuffers};
pub use compensation_curve::{AutoExposureCompensationCurve, AutoExposureCompensationCurveError}; pub use compensation_curve::{AutoExposureCompensationCurve, AutoExposureCompensationCurveError};
use node::AutoExposureNode; use node::AutoExposureNode;
use pipeline::{ use pipeline::{AutoExposurePass, AutoExposurePipeline, ViewAutoExposurePipeline};
AutoExposurePass, AutoExposurePipeline, ViewAutoExposurePipeline, METERING_SHADER_HANDLE,
};
pub use settings::AutoExposure; pub use settings::AutoExposure;
use crate::{ use crate::{
@ -43,12 +41,7 @@ struct AutoExposureResources {
impl Plugin for AutoExposurePlugin { impl Plugin for AutoExposurePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!( embedded_asset!(app, "auto_exposure.wgsl");
app,
METERING_SHADER_HANDLE,
"auto_exposure.wgsl",
Shader::from_wgsl
);
app.add_plugins(RenderAssetPlugin::<GpuAutoExposureCompensationCurve>::default()) app.add_plugins(RenderAssetPlugin::<GpuAutoExposureCompensationCurve>::default())
.register_type::<AutoExposureCompensationCurve>() .register_type::<AutoExposureCompensationCurve>()

View File

@ -1,7 +1,7 @@
use super::compensation_curve::{ use super::compensation_curve::{
AutoExposureCompensationCurve, AutoExposureCompensationCurveUniform, AutoExposureCompensationCurve, AutoExposureCompensationCurveUniform,
}; };
use bevy_asset::{prelude::*, weak_handle}; use bevy_asset::{load_embedded_asset, prelude::*};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_image::Image; use bevy_image::Image;
use bevy_render::{ use bevy_render::{
@ -44,9 +44,6 @@ pub enum AutoExposurePass {
Average, Average,
} }
pub const METERING_SHADER_HANDLE: Handle<Shader> =
weak_handle!("05c84384-afa4-41d9-844e-e9cd5e7609af");
pub const HISTOGRAM_BIN_COUNT: u64 = 64; pub const HISTOGRAM_BIN_COUNT: u64 = 64;
impl FromWorld for AutoExposurePipeline { impl FromWorld for AutoExposurePipeline {
@ -71,7 +68,7 @@ impl FromWorld for AutoExposurePipeline {
), ),
), ),
), ),
histogram_shader: METERING_SHADER_HANDLE.clone(), histogram_shader: load_embedded_asset!(world, "auto_exposure.wgsl"),
} }
} }
} }

View File

@ -1,5 +1,5 @@
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, weak_handle, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, Handle};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_render::{ use bevy_render::{
render_resource::{ render_resource::{
@ -12,14 +12,12 @@ use bevy_render::{
use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state; use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
pub const BLIT_SHADER_HANDLE: Handle<Shader> = weak_handle!("59be3075-c34e-43e7-bf24-c8fe21a0192e");
/// Adds support for specialized "blit pipelines", which can be used to write one texture to another. /// Adds support for specialized "blit pipelines", which can be used to write one texture to another.
pub struct BlitPlugin; pub struct BlitPlugin;
impl Plugin for BlitPlugin { impl Plugin for BlitPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!(app, BLIT_SHADER_HANDLE, "blit.wgsl", Shader::from_wgsl); embedded_asset!(app, "blit.wgsl");
if let Some(render_app) = app.get_sub_app_mut(RenderApp) { if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app.allow_ambiguous_resource::<SpecializedRenderPipelines<BlitPipeline>>(); render_app.allow_ambiguous_resource::<SpecializedRenderPipelines<BlitPipeline>>();
@ -40,6 +38,7 @@ impl Plugin for BlitPlugin {
pub struct BlitPipeline { pub struct BlitPipeline {
pub texture_bind_group: BindGroupLayout, pub texture_bind_group: BindGroupLayout,
pub sampler: Sampler, pub sampler: Sampler,
pub shader: Handle<Shader>,
} }
impl FromWorld for BlitPipeline { impl FromWorld for BlitPipeline {
@ -62,6 +61,7 @@ impl FromWorld for BlitPipeline {
BlitPipeline { BlitPipeline {
texture_bind_group, texture_bind_group,
sampler, sampler,
shader: load_embedded_asset!(render_world, "blit.wgsl"),
} }
} }
} }
@ -82,7 +82,7 @@ impl SpecializedRenderPipeline for BlitPipeline {
layout: vec![self.texture_bind_group.clone()], layout: vec![self.texture_bind_group.clone()],
vertex: fullscreen_shader_vertex_state(), vertex: fullscreen_shader_vertex_state(),
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: BLIT_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs: vec![], shader_defs: vec![],
entry_point: "fs_main".into(), entry_point: "fs_main".into(),
targets: vec![Some(ColorTargetState { targets: vec![Some(ColorTargetState {

View File

@ -1,5 +1,6 @@
use super::{Bloom, BLOOM_SHADER_HANDLE, BLOOM_TEXTURE_FORMAT}; use super::{Bloom, BLOOM_TEXTURE_FORMAT};
use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state; use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
use bevy_asset::{load_embedded_asset, Handle};
use bevy_ecs::{ use bevy_ecs::{
prelude::{Component, Entity}, prelude::{Component, Entity},
resource::Resource, resource::Resource,
@ -26,6 +27,8 @@ pub struct BloomDownsamplingPipeline {
/// Layout with a texture, a sampler, and uniforms /// Layout with a texture, a sampler, and uniforms
pub bind_group_layout: BindGroupLayout, pub bind_group_layout: BindGroupLayout,
pub sampler: Sampler, pub sampler: Sampler,
/// The shader asset handle.
pub shader: Handle<Shader>,
} }
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
@ -78,6 +81,7 @@ impl FromWorld for BloomDownsamplingPipeline {
BloomDownsamplingPipeline { BloomDownsamplingPipeline {
bind_group_layout, bind_group_layout,
sampler, sampler,
shader: load_embedded_asset!(world, "bloom.wgsl"),
} }
} }
} }
@ -120,7 +124,7 @@ impl SpecializedRenderPipeline for BloomDownsamplingPipeline {
layout, layout,
vertex: fullscreen_shader_vertex_state(), vertex: fullscreen_shader_vertex_state(),
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: BLOOM_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs, shader_defs,
entry_point, entry_point,
targets: vec![Some(ColorTargetState { targets: vec![Some(ColorTargetState {

View File

@ -9,7 +9,7 @@ use crate::{
core_3d::graph::{Core3d, Node3d}, core_3d::graph::{Core3d, Node3d},
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, weak_handle, Handle}; use bevy_asset::embedded_asset;
use bevy_color::{Gray, LinearRgba}; use bevy_color::{Gray, LinearRgba};
use bevy_ecs::{prelude::*, query::QueryItem}; use bevy_ecs::{prelude::*, query::QueryItem};
use bevy_math::{ops, UVec2}; use bevy_math::{ops, UVec2};
@ -36,15 +36,13 @@ use upsampling_pipeline::{
prepare_upsampling_pipeline, BloomUpsamplingPipeline, UpsamplingPipelineIds, prepare_upsampling_pipeline, BloomUpsamplingPipeline, UpsamplingPipelineIds,
}; };
const BLOOM_SHADER_HANDLE: Handle<Shader> = weak_handle!("c9190ddc-573b-4472-8b21-573cab502b73");
const BLOOM_TEXTURE_FORMAT: TextureFormat = TextureFormat::Rg11b10Ufloat; const BLOOM_TEXTURE_FORMAT: TextureFormat = TextureFormat::Rg11b10Ufloat;
pub struct BloomPlugin; pub struct BloomPlugin;
impl Plugin for BloomPlugin { impl Plugin for BloomPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!(app, BLOOM_SHADER_HANDLE, "bloom.wgsl", Shader::from_wgsl); embedded_asset!(app, "bloom.wgsl");
app.register_type::<Bloom>(); app.register_type::<Bloom>();
app.register_type::<BloomPrefilter>(); app.register_type::<BloomPrefilter>();

View File

@ -1,8 +1,8 @@
use super::{ use super::{
downsampling_pipeline::BloomUniforms, Bloom, BloomCompositeMode, BLOOM_SHADER_HANDLE, downsampling_pipeline::BloomUniforms, Bloom, BloomCompositeMode, BLOOM_TEXTURE_FORMAT,
BLOOM_TEXTURE_FORMAT,
}; };
use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state; use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
use bevy_asset::{load_embedded_asset, Handle};
use bevy_ecs::{ use bevy_ecs::{
prelude::{Component, Entity}, prelude::{Component, Entity},
resource::Resource, resource::Resource,
@ -27,6 +27,8 @@ pub struct UpsamplingPipelineIds {
#[derive(Resource)] #[derive(Resource)]
pub struct BloomUpsamplingPipeline { pub struct BloomUpsamplingPipeline {
pub bind_group_layout: BindGroupLayout, pub bind_group_layout: BindGroupLayout,
/// The shader asset handle.
pub shader: Handle<Shader>,
} }
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
@ -54,7 +56,10 @@ impl FromWorld for BloomUpsamplingPipeline {
), ),
); );
BloomUpsamplingPipeline { bind_group_layout } BloomUpsamplingPipeline {
bind_group_layout,
shader: load_embedded_asset!(world, "bloom.wgsl"),
}
} }
} }
@ -105,7 +110,7 @@ impl SpecializedRenderPipeline for BloomUpsamplingPipeline {
layout: vec![self.bind_group_layout.clone()], layout: vec![self.bind_group_layout.clone()],
vertex: fullscreen_shader_vertex_state(), vertex: fullscreen_shader_vertex_state(),
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: BLOOM_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs: vec![], shader_defs: vec![],
entry_point: "upsample".into(), entry_point: "upsample".into(),
targets: vec![Some(ColorTargetState { targets: vec![Some(ColorTargetState {

View File

@ -3,7 +3,7 @@ use crate::{
prepass::{DeferredPrepass, ViewPrepassTextures}, prepass::{DeferredPrepass, ViewPrepassTextures},
}; };
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, weak_handle, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_math::UVec2; use bevy_math::UVec2;
use bevy_render::{ use bevy_render::{
@ -23,18 +23,11 @@ use bevy_render::{
use super::DEFERRED_LIGHTING_PASS_ID_DEPTH_FORMAT; use super::DEFERRED_LIGHTING_PASS_ID_DEPTH_FORMAT;
pub const COPY_DEFERRED_LIGHTING_ID_SHADER_HANDLE: Handle<Shader> =
weak_handle!("70d91342-1c43-4b20-973f-aa6ce93aa617");
pub struct CopyDeferredLightingIdPlugin; pub struct CopyDeferredLightingIdPlugin;
impl Plugin for CopyDeferredLightingIdPlugin { impl Plugin for CopyDeferredLightingIdPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!( embedded_asset!(app, "copy_deferred_lighting_id.wgsl");
app,
COPY_DEFERRED_LIGHTING_ID_SHADER_HANDLE,
"copy_deferred_lighting_id.wgsl",
Shader::from_wgsl
);
let Some(render_app) = app.get_sub_app_mut(RenderApp) else { let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return; return;
}; };
@ -137,6 +130,8 @@ impl FromWorld for CopyDeferredLightingIdPipeline {
), ),
); );
let shader = load_embedded_asset!(world, "copy_deferred_lighting_id.wgsl");
let pipeline_id = let pipeline_id =
world world
.resource_mut::<PipelineCache>() .resource_mut::<PipelineCache>()
@ -145,7 +140,7 @@ impl FromWorld for CopyDeferredLightingIdPipeline {
layout: vec![layout.clone()], layout: vec![layout.clone()],
vertex: fullscreen_shader_vertex_state(), vertex: fullscreen_shader_vertex_state(),
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: COPY_DEFERRED_LIGHTING_ID_SHADER_HANDLE, shader,
shader_defs: vec![], shader_defs: vec![],
entry_point: "fragment".into(), entry_point: "fragment".into(),
targets: vec![], targets: vec![],

View File

@ -15,7 +15,7 @@
//! [Depth of field]: https://en.wikipedia.org/wiki/Depth_of_field //! [Depth of field]: https://en.wikipedia.org/wiki/Depth_of_field
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, weak_handle, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer, Handle};
use bevy_derive::{Deref, DerefMut}; use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{ use bevy_ecs::{
component::Component, component::Component,
@ -69,8 +69,6 @@ use crate::{
fullscreen_vertex_shader::fullscreen_shader_vertex_state, fullscreen_vertex_shader::fullscreen_shader_vertex_state,
}; };
const DOF_SHADER_HANDLE: Handle<Shader> = weak_handle!("c3580ddc-2cbc-4535-a02b-9a2959066b52");
/// A plugin that adds support for the depth of field effect to Bevy. /// A plugin that adds support for the depth of field effect to Bevy.
pub struct DepthOfFieldPlugin; pub struct DepthOfFieldPlugin;
@ -206,7 +204,7 @@ enum DofPass {
impl Plugin for DepthOfFieldPlugin { impl Plugin for DepthOfFieldPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!(app, DOF_SHADER_HANDLE, "dof.wgsl", Shader::from_wgsl); embedded_asset!(app, "dof.wgsl");
app.register_type::<DepthOfField>(); app.register_type::<DepthOfField>();
app.register_type::<DepthOfFieldMode>(); app.register_type::<DepthOfFieldMode>();
@ -327,6 +325,8 @@ pub struct DepthOfFieldPipeline {
/// The bind group layout shared among all invocations of the depth of field /// The bind group layout shared among all invocations of the depth of field
/// shader. /// shader.
global_bind_group_layout: BindGroupLayout, global_bind_group_layout: BindGroupLayout,
/// The shader asset handle.
shader: Handle<Shader>,
} }
impl ViewNode for DepthOfFieldNode { impl ViewNode for DepthOfFieldNode {
@ -678,11 +678,13 @@ pub fn prepare_depth_of_field_pipelines(
&ViewDepthOfFieldBindGroupLayouts, &ViewDepthOfFieldBindGroupLayouts,
&Msaa, &Msaa,
)>, )>,
asset_server: Res<AssetServer>,
) { ) {
for (entity, view, depth_of_field, view_bind_group_layouts, msaa) in view_targets.iter() { for (entity, view, depth_of_field, view_bind_group_layouts, msaa) in view_targets.iter() {
let dof_pipeline = DepthOfFieldPipeline { let dof_pipeline = DepthOfFieldPipeline {
view_bind_group_layouts: view_bind_group_layouts.clone(), view_bind_group_layouts: view_bind_group_layouts.clone(),
global_bind_group_layout: global_bind_group_layout.layout.clone(), global_bind_group_layout: global_bind_group_layout.layout.clone(),
shader: load_embedded_asset!(asset_server.as_ref(), "dof.wgsl"),
}; };
// We'll need these two flags to create the `DepthOfFieldPipelineKey`s. // We'll need these two flags to create the `DepthOfFieldPipelineKey`s.
@ -800,7 +802,7 @@ impl SpecializedRenderPipeline for DepthOfFieldPipeline {
depth_stencil: None, depth_stencil: None,
multisample: default(), multisample: default(),
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: DOF_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs, shader_defs,
entry_point: match key.pass { entry_point: match key.pass {
DofPass::GaussianHorizontal => "gaussian_horizontal".into(), DofPass::GaussianHorizontal => "gaussian_horizontal".into(),

View File

@ -7,7 +7,7 @@ use crate::{
prepass::{DepthPrepass, MotionVectorPrepass}, prepass::{DepthPrepass, MotionVectorPrepass},
}; };
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, weak_handle, Handle}; use bevy_asset::embedded_asset;
use bevy_ecs::{ use bevy_ecs::{
component::Component, component::Component,
query::{QueryItem, With}, query::{QueryItem, With},
@ -19,7 +19,7 @@ use bevy_render::{
camera::Camera, camera::Camera,
extract_component::{ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin}, extract_component::{ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin},
render_graph::{RenderGraphApp, ViewNodeRunner}, render_graph::{RenderGraphApp, ViewNodeRunner},
render_resource::{Shader, ShaderType, SpecializedRenderPipelines}, render_resource::{ShaderType, SpecializedRenderPipelines},
Render, RenderApp, RenderSystems, Render, RenderApp, RenderSystems,
}; };
@ -126,19 +126,12 @@ pub struct MotionBlurUniform {
_webgl2_padding: bevy_math::Vec2, _webgl2_padding: bevy_math::Vec2,
} }
pub const MOTION_BLUR_SHADER_HANDLE: Handle<Shader> =
weak_handle!("d9ca74af-fa0a-4f11-b0f2-19613b618b93");
/// Adds support for per-object motion blur to the app. See [`MotionBlur`] for details. /// Adds support for per-object motion blur to the app. See [`MotionBlur`] for details.
pub struct MotionBlurPlugin; pub struct MotionBlurPlugin;
impl Plugin for MotionBlurPlugin { impl Plugin for MotionBlurPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!( embedded_asset!(app, "motion_blur.wgsl");
app,
MOTION_BLUR_SHADER_HANDLE,
"motion_blur.wgsl",
Shader::from_wgsl
);
app.add_plugins(( app.add_plugins((
ExtractComponentPlugin::<MotionBlur>::default(), ExtractComponentPlugin::<MotionBlur>::default(),
UniformComponentPlugin::<MotionBlurUniform>::default(), UniformComponentPlugin::<MotionBlurUniform>::default(),

View File

@ -1,3 +1,4 @@
use bevy_asset::{load_embedded_asset, Handle};
use bevy_ecs::{ use bevy_ecs::{
component::Component, component::Component,
entity::Entity, entity::Entity,
@ -16,9 +17,9 @@ use bevy_render::{
}, },
BindGroupLayout, BindGroupLayoutEntries, CachedRenderPipelineId, ColorTargetState, BindGroupLayout, BindGroupLayoutEntries, CachedRenderPipelineId, ColorTargetState,
ColorWrites, FragmentState, MultisampleState, PipelineCache, PrimitiveState, ColorWrites, FragmentState, MultisampleState, PipelineCache, PrimitiveState,
RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, ShaderDefVal, RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, Shader,
ShaderStages, ShaderType, SpecializedRenderPipeline, SpecializedRenderPipelines, ShaderDefVal, ShaderStages, ShaderType, SpecializedRenderPipeline,
TextureFormat, TextureSampleType, SpecializedRenderPipelines, TextureFormat, TextureSampleType,
}, },
renderer::RenderDevice, renderer::RenderDevice,
view::{ExtractedView, Msaa, ViewTarget}, view::{ExtractedView, Msaa, ViewTarget},
@ -26,17 +27,18 @@ use bevy_render::{
use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state; use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
use super::{MotionBlurUniform, MOTION_BLUR_SHADER_HANDLE}; use super::MotionBlurUniform;
#[derive(Resource)] #[derive(Resource)]
pub struct MotionBlurPipeline { pub struct MotionBlurPipeline {
pub(crate) sampler: Sampler, pub(crate) sampler: Sampler,
pub(crate) layout: BindGroupLayout, pub(crate) layout: BindGroupLayout,
pub(crate) layout_msaa: BindGroupLayout, pub(crate) layout_msaa: BindGroupLayout,
pub(crate) shader: Handle<Shader>,
} }
impl MotionBlurPipeline { impl MotionBlurPipeline {
pub(crate) fn new(render_device: &RenderDevice) -> Self { pub(crate) fn new(render_device: &RenderDevice, shader: Handle<Shader>) -> Self {
let mb_layout = &BindGroupLayoutEntries::sequential( let mb_layout = &BindGroupLayoutEntries::sequential(
ShaderStages::FRAGMENT, ShaderStages::FRAGMENT,
( (
@ -82,6 +84,7 @@ impl MotionBlurPipeline {
sampler, sampler,
layout, layout,
layout_msaa, layout_msaa,
shader,
} }
} }
} }
@ -89,7 +92,9 @@ impl MotionBlurPipeline {
impl FromWorld for MotionBlurPipeline { impl FromWorld for MotionBlurPipeline {
fn from_world(render_world: &mut bevy_ecs::world::World) -> Self { fn from_world(render_world: &mut bevy_ecs::world::World) -> Self {
let render_device = render_world.resource::<RenderDevice>().clone(); let render_device = render_world.resource::<RenderDevice>().clone();
MotionBlurPipeline::new(&render_device)
let shader = load_embedded_asset!(render_world, "motion_blur.wgsl");
MotionBlurPipeline::new(&render_device, shader)
} }
} }
@ -125,7 +130,7 @@ impl SpecializedRenderPipeline for MotionBlurPipeline {
layout, layout,
vertex: fullscreen_shader_vertex_state(), vertex: fullscreen_shader_vertex_state(),
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: MOTION_BLUR_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs, shader_defs,
entry_point: "fragment".into(), entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState { targets: vec![Some(ColorTargetState {

View File

@ -1,7 +1,6 @@
//! Order Independent Transparency (OIT) for 3d rendering. See [`OrderIndependentTransparencyPlugin`] for more details. //! Order Independent Transparency (OIT) for 3d rendering. See [`OrderIndependentTransparencyPlugin`] for more details.
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, weak_handle, Handle};
use bevy_ecs::{component::*, prelude::*}; use bevy_ecs::{component::*, prelude::*};
use bevy_math::UVec2; use bevy_math::UVec2;
use bevy_platform::collections::HashSet; use bevy_platform::collections::HashSet;
@ -10,10 +9,9 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{ use bevy_render::{
camera::{Camera, ExtractedCamera}, camera::{Camera, ExtractedCamera},
extract_component::{ExtractComponent, ExtractComponentPlugin}, extract_component::{ExtractComponent, ExtractComponentPlugin},
load_shader_library,
render_graph::{RenderGraphApp, ViewNodeRunner}, render_graph::{RenderGraphApp, ViewNodeRunner},
render_resource::{ render_resource::{BufferUsages, BufferVec, DynamicUniformBuffer, ShaderType, TextureUsages},
BufferUsages, BufferVec, DynamicUniformBuffer, Shader, ShaderType, TextureUsages,
},
renderer::{RenderDevice, RenderQueue}, renderer::{RenderDevice, RenderQueue},
view::Msaa, view::Msaa,
Render, RenderApp, RenderSystems, Render, RenderApp, RenderSystems,
@ -33,10 +31,6 @@ use crate::core_3d::{
/// Module that defines the necessary systems to resolve the OIT buffer and render it to the screen. /// Module that defines the necessary systems to resolve the OIT buffer and render it to the screen.
pub mod resolve; pub mod resolve;
/// Shader handle for the shader that draws the transparent meshes to the OIT layers buffer.
pub const OIT_DRAW_SHADER_HANDLE: Handle<Shader> =
weak_handle!("0cd3c764-39b8-437b-86b4-4e45635fc03d");
/// Used to identify which camera will use OIT to render transparent meshes /// Used to identify which camera will use OIT to render transparent meshes
/// and to configure OIT. /// and to configure OIT.
// TODO consider supporting multiple OIT techniques like WBOIT, Moment Based OIT, // TODO consider supporting multiple OIT techniques like WBOIT, Moment Based OIT,
@ -105,12 +99,7 @@ impl Component for OrderIndependentTransparencySettings {
pub struct OrderIndependentTransparencyPlugin; pub struct OrderIndependentTransparencyPlugin;
impl Plugin for OrderIndependentTransparencyPlugin { impl Plugin for OrderIndependentTransparencyPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!( load_shader_library!(app, "oit_draw.wgsl");
app,
OIT_DRAW_SHADER_HANDLE,
"oit_draw.wgsl",
Shader::from_wgsl
);
app.add_plugins(( app.add_plugins((
ExtractComponentPlugin::<OrderIndependentTransparencySettings>::default(), ExtractComponentPlugin::<OrderIndependentTransparencySettings>::default(),

View File

@ -3,7 +3,7 @@ use crate::{
oit::OrderIndependentTransparencySettings, oit::OrderIndependentTransparencySettings,
}; };
use bevy_app::Plugin; use bevy_app::Plugin;
use bevy_asset::{load_internal_asset, weak_handle, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, AssetServer};
use bevy_derive::Deref; use bevy_derive::Deref;
use bevy_ecs::{ use bevy_ecs::{
entity::{EntityHashMap, EntityHashSet}, entity::{EntityHashMap, EntityHashSet},
@ -16,7 +16,7 @@ use bevy_render::{
BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, BlendComponent, BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, BlendComponent,
BlendState, CachedRenderPipelineId, ColorTargetState, ColorWrites, DownlevelFlags, BlendState, CachedRenderPipelineId, ColorTargetState, ColorWrites, DownlevelFlags,
FragmentState, MultisampleState, PipelineCache, PrimitiveState, RenderPipelineDescriptor, FragmentState, MultisampleState, PipelineCache, PrimitiveState, RenderPipelineDescriptor,
Shader, ShaderDefVal, ShaderStages, TextureFormat, ShaderDefVal, ShaderStages, TextureFormat,
}, },
renderer::{RenderAdapter, RenderDevice}, renderer::{RenderAdapter, RenderDevice},
view::{ExtractedView, ViewTarget, ViewUniform, ViewUniforms}, view::{ExtractedView, ViewTarget, ViewUniform, ViewUniforms},
@ -26,10 +26,6 @@ use tracing::warn;
use super::OitBuffers; use super::OitBuffers;
/// Shader handle for the shader that sorts the OIT layers, blends the colors based on depth and renders them to the screen.
pub const OIT_RESOLVE_SHADER_HANDLE: Handle<Shader> =
weak_handle!("562d2917-eb06-444d-9ade-41de76b0f5ae");
/// Contains the render node used to run the resolve pass. /// Contains the render node used to run the resolve pass.
pub mod node; pub mod node;
@ -40,12 +36,7 @@ pub const OIT_REQUIRED_STORAGE_BUFFERS: u32 = 2;
pub struct OitResolvePlugin; pub struct OitResolvePlugin;
impl Plugin for OitResolvePlugin { impl Plugin for OitResolvePlugin {
fn build(&self, app: &mut bevy_app::App) { fn build(&self, app: &mut bevy_app::App) {
load_internal_asset!( embedded_asset!(app, "oit_resolve.wgsl");
app,
OIT_RESOLVE_SHADER_HANDLE,
"oit_resolve.wgsl",
Shader::from_wgsl
);
} }
fn finish(&self, app: &mut bevy_app::App) { fn finish(&self, app: &mut bevy_app::App) {
@ -165,6 +156,7 @@ pub fn queue_oit_resolve_pipeline(
), ),
With<OrderIndependentTransparencySettings>, With<OrderIndependentTransparencySettings>,
>, >,
asset_server: Res<AssetServer>,
// Store the key with the id to make the clean up logic easier. // Store the key with the id to make the clean up logic easier.
// This also means it will always replace the entry if the key changes so nothing to clean up. // This also means it will always replace the entry if the key changes so nothing to clean up.
mut cached_pipeline_id: Local<EntityHashMap<(OitResolvePipelineKey, CachedRenderPipelineId)>>, mut cached_pipeline_id: Local<EntityHashMap<(OitResolvePipelineKey, CachedRenderPipelineId)>>,
@ -184,7 +176,7 @@ pub fn queue_oit_resolve_pipeline(
} }
} }
let desc = specialize_oit_resolve_pipeline(key, &resolve_pipeline); let desc = specialize_oit_resolve_pipeline(key, &resolve_pipeline, &asset_server);
let pipeline_id = pipeline_cache.queue_render_pipeline(desc); let pipeline_id = pipeline_cache.queue_render_pipeline(desc);
commands.entity(e).insert(OitResolvePipelineId(pipeline_id)); commands.entity(e).insert(OitResolvePipelineId(pipeline_id));
@ -202,6 +194,7 @@ pub fn queue_oit_resolve_pipeline(
fn specialize_oit_resolve_pipeline( fn specialize_oit_resolve_pipeline(
key: OitResolvePipelineKey, key: OitResolvePipelineKey,
resolve_pipeline: &OitResolvePipeline, resolve_pipeline: &OitResolvePipeline,
asset_server: &AssetServer,
) -> RenderPipelineDescriptor { ) -> RenderPipelineDescriptor {
let format = if key.hdr { let format = if key.hdr {
ViewTarget::TEXTURE_FORMAT_HDR ViewTarget::TEXTURE_FORMAT_HDR
@ -217,7 +210,7 @@ fn specialize_oit_resolve_pipeline(
], ],
fragment: Some(FragmentState { fragment: Some(FragmentState {
entry_point: "fragment".into(), entry_point: "fragment".into(),
shader: OIT_RESOLVE_SHADER_HANDLE, shader: load_embedded_asset!(asset_server, "oit_resolve.wgsl"),
shader_defs: vec![ShaderDefVal::UInt( shader_defs: vec![ShaderDefVal::UInt(
"LAYER_COUNT".into(), "LAYER_COUNT".into(),
key.layer_count as u32, key.layer_count as u32,

View File

@ -3,7 +3,7 @@
//! Currently, this consists only of chromatic aberration. //! Currently, this consists only of chromatic aberration.
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, weak_handle, Assets, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, weak_handle, Assets, Handle};
use bevy_derive::{Deref, DerefMut}; use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{ use bevy_ecs::{
component::Component, component::Component,
@ -20,6 +20,7 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{ use bevy_render::{
camera::Camera, camera::Camera,
extract_component::{ExtractComponent, ExtractComponentPlugin}, extract_component::{ExtractComponent, ExtractComponentPlugin},
load_shader_library,
render_asset::{RenderAssetUsages, RenderAssets}, render_asset::{RenderAssetUsages, RenderAssets},
render_graph::{ render_graph::{
NodeRunError, RenderGraphApp as _, RenderGraphContext, ViewNode, ViewNodeRunner, NodeRunError, RenderGraphApp as _, RenderGraphContext, ViewNode, ViewNodeRunner,
@ -46,13 +47,6 @@ use crate::{
fullscreen_vertex_shader, fullscreen_vertex_shader,
}; };
/// The handle to the built-in postprocessing shader `post_process.wgsl`.
const POST_PROCESSING_SHADER_HANDLE: Handle<Shader> =
weak_handle!("5e8e627a-7531-484d-a988-9a38acb34e52");
/// The handle to the chromatic aberration shader `chromatic_aberration.wgsl`.
const CHROMATIC_ABERRATION_SHADER_HANDLE: Handle<Shader> =
weak_handle!("e598550e-71c3-4f5a-ba29-aebc3f88c7b5");
/// The handle to the default chromatic aberration lookup texture. /// The handle to the default chromatic aberration lookup texture.
/// ///
/// This is just a 3x1 image consisting of one red pixel, one green pixel, and /// This is just a 3x1 image consisting of one red pixel, one green pixel, and
@ -136,6 +130,8 @@ pub struct PostProcessingPipeline {
source_sampler: Sampler, source_sampler: Sampler,
/// Specifies how to sample the chromatic aberration gradient. /// Specifies how to sample the chromatic aberration gradient.
chromatic_aberration_lut_sampler: Sampler, chromatic_aberration_lut_sampler: Sampler,
/// The shader asset handle.
shader: Handle<Shader>,
} }
/// A key that uniquely identifies a built-in postprocessing pipeline. /// A key that uniquely identifies a built-in postprocessing pipeline.
@ -188,18 +184,9 @@ pub struct PostProcessingNode;
impl Plugin for PostProcessingPlugin { impl Plugin for PostProcessingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!( load_shader_library!(app, "chromatic_aberration.wgsl");
app,
POST_PROCESSING_SHADER_HANDLE, embedded_asset!(app, "post_process.wgsl");
"post_process.wgsl",
Shader::from_wgsl
);
load_internal_asset!(
app,
CHROMATIC_ABERRATION_SHADER_HANDLE,
"chromatic_aberration.wgsl",
Shader::from_wgsl
);
// Load the default chromatic aberration LUT. // Load the default chromatic aberration LUT.
let mut assets = app.world_mut().resource_mut::<Assets<_>>(); let mut assets = app.world_mut().resource_mut::<Assets<_>>();
@ -321,6 +308,7 @@ impl FromWorld for PostProcessingPipeline {
bind_group_layout, bind_group_layout,
source_sampler, source_sampler,
chromatic_aberration_lut_sampler, chromatic_aberration_lut_sampler,
shader: load_embedded_asset!(world, "post_process.wgsl"),
} }
} }
} }
@ -334,7 +322,7 @@ impl SpecializedRenderPipeline for PostProcessingPipeline {
layout: vec![self.bind_group_layout.clone()], layout: vec![self.bind_group_layout.clone()],
vertex: fullscreen_vertex_shader::fullscreen_shader_vertex_state(), vertex: fullscreen_vertex_shader::fullscreen_shader_vertex_state(),
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: POST_PROCESSING_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs: vec![], shader_defs: vec![],
entry_point: "fragment_main".into(), entry_point: "fragment_main".into(),
targets: vec![Some(ColorTargetState { targets: vec![Some(ColorTargetState {

View File

@ -1,5 +1,5 @@
use bevy_app::{App, Plugin}; use bevy_app::{App, Plugin};
use bevy_asset::{load_internal_asset, weak_handle, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, Handle};
use bevy_ecs::{ use bevy_ecs::{
prelude::{Component, Entity}, prelude::{Component, Entity},
query::{QueryItem, With}, query::{QueryItem, With},
@ -28,25 +28,18 @@ use bevy_render::{
Render, RenderApp, RenderSystems, Render, RenderApp, RenderSystems,
}; };
use bevy_transform::components::Transform; use bevy_transform::components::Transform;
use prepass::{SkyboxPrepassPipeline, SKYBOX_PREPASS_SHADER_HANDLE}; use prepass::SkyboxPrepassPipeline;
use crate::{core_3d::CORE_3D_DEPTH_FORMAT, prepass::PreviousViewUniforms}; use crate::{core_3d::CORE_3D_DEPTH_FORMAT, prepass::PreviousViewUniforms};
const SKYBOX_SHADER_HANDLE: Handle<Shader> = weak_handle!("a66cf9cc-cab8-47f8-ac32-db82fdc4f29b");
pub mod prepass; pub mod prepass;
pub struct SkyboxPlugin; pub struct SkyboxPlugin;
impl Plugin for SkyboxPlugin { impl Plugin for SkyboxPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!(app, SKYBOX_SHADER_HANDLE, "skybox.wgsl", Shader::from_wgsl); embedded_asset!(app, "skybox.wgsl");
load_internal_asset!( embedded_asset!(app, "skybox_prepass.wgsl");
app,
SKYBOX_PREPASS_SHADER_HANDLE,
"skybox_prepass.wgsl",
Shader::from_wgsl
);
app.register_type::<Skybox>().add_plugins(( app.register_type::<Skybox>().add_plugins((
ExtractComponentPlugin::<Skybox>::default(), ExtractComponentPlugin::<Skybox>::default(),
@ -76,9 +69,10 @@ impl Plugin for SkyboxPlugin {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else { let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return; return;
}; };
let shader = load_embedded_asset!(render_app.world(), "skybox.wgsl");
let render_device = render_app.world().resource::<RenderDevice>().clone(); let render_device = render_app.world().resource::<RenderDevice>().clone();
render_app render_app
.insert_resource(SkyboxPipeline::new(&render_device)) .insert_resource(SkyboxPipeline::new(&render_device, shader))
.init_resource::<SkyboxPrepassPipeline>(); .init_resource::<SkyboxPrepassPipeline>();
} }
} }
@ -158,10 +152,11 @@ pub struct SkyboxUniforms {
#[derive(Resource)] #[derive(Resource)]
struct SkyboxPipeline { struct SkyboxPipeline {
bind_group_layout: BindGroupLayout, bind_group_layout: BindGroupLayout,
shader: Handle<Shader>,
} }
impl SkyboxPipeline { impl SkyboxPipeline {
fn new(render_device: &RenderDevice) -> Self { fn new(render_device: &RenderDevice, shader: Handle<Shader>) -> Self {
Self { Self {
bind_group_layout: render_device.create_bind_group_layout( bind_group_layout: render_device.create_bind_group_layout(
"skybox_bind_group_layout", "skybox_bind_group_layout",
@ -176,6 +171,7 @@ impl SkyboxPipeline {
), ),
), ),
), ),
shader,
} }
} }
} }
@ -196,7 +192,7 @@ impl SpecializedRenderPipeline for SkyboxPipeline {
layout: vec![self.bind_group_layout.clone()], layout: vec![self.bind_group_layout.clone()],
push_constant_ranges: Vec::new(), push_constant_ranges: Vec::new(),
vertex: VertexState { vertex: VertexState {
shader: SKYBOX_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs: Vec::new(), shader_defs: Vec::new(),
entry_point: "skybox_vertex".into(), entry_point: "skybox_vertex".into(),
buffers: Vec::new(), buffers: Vec::new(),
@ -224,7 +220,7 @@ impl SpecializedRenderPipeline for SkyboxPipeline {
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: SKYBOX_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs: Vec::new(), shader_defs: Vec::new(),
entry_point: "skybox_fragment".into(), entry_point: "skybox_fragment".into(),
targets: vec![Some(ColorTargetState { targets: vec![Some(ColorTargetState {

View File

@ -1,6 +1,6 @@
//! Adds motion vector support to skyboxes. See [`SkyboxPrepassPipeline`] for details. //! Adds motion vector support to skyboxes. See [`SkyboxPrepassPipeline`] for details.
use bevy_asset::{weak_handle, Handle}; use bevy_asset::{load_embedded_asset, Handle};
use bevy_ecs::{ use bevy_ecs::{
component::Component, component::Component,
entity::Entity, entity::Entity,
@ -30,9 +30,6 @@ use crate::{
Skybox, Skybox,
}; };
pub const SKYBOX_PREPASS_SHADER_HANDLE: Handle<Shader> =
weak_handle!("7a292435-bfe6-4ed9-8d30-73bf7aa673b0");
/// This pipeline writes motion vectors to the prepass for all [`Skybox`]es. /// This pipeline writes motion vectors to the prepass for all [`Skybox`]es.
/// ///
/// This allows features like motion blur and TAA to work correctly on the skybox. Without this, for /// This allows features like motion blur and TAA to work correctly on the skybox. Without this, for
@ -41,6 +38,7 @@ pub const SKYBOX_PREPASS_SHADER_HANDLE: Handle<Shader> =
#[derive(Resource)] #[derive(Resource)]
pub struct SkyboxPrepassPipeline { pub struct SkyboxPrepassPipeline {
bind_group_layout: BindGroupLayout, bind_group_layout: BindGroupLayout,
shader: Handle<Shader>,
} }
/// Used to specialize the [`SkyboxPrepassPipeline`]. /// Used to specialize the [`SkyboxPrepassPipeline`].
@ -75,6 +73,7 @@ impl FromWorld for SkyboxPrepassPipeline {
), ),
), ),
), ),
shader: load_embedded_asset!(world, "skybox_prepass.wgsl"),
} }
} }
} }
@ -102,7 +101,7 @@ impl SpecializedRenderPipeline for SkyboxPrepassPipeline {
alpha_to_coverage_enabled: false, alpha_to_coverage_enabled: false,
}, },
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: SKYBOX_PREPASS_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs: vec![], shader_defs: vec![],
entry_point: "fragment".into(), entry_point: "fragment".into(),
targets: prepass_target_descriptors(key.normal_prepass, true, false), targets: prepass_target_descriptors(key.normal_prepass, true, false),

View File

@ -1,6 +1,6 @@
use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state; use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, weak_handle, Assets, Handle}; use bevy_asset::{embedded_asset, load_embedded_asset, Assets, Handle};
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_image::{CompressedImageFormats, Image, ImageSampler, ImageType}; use bevy_image::{CompressedImageFormats, Image, ImageSampler, ImageType};
use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_reflect::{std_traits::ReflectDefault, Reflect};
@ -8,6 +8,7 @@ use bevy_render::{
camera::Camera, camera::Camera,
extract_component::{ExtractComponent, ExtractComponentPlugin}, extract_component::{ExtractComponent, ExtractComponentPlugin},
extract_resource::{ExtractResource, ExtractResourcePlugin}, extract_resource::{ExtractResource, ExtractResourcePlugin},
load_shader_library,
render_asset::{RenderAssetUsages, RenderAssets}, render_asset::{RenderAssetUsages, RenderAssets},
render_resource::{ render_resource::{
binding_types::{sampler, texture_2d, texture_3d, uniform_buffer}, binding_types::{sampler, texture_2d, texture_3d, uniform_buffer},
@ -27,15 +28,6 @@ mod node;
use bevy_utils::default; use bevy_utils::default;
pub use node::TonemappingNode; pub use node::TonemappingNode;
const TONEMAPPING_SHADER_HANDLE: Handle<Shader> =
weak_handle!("e239c010-c25c-42a1-b4e8-08818764d667");
const TONEMAPPING_SHARED_SHADER_HANDLE: Handle<Shader> =
weak_handle!("61dbc544-4b30-4ca9-83bd-4751b5cfb1b1");
const TONEMAPPING_LUT_BINDINGS_SHADER_HANDLE: Handle<Shader> =
weak_handle!("d50e3a70-c85e-4725-a81e-72fc83281145");
/// 3D LUT (look up table) textures used for tonemapping /// 3D LUT (look up table) textures used for tonemapping
#[derive(Resource, Clone, ExtractResource)] #[derive(Resource, Clone, ExtractResource)]
pub struct TonemappingLuts { pub struct TonemappingLuts {
@ -48,24 +40,10 @@ pub struct TonemappingPlugin;
impl Plugin for TonemappingPlugin { impl Plugin for TonemappingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
load_internal_asset!( load_shader_library!(app, "tonemapping_shared.wgsl");
app, load_shader_library!(app, "lut_bindings.wgsl");
TONEMAPPING_SHADER_HANDLE,
"tonemapping.wgsl", embedded_asset!(app, "tonemapping.wgsl");
Shader::from_wgsl
);
load_internal_asset!(
app,
TONEMAPPING_SHARED_SHADER_HANDLE,
"tonemapping_shared.wgsl",
Shader::from_wgsl
);
load_internal_asset!(
app,
TONEMAPPING_LUT_BINDINGS_SHADER_HANDLE,
"lut_bindings.wgsl",
Shader::from_wgsl
);
if !app.world().is_resource_added::<TonemappingLuts>() { if !app.world().is_resource_added::<TonemappingLuts>() {
let mut images = app.world_mut().resource_mut::<Assets<Image>>(); let mut images = app.world_mut().resource_mut::<Assets<Image>>();
@ -134,6 +112,7 @@ impl Plugin for TonemappingPlugin {
pub struct TonemappingPipeline { pub struct TonemappingPipeline {
texture_bind_group: BindGroupLayout, texture_bind_group: BindGroupLayout,
sampler: Sampler, sampler: Sampler,
shader: Handle<Shader>,
} }
/// Optionally enables a tonemapping shader that attempts to map linear input stimulus into a perceptually uniform image for a given [`Camera`] entity. /// Optionally enables a tonemapping shader that attempts to map linear input stimulus into a perceptually uniform image for a given [`Camera`] entity.
@ -296,7 +275,7 @@ impl SpecializedRenderPipeline for TonemappingPipeline {
layout: vec![self.texture_bind_group.clone()], layout: vec![self.texture_bind_group.clone()],
vertex: fullscreen_shader_vertex_state(), vertex: fullscreen_shader_vertex_state(),
fragment: Some(FragmentState { fragment: Some(FragmentState {
shader: TONEMAPPING_SHADER_HANDLE, shader: self.shader.clone(),
shader_defs, shader_defs,
entry_point: "fragment".into(), entry_point: "fragment".into(),
targets: vec![Some(ColorTargetState { targets: vec![Some(ColorTargetState {
@ -340,6 +319,7 @@ impl FromWorld for TonemappingPipeline {
TonemappingPipeline { TonemappingPipeline {
texture_bind_group: tonemap_texture_bind_group, texture_bind_group: tonemap_texture_bind_group,
sampler, sampler,
shader: load_embedded_asset!(render_world, "tonemapping.wgsl"),
} }
} }
} }