22
33use bevy_app:: prelude:: * ;
44use bevy_asset:: { load_internal_asset, Handle } ;
5- use bevy_ecs:: prelude:: * ;
5+ use bevy_ecs:: { component :: * , prelude:: * } ;
66use bevy_math:: UVec2 ;
7+ use bevy_reflect:: Reflect ;
78use bevy_render:: {
89 camera:: { Camera , ExtractedCamera } ,
910 extract_component:: { ExtractComponent , ExtractComponentPlugin } ,
1011 render_graph:: { RenderGraphApp , ViewNodeRunner } ,
11- render_resource:: { BufferUsages , BufferVec , DynamicUniformBuffer , Shader , TextureUsages } ,
12+ render_resource:: {
13+ BufferUsages , BufferVec , DynamicUniformBuffer , Shader , ShaderType , TextureUsages ,
14+ } ,
1215 renderer:: { RenderDevice , RenderQueue } ,
1316 view:: Msaa ,
1417 Render , RenderApp , RenderSet ,
1518} ;
16- use bevy_utils:: { tracing:: trace, HashSet , Instant } ;
19+ use bevy_utils:: {
20+ tracing:: { trace, warn} ,
21+ HashSet , Instant ,
22+ } ;
1723use bevy_window:: PrimaryWindow ;
1824use resolve:: {
1925 node:: { OitResolveNode , OitResolvePass } ,
@@ -36,17 +42,41 @@ pub const OIT_DRAW_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(404252
3642// TODO consider supporting multiple OIT techniques like WBOIT, Moment Based OIT,
3743// depth peeling, stochastic transparency, ray tracing etc.
3844// This should probably be done by adding an enum to this component.
39- #[ derive( Component , Clone , Copy , ExtractComponent ) ]
45+ // We use the same struct to pass on the settings to the drawing shader.
46+ #[ derive( Clone , Copy , ExtractComponent , Reflect , ShaderType ) ]
4047pub struct OrderIndependentTransparencySettings {
4148 /// Controls how many layers will be used to compute the blending.
4249 /// The more layers you use the more memory it will use but it will also give better results.
4350 /// 8 is generally recommended, going above 16 is probably not worth it in the vast majority of cases
44- pub layer_count : u8 ,
51+ pub layer_count : i32 ,
52+ /// Controls the threshold from which fragments will be added to the blending layers.
53+ /// This can be tweaked to optimize quality / layers count. Higher values will
54+ /// allow lower number of layers and a better performance, compromising quality.
55+ pub alpha_threshold : f32 ,
4556}
4657
4758impl Default for OrderIndependentTransparencySettings {
4859 fn default ( ) -> Self {
49- Self { layer_count : 8 }
60+ Self {
61+ layer_count : 8 ,
62+ alpha_threshold : 0.0 ,
63+ }
64+ }
65+ }
66+
67+ // OrderIndependentTransparencySettings is also a Component. We explicitly implement the trait so
68+ // we can hook on_add to issue a warning in case `layer_count` is seemingly too high.
69+ impl Component for OrderIndependentTransparencySettings {
70+ const STORAGE_TYPE : StorageType = StorageType :: SparseSet ;
71+
72+ fn register_component_hooks ( hooks : & mut ComponentHooks ) {
73+ hooks. on_add ( |world, entity, _| {
74+ if let Some ( value) = world. get :: < OrderIndependentTransparencySettings > ( entity) {
75+ if value. layer_count > 32 {
76+ warn ! ( "OrderIndependentTransparencySettings layer_count set to {} might be too high." , value. layer_count) ;
77+ }
78+ }
79+ } ) ;
5080 }
5181}
5282
@@ -82,7 +112,8 @@ impl Plugin for OrderIndependentTransparencyPlugin {
82112 OitResolvePlugin ,
83113 ) )
84114 . add_systems ( Update , check_msaa)
85- . add_systems ( Last , configure_depth_texture_usages) ;
115+ . add_systems ( Last , configure_depth_texture_usages)
116+ . register_type :: < OrderIndependentTransparencySettings > ( ) ;
86117
87118 let Some ( render_app) = app. get_sub_app_mut ( RenderApp ) else {
88119 return ;
@@ -164,7 +195,7 @@ pub struct OitBuffers {
164195 pub layers : BufferVec < UVec2 > ,
165196 /// Buffer containing the index of the last layer that was written for each fragment.
166197 pub layer_ids : BufferVec < i32 > ,
167- pub layers_count_uniforms : DynamicUniformBuffer < i32 > ,
198+ pub settings : DynamicUniformBuffer < OrderIndependentTransparencySettings > ,
168199}
169200
170201impl FromWorld for OitBuffers {
@@ -184,19 +215,19 @@ impl FromWorld for OitBuffers {
184215 layer_ids. reserve ( 1 , render_device) ;
185216 layer_ids. write_buffer ( render_device, render_queue) ;
186217
187- let mut layers_count_uniforms = DynamicUniformBuffer :: default ( ) ;
188- layers_count_uniforms . set_label ( Some ( "oit_layers_count " ) ) ;
218+ let mut settings = DynamicUniformBuffer :: default ( ) ;
219+ settings . set_label ( Some ( "oit_settings " ) ) ;
189220
190221 Self {
191222 layers,
192223 layer_ids,
193- layers_count_uniforms ,
224+ settings ,
194225 }
195226 }
196227}
197228
198229#[ derive( Component ) ]
199- pub struct OitLayersCountOffset {
230+ pub struct OrderIndependentTransparencySettingsOffset {
200231 pub offset : u32 ,
201232}
202233
@@ -268,16 +299,16 @@ pub fn prepare_oit_buffers(
268299 ) ;
269300 }
270301
271- if let Some ( mut writer) = buffers. layers_count_uniforms . get_writer (
302+ if let Some ( mut writer) = buffers. settings . get_writer (
272303 camera_oit_uniforms. iter ( ) . len ( ) ,
273304 & render_device,
274305 & render_queue,
275306 ) {
276307 for ( entity, settings) in & camera_oit_uniforms {
277- let offset = writer. write ( & ( settings. layer_count as i32 ) ) ;
308+ let offset = writer. write ( settings) ;
278309 commands
279310 . entity ( entity)
280- . insert ( OitLayersCountOffset { offset } ) ;
311+ . insert ( OrderIndependentTransparencySettingsOffset { offset } ) ;
281312 }
282313 }
283314}
0 commit comments