2022-10-26 20:13:59 +00:00
|
|
|
#ifdef TONEMAP_IN_SHADER
|
|
|
|
#import bevy_core_pipeline::tonemapping
|
|
|
|
#endif
|
|
|
|
|
2023-09-02 18:03:19 +00:00
|
|
|
#import bevy_render::maths affine_to_square
|
improve shader import model (#5703)
# Objective
operate on naga IR directly to improve handling of shader modules.
- give codespan reporting into imported modules
- allow glsl to be used from wgsl and vice-versa
the ultimate objective is to make it possible to
- provide user hooks for core shader functions (to modify light
behaviour within the standard pbr pipeline, for example)
- make automatic binding slot allocation possible
but ... since this is already big, adds some value and (i think) is at
feature parity with the existing code, i wanted to push this now.
## Solution
i made a crate called naga_oil (https://github.com/robtfm/naga_oil -
unpublished for now, could be part of bevy) which manages modules by
- building each module independantly to naga IR
- creating "header" files for each supported language, which are used to
build dependent modules/shaders
- make final shaders by combining the shader IR with the IR for imported
modules
then integrated this into bevy, replacing some of the existing shader
processing stuff. also reworked examples to reflect this.
## Migration Guide
shaders that don't use `#import` directives should work without changes.
the most notable user-facing difference is that imported
functions/variables/etc need to be qualified at point of use, and
there's no "leakage" of visible stuff into your shader scope from the
imports of your imports, so if you used things imported by your imports,
you now need to import them directly and qualify them.
the current strategy of including/'spreading' `mesh_vertex_output`
directly into a struct doesn't work any more, so these need to be
modified as per the examples (e.g. color_material.wgsl, or many others).
mesh data is assumed to be in bindgroup 2 by default, if mesh data is
bound into bindgroup 1 instead then the shader def `MESH_BINDGROUP_1`
needs to be added to the pipeline shader_defs.
2023-06-27 00:29:22 +00:00
|
|
|
#import bevy_render::view View
|
2023-02-11 17:55:18 +00:00
|
|
|
|
2022-07-14 21:17:16 +00:00
|
|
|
@group(0) @binding(0)
|
2021-10-08 19:55:24 +00:00
|
|
|
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
|
|
|
|
);
|
|
|
|
|
|
|
|
out.clip_position = view.view_proj * affine_to_square(mat3x4<f32>(
|
|
|
|
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
|
|
|
|
2022-07-14 21:17:16 +00:00
|
|
|
@group(1) @binding(0)
|
2021-06-28 22:36:50 +00:00
|
|
|
var sprite_texture: texture_2d<f32>;
|
2022-07-14 21:17:16 +00:00
|
|
|
@group(1) @binding(1)
|
2021-06-28 22:36:50 +00:00
|
|
|
var sprite_sampler: sampler;
|
|
|
|
|
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
|
improve shader import model (#5703)
# Objective
operate on naga IR directly to improve handling of shader modules.
- give codespan reporting into imported modules
- allow glsl to be used from wgsl and vice-versa
the ultimate objective is to make it possible to
- provide user hooks for core shader functions (to modify light
behaviour within the standard pbr pipeline, for example)
- make automatic binding slot allocation possible
but ... since this is already big, adds some value and (i think) is at
feature parity with the existing code, i wanted to push this now.
## Solution
i made a crate called naga_oil (https://github.com/robtfm/naga_oil -
unpublished for now, could be part of bevy) which manages modules by
- building each module independantly to naga IR
- creating "header" files for each supported language, which are used to
build dependent modules/shaders
- make final shaders by combining the shader IR with the IR for imported
modules
then integrated this into bevy, replacing some of the existing shader
processing stuff. also reworked examples to reflect this.
## Migration Guide
shaders that don't use `#import` directives should work without changes.
the most notable user-facing difference is that imported
functions/variables/etc need to be qualified at point of use, and
there's no "leakage" of visible stuff into your shader scope from the
imports of your imports, so if you used things imported by your imports,
you now need to import them directly and qualify them.
the current strategy of including/'spreading' `mesh_vertex_output`
directly into a struct doesn't work any more, so these need to be
modified as per the examples (e.g. color_material.wgsl, or many others).
mesh data is assumed to be in bindgroup 2 by default, if mesh data is
bound into bindgroup 1 instead then the shader def `MESH_BINDGROUP_1`
needs to be added to the pipeline shader_defs.
2023-06-27 00:29:22 +00:00
|
|
|
color = bevy_core_pipeline::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
|
|
|
}
|