2022-10-26 20:13:59 +00:00
|
|
|
#ifdef TONEMAP_IN_SHADER
|
|
|
|
#import bevy_core_pipeline::tonemapping
|
|
|
|
#endif
|
|
|
|
|
2023-10-21 11:51:58 +00:00
|
|
|
#import bevy_render::{
|
2024-02-21 01:11:28 +00:00
|
|
|
maths::affine3_to_square,
|
2023-10-21 11:51:58 +00:00
|
|
|
view::View,
|
|
|
|
}
|
2023-02-11 17:55:18 +00:00
|
|
|
|
2023-09-19 22:17:44 +00:00
|
|
|
@group(0) @binding(0) var<uniform> view: View;
|
2021-06-28 22:36:50 +00:00
|
|
|
|
2023-09-02 18:03:19 +00:00
|
|
|
struct VertexInput {
|
|
|
|
@builtin(vertex_index) index: u32,
|
|
|
|
// NOTE: Instance-rate vertex buffer members prefixed with i_
|
|
|
|
// NOTE: i_model_transpose_colN are the 3 columns of a 3x4 matrix that is the transpose of the
|
|
|
|
// affine 4x3 model matrix.
|
|
|
|
@location(0) i_model_transpose_col0: vec4<f32>,
|
|
|
|
@location(1) i_model_transpose_col1: vec4<f32>,
|
|
|
|
@location(2) i_model_transpose_col2: vec4<f32>,
|
|
|
|
@location(3) i_color: vec4<f32>,
|
|
|
|
@location(4) i_uv_offset_scale: vec4<f32>,
|
|
|
|
}
|
|
|
|
|
2021-06-28 22:36:50 +00:00
|
|
|
struct VertexOutput {
|
2023-09-02 18:03:19 +00:00
|
|
|
@builtin(position) clip_position: vec4<f32>,
|
2022-07-14 21:17:16 +00:00
|
|
|
@location(0) uv: vec2<f32>,
|
2023-09-02 18:03:19 +00:00
|
|
|
@location(1) @interpolate(flat) color: vec4<f32>,
|
2021-06-28 22:36:50 +00:00
|
|
|
};
|
|
|
|
|
2022-07-14 21:17:16 +00:00
|
|
|
@vertex
|
2023-09-02 18:03:19 +00:00
|
|
|
fn vertex(in: VertexInput) -> VertexOutput {
|
2021-06-28 22:36:50 +00:00
|
|
|
var out: VertexOutput;
|
2023-09-02 18:03:19 +00:00
|
|
|
|
|
|
|
let vertex_position = vec3<f32>(
|
|
|
|
f32(in.index & 0x1u),
|
|
|
|
f32((in.index & 0x2u) >> 1u),
|
|
|
|
0.0
|
|
|
|
);
|
|
|
|
|
2024-02-21 01:11:28 +00:00
|
|
|
out.clip_position = view.view_proj * affine3_to_square(mat3x4<f32>(
|
2023-09-02 18:03:19 +00:00
|
|
|
in.i_model_transpose_col0,
|
|
|
|
in.i_model_transpose_col1,
|
|
|
|
in.i_model_transpose_col2,
|
|
|
|
)) * vec4<f32>(vertex_position, 1.0);
|
|
|
|
out.uv = vec2<f32>(vertex_position.xy) * in.i_uv_offset_scale.zw + in.i_uv_offset_scale.xy;
|
|
|
|
out.color = in.i_color;
|
|
|
|
|
2021-06-28 22:36:50 +00:00
|
|
|
return out;
|
2022-06-14 00:32:33 +00:00
|
|
|
}
|
2021-06-28 22:36:50 +00:00
|
|
|
|
2023-09-19 22:17:44 +00:00
|
|
|
@group(1) @binding(0) var sprite_texture: texture_2d<f32>;
|
|
|
|
@group(1) @binding(1) var sprite_sampler: sampler;
|
2021-06-28 22:36:50 +00:00
|
|
|
|
2022-07-14 21:17:16 +00:00
|
|
|
@fragment
|
|
|
|
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
|
2023-09-02 18:03:19 +00:00
|
|
|
var color = in.color * textureSample(sprite_texture, sprite_sampler, in.uv);
|
2022-10-26 20:13:59 +00:00
|
|
|
|
|
|
|
#ifdef TONEMAP_IN_SHADER
|
2023-10-21 11:51:58 +00:00
|
|
|
color = tonemapping::tone_mapping(color, view.color_grading);
|
2022-10-26 20:13:59 +00:00
|
|
|
#endif
|
|
|
|
|
Sprite Batching (#3060)
This implements the following:
* **Sprite Batching**: Collects sprites in a vertex buffer to draw many sprites with a single draw call. Sprites are batched by their `Handle<Image>` within a specific z-level. When possible, sprites are opportunistically batched _across_ z-levels (when no sprites with a different texture exist between two sprites with the same texture on different z levels). With these changes, I can now get ~130,000 sprites at 60fps on the `bevymark_pipelined` example.
* **Sprite Color Tints**: The `Sprite` type now has a `color` field. Non-white color tints result in a specialized render pipeline that passes the color in as a vertex attribute. I chose to specialize this because passing vertex colors has a measurable price (without colors I get ~130,000 sprites on bevymark, with colors I get ~100,000 sprites). "Colored" sprites cannot be batched with "uncolored" sprites, but I think this is fine because the chance of a "colored" sprite needing to batch with other "colored" sprites is generally probably way higher than an "uncolored" sprite needing to batch with a "colored" sprite.
* **Sprite Flipping**: Sprites can be flipped on their x or y axis using `Sprite::flip_x` and `Sprite::flip_y`. This is also true for `TextureAtlasSprite`.
* **Simpler BufferVec/UniformVec/DynamicUniformVec Clearing**: improved the clearing interface by removing the need to know the size of the final buffer at the initial clear.
![image](https://user-images.githubusercontent.com/2694663/140001821-99be0d96-025d-489e-9bfa-ba19c1dc9548.png)
Note that this moves sprites away from entity-driven rendering and back to extracted lists. We _could_ use entities here, but it necessitates that an intermediate list is allocated / populated to collect and sort extracted sprites. This redundant copy, combined with the normal overhead of spawning extracted sprite entities, brings bevymark down to ~80,000 sprites at 60fps. I think making sprites a bit more fixed (by default) is worth it. I view this as acceptable because batching makes normal entity-driven rendering pretty useless anyway (and we would want to batch most custom materials too). We can still support custom shaders with custom bindings, we'll just need to define a specific interface for it.
2021-11-04 20:28:53 +00:00
|
|
|
return color;
|
2022-06-14 00:32:33 +00:00
|
|
|
}
|