• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

djeedai / bevy_hanabi / 10416573129

16 Aug 2024 07:49AM UTC coverage: 59.11% (-0.8%) from 59.863%
10416573129

push

github

web-flow
Add support for texture sampling as expression (#367)

Add a new `TextureSampleExpr` to allow sampling a texture from an
expression. Make the `ParticleTextureModifier` use this. Change the
texture image to be hosted on a new `EffectMaterial` component, and add
`Module::add_texture()` to define a new texture slot (binding).

This is a primitive first version with several restrictions:
- Only color textures (those returning `vec4<f32>`), no depth.
- Only sampling via `textureSample()` in WGSL, no LOD or bias, no
  unsampled gather, _etc._
- No validation whatsoever about the coherence of the slots, the images
  on the material, and the expressions. If anything is inconsistent,
  this might produce runtime errors (fail to create shader) or simply
  render the wrong thing (no texture).

Fixes #355

52 of 204 new or added lines in 8 files covered. (25.49%)

3 existing lines in 2 files now uncovered.

3494 of 5911 relevant lines covered (59.11%)

23.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/render/batch.rs
1
use std::ops::{Index, Range};
2

3
#[cfg(feature = "2d")]
4
use bevy::math::FloatOrd;
5
use bevy::{
6
    prelude::*,
7
    render::render_resource::{Buffer, CachedComputePipelineId},
8
};
9

10
use super::{
11
    effect_cache::{DispatchBufferIndices, EffectSlices},
12
    EffectCacheId, GpuCompressedTransform, LayoutFlags,
13
};
14
use crate::{AlphaMode, EffectAsset, EffectShader, ParticleLayout, PropertyLayout, TextureLayout};
15

16
/// Data needed to render all batches pertaining to a specific effect.
17
#[derive(Debug, Component)]
18
pub(crate) struct EffectBatches {
19
    /// Handle of the underlying effect asset describing the effect.
20
    pub handle: Handle<EffectAsset>,
21
    /// One batch per particle group.
22
    pub group_batches: Vec<EffectBatch>,
23
    /// Index of the buffer.
24
    pub buffer_index: u32,
25
    /// Index of the first Spawner of the effects in the batch.
26
    pub spawner_base: u32,
27
    /// Number of particles to spawn/init this frame.
28
    pub spawn_count: u32,
29
    /// The effect cache ID.
30
    pub effect_cache_id: EffectCacheId,
31
    /// The indices within the various indirect dispatch buffers.
32
    pub dispatch_buffer_indices: DispatchBufferIndices,
33
    /// The index of the first [`GpuParticleGroup`] structure in the global
34
    /// [`EffectsMeta::particle_group_buffer`] buffer. The buffer is currently
35
    /// re-created each frame, so the rows for multiple groups of an effect are
36
    /// guaranteed to be contiguous.
37
    pub first_particle_group_buffer_index: u32,
38
    /// Particle layout.
39
    pub particle_layout: ParticleLayout,
40
    /// Flags describing the render layout.
41
    pub layout_flags: LayoutFlags,
42
    /// Texture layout.
43
    pub texture_layout: TextureLayout,
44
    /// Textures.
45
    pub textures: Vec<Handle<Image>>,
46
    /// Alpha mode.
47
    pub alpha_mode: AlphaMode,
48
    /// Entities holding the source [`ParticleEffect`] instances which were
49
    /// batched into this single batch. Used to determine visibility per view.
50
    ///
51
    /// [`ParticleEffect`]: crate::ParticleEffect
52
    pub entities: Vec<u32>,
53
    /// Configured shaders used for the particle rendering of this batch.
54
    /// Note that we don't need to keep the init/update shaders alive because
55
    /// their pipeline specialization is doing it via the specialization key.
56
    pub render_shaders: Vec<Handle<Shader>>,
57
    /// Init compute pipeline specialized for this batch.
58
    pub init_pipeline_id: CachedComputePipelineId,
59
    /// Update compute pipeline specialized for this batch.
60
    pub update_pipeline_ids: Vec<CachedComputePipelineId>,
61
}
62

63
impl Index<u32> for EffectBatches {
64
    type Output = EffectBatch;
65

66
    fn index(&self, index: u32) -> &Self::Output {
×
67
        &self.group_batches[index as usize]
×
68
    }
69
}
70

71
/// Single effect batch to drive rendering.
72
///
73
/// This component is spawned into the render world during the prepare phase
74
/// ([`prepare_effects()`]), once per effect batch per group. In turns it
75
/// references an [`EffectBatches`] component containing all the shared data for
76
/// all the groups of the effect.
77
#[derive(Debug, Component)]
78
pub(crate) struct EffectDrawBatch {
79
    /// Group index of the batch.
80
    pub group_index: u32,
81
    /// Entity holding the [`EffectBatches`] this batch is part of.
82
    pub batches_entity: Entity,
83
    /// For 2D rendering, the Z coordinate used as the sort key. Ignored for 3D
84
    /// rendering.
85
    #[cfg(feature = "2d")]
86
    pub z_sort_key_2d: FloatOrd,
87
    /// For 3d rendering, the position of the emitter so we can compute distance
88
    /// to camera. Ignored for 2D rendering.
89
    #[cfg(feature = "3d")]
90
    pub translation_3d: Vec3,
91
}
92

93
/// Batch data specific to a single particle group.
94
#[derive(Debug)]
95
pub(crate) struct EffectBatch {
96
    /// Slice of particles in the GPU effect buffer for the entire batch.
97
    pub slice: Range<u32>,
98
}
99

100
impl EffectBatches {
101
    /// Create a new batch from a single input.
102
    pub fn from_input(
×
103
        input: BatchesInput,
104
        spawner_base: u32,
105
        effect_cache_id: EffectCacheId,
106
        init_pipeline_id: CachedComputePipelineId,
107
        update_pipeline_ids: Vec<CachedComputePipelineId>,
108
        dispatch_buffer_indices: DispatchBufferIndices,
109
        first_particle_group_buffer_index: u32,
110
    ) -> EffectBatches {
111
        EffectBatches {
112
            buffer_index: input.effect_slices.buffer_index,
×
113
            spawner_base,
114
            spawn_count: input.spawn_count,
×
115
            particle_layout: input.effect_slices.particle_layout,
×
116
            effect_cache_id,
117
            dispatch_buffer_indices,
118
            first_particle_group_buffer_index,
119
            group_batches: input
×
120
                .effect_slices
121
                .slices
122
                .windows(2)
123
                .map(|range| EffectBatch {
124
                    slice: range[0]..range[1],
125
                })
126
                .collect(),
127
            handle: input.handle,
×
128
            layout_flags: input.layout_flags,
×
NEW
129
            texture_layout: input.texture_layout,
×
NEW
130
            textures: input.textures,
×
131
            alpha_mode: input.alpha_mode,
×
132
            render_shaders: input.effect_shader.render,
×
133
            init_pipeline_id,
134
            update_pipeline_ids,
135
            entities: vec![input.entity.index()],
×
136
        }
137
    }
138
}
139

140
/// Effect batching input, obtained from extracted effects.
141
#[derive(Debug, Clone)]
142
pub(crate) struct BatchesInput {
143
    /// Handle of the underlying effect asset describing the effect.
144
    pub handle: Handle<EffectAsset>,
145
    /// Entity index excluding generation ([`Entity::index()`]). This is
146
    /// transient for a single frame, so the generation is useless.
147
    pub entity: Entity,
148
    /// Effect slices.
149
    pub effect_slices: EffectSlices,
150
    /// Layout of the effect properties.
151
    pub property_layout: PropertyLayout,
152
    /// Effect shader.
153
    pub effect_shader: EffectShader,
154
    /// Various flags related to the effect.
155
    pub layout_flags: LayoutFlags,
156
    /// Texture layout.
157
    pub texture_layout: TextureLayout,
158
    /// Textures.
159
    pub textures: Vec<Handle<Image>>,
160
    /// Alpha mode.
161
    pub alpha_mode: AlphaMode,
162
    /// Number of particles to spawn for this effect.
163
    pub spawn_count: u32,
164
    /// Emitter transform.
165
    pub transform: GpuCompressedTransform,
166
    /// Emitter inverse transform.
167
    pub inverse_transform: GpuCompressedTransform,
168
    /// GPU buffer where properties for this batch need to be written.
169
    pub property_buffer: Option<Buffer>,
170
    /// Serialized property data.
171
    // FIXME - Contains a single effect's data; should handle multiple ones.
172
    pub property_data: Option<Vec<u8>>,
173
    /// Sort key, for 2D only.
174
    #[cfg(feature = "2d")]
175
    pub z_sort_key_2d: FloatOrd,
176
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc