Skip to content

Commit

Permalink
Bug fixes, plugin passthrough, documentation updates.. (#55)
Browse files Browse the repository at this point in the history
- Add limitations section in readme
- Add breakout Bevy example showcase in readme
- Fix LUT shader: Green and blue channels were swapped
- Allow added plugins to be skipped via a passthrough functionality
- Add LUTs when not feature dev such that external users may use them. Also list the available ones in docs.
- Add missing raindrops tga when not feature dev
- Fix minor doc issues:
    - Copy pasted text
    - Hide macros not meant to be used externally

Signed-off-by: Torstein Grindvik <torstein.grindvik@nordicsemi.no>
  • Loading branch information
torsteingrindvik authored Oct 29, 2022
1 parent f0bc31e commit 7906a03
Show file tree
Hide file tree
Showing 29 changed files with 786 additions and 225 deletions.
30 changes: 15 additions & 15 deletions .github/workflows/basics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,21 @@ jobs:
command: check
args: --all-targets --features dev

test:
name: Test Suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Install alsa and udev
run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
- uses: actions-rs/cargo@v1
with:
command: test
# test:
# name: Test Suite
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
# - uses: actions-rs/toolchain@v1
# with:
# profile: minimal
# toolchain: stable
# override: true
# - name: Install alsa and udev
# run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
# - uses: actions-rs/cargo@v1
# with:
# command: test

fmt:
name: Rustfmt
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ alsa = "=0.6.0"

[dev-dependencies]
bevy = { git = "https://github.com/bevyengine/bevy", features = ["tga"] }
# bevy = { path = "../bevy", features = ["tga"] }

color-eyre = "0.6"
image = "0.24"
Expand Down
37 changes: 32 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,23 @@

This crate has an assortment of effects easily applied to Bevy apps via plugins.

## Getting started
Here is a showcase made by adding some visual effects to Bevy's breakout example.
Note that the game itself is not modified except visually.

[Breakout Video](https://user-images.githubusercontent.com/52322338/198832540-a1a2fa00-8c75-4f55-a3e7-b4ce18fef958.mp4)

The effects added in the above are:

### Bevy compatibility
- A raindrop effect (due to effects applied after this one it gives the impression of static noise across the screen).
- Chromatic aberration.
- Waves. This effect causes the general "waviness" seen as well as the collision shake effect.
- A CRT mask. This changes the edges of the screen to resemeble a CRT.
- Pixelation. This pixelates the image. The demo increases this effect slightly each time a collision happens, but it's a bit hard to notice due to the short length of the video.
- Color grading. A color lookup texture is applied, which changes the color output accordingly.

Scroll down to see videos of the examples in contained in this repo.

## Bevy compatibility

When adding this crate as a dependency in your project,
the Bevy version you use will need to match up according to the
Expand All @@ -14,7 +28,7 @@ following table:
|---|---|
|0.1 (unreleased)|0.9 (unreleased)|

### In your code
## Getting started

The general strategy is:

Expand Down Expand Up @@ -48,9 +62,15 @@ fn update(mut flip: ResMut<Flip>) {
}
```

## Limitations

- You can only use a single camera as the source for effects.
- You cannot change the order of applied effects at runtime- this is decided by plugin insertion order when making the `App`.
- You can toggle effects off/on at runtime- but the shaders will still run. They simply pass through the input image to the output, but this requires a texture sample. Therefore there is likely a slight performance cost for added-but-disabled effects.

## Examples

All videos are captured from running the [examples](https://github.com/torsteingrindvik/bevy-vfx-bag/tree/main/examples).
All videos below are captured from running the [examples](https://github.com/torsteingrindvik/bevy-vfx-bag/tree/main/examples).

Do `cargo r --example` in this repository to get a list of examples you may run.
Some examples use keyboard/mouse input to change parameters at runtime as well.
Expand Down Expand Up @@ -123,6 +143,14 @@ Not shown is changing the radius, and changing the color of the vignette.

[Vignette Example Video](https://user-images.githubusercontent.com/52322338/195917174-0be12446-d527-4d81-8e0d-24370b8bdd03.mp4)

### T-Rex

Shows another use of the wave effect.
By having a violent wave effect we can simulate something like the earth shaking due to something
big approaching by toggling the effect in intervals.

[T-Rex Example Video](https://user-images.githubusercontent.com/52322338/198832244-4898bbe9-4b24-4ddb-a5d5-665f3ecc71e3.mp4)

### Underwater

Underwater (ish) effect.
Expand All @@ -145,4 +173,3 @@ which might be achieved by having a high number of waves at high speed with low
and quickly dampening those parameters to zero so the effect ends.

[Wave Example Video](https://user-images.githubusercontent.com/52322338/195917192-461fd2a1-8bdf-4671-bfce-a1182de41fb1.mp4)

13 changes: 6 additions & 7 deletions assets/shaders/blur.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,16 @@ fn s_blurred(uv: vec2<f32>) -> vec3<f32> {
;
}

@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {
let uv = coords_to_viewport_uv(position.xy, view.viewport);

fn fragment_impl(
position: vec4<f32>,
uv: vec2<f32>
) -> vec4<f32> {
let original = s(uv);
let blurred = s_blurred(uv);

let output = mix(original, blurred, blur.amount);

return vec4<f32>(output, 1.0);
}

#import bevy_vfx_bag::post_processing_passthrough
13 changes: 6 additions & 7 deletions assets/shaders/chromatic-aberration.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@ struct ChromaticAberration {
@group(1) @binding(2)
var<uniform> chromatic_aberration: ChromaticAberration;

@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {
let uv = coords_to_viewport_uv(position.xy, view.viewport);

fn fragment_impl(
position: vec4<f32>,
uv: vec2<f32>
) -> vec4<f32> {
let out = vec3<f32>(
textureSample(texture, our_sampler, uv + (chromatic_aberration.dir_r * chromatic_aberration.magnitude_r)).r,
textureSample(texture, our_sampler, uv + (chromatic_aberration.dir_g * chromatic_aberration.magnitude_g)).g,
Expand All @@ -36,3 +33,5 @@ fn fragment(

return vec4<f32>(out, 1.0);
}

#import bevy_vfx_bag::post_processing_passthrough
15 changes: 7 additions & 8 deletions assets/shaders/flip.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ struct FlipUniform {
@group(1) @binding(2)
var<uniform> flip: FlipUniform;

@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {
let uv_unaltered = coords_to_viewport_uv(position.xy, view.viewport);
let uv = abs(vec2<f32>(flip.x, flip.y) - uv_unaltered);

fn fragment_impl(
position: vec4<f32>,
uv: vec2<f32>
) -> vec4<f32> {
let uv = abs(vec2<f32>(flip.x, flip.y) - uv);
return vec4<f32>(textureSample(texture, our_sampler, uv).rgb, 1.0);
}

#import bevy_vfx_bag::post_processing_passthrough
23 changes: 14 additions & 9 deletions assets/shaders/lut.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,32 @@ var lut: texture_3d<f32>;
@group(1) @binding(3)
var lut_sampler: sampler;

@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {
let uv = coords_to_viewport_uv(position.xy, view.viewport);

fn fragment_impl(
position: vec4<f32>,
uv: vec2<f32>
) -> vec4<f32> {
// https://developer.nvidia.com/gpugems/gpugems2/part-iii-high-quality-rendering/chapter-24-using-lookup-tables-accelerate-color
// I'm honestly not sure why this is necessary, I don't quite follow the reasoning.
// But the neutral LUT seems indistinguishable from the original input texture
// when this is used. Great!
let half_texel = vec3<f32>(1.0 / 64. / 2.);

let raw_color = textureSample(texture, our_sampler, uv).rgb;
// Notice the ".rbg".
// If we sample the LUT using ".rgb" instead,
// the way the 3D texture is loaded will mean the
// green and blue colors are swapped.
// This mitigates that.
let raw_color = textureSample(texture, our_sampler, uv).rbg;

var out = textureSample(lut, lut_sampler, raw_color + half_texel).rgb;

#ifdef SPLIT_VERTICALLY
if (uv.x > 0.5) {
if (uv.x < 0.5) {
out = raw_color;
}
#endif

return vec4<f32>(out, 1.0);
}

#import bevy_vfx_bag::post_processing_passthrough
14 changes: 6 additions & 8 deletions assets/shaders/masks.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,12 @@ fn vignette(uv: vec2<f32>) -> f32 {
}
#endif

@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {

let uv = coords_to_viewport_uv(position.xy, view.viewport);
fn fragment_impl(
position: vec4<f32>,
uv: vec2<f32>
) -> vec4<f32> {
let t = textureSample(texture, our_sampler, uv);


#ifdef SQUARE
let mask = square(uv);
#endif
Expand All @@ -98,3 +94,5 @@ fn fragment(

return vec4<f32>(t.rgb * mask, 1.0);
}

#import bevy_vfx_bag::post_processing_passthrough
14 changes: 7 additions & 7 deletions assets/shaders/pixelate.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ struct Pixelate {
@group(1) @binding(2)
var<uniform> pixelate: Pixelate;

@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {
var uv = coords_to_viewport_uv(position.xy, view.viewport);
uv += 0.5;
fn fragment_impl(
position: vec4<f32>,
uv: vec2<f32>
) -> vec4<f32> {
var uv = uv + 0.5;

let width_height_over_block_size = view.viewport.zw / max(1.0, pixelate.block_size);

Expand All @@ -32,3 +30,5 @@ fn fragment(

return vec4<f32>(textureSample(texture, our_sampler, uv).rgb, 1.0);
}

#import bevy_vfx_bag::post_processing_passthrough
14 changes: 7 additions & 7 deletions assets/shaders/raindrops.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,10 @@ fn animation(raindrops_b: f32) -> f32 {
return fract(raindrops_b - (globals.time * raindrops.time_scaling));
}

@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {
let uv = coords_to_viewport_uv(position.xy, view.viewport);

fn fragment_impl(
position: vec4<f32>,
uv: vec2<f32>
) -> vec4<f32> {
// Raindrops texture wraps.
// Make aspect-ratio independent UV coords.
let uv_aspect_fixed = vec2<f32>(uv.x * view.viewport.z / view.viewport.w, uv.y);
Expand All @@ -65,4 +62,7 @@ fn fragment(
let masked_norms = mask * offset;

return vec4<f32>(textureSample(texture, our_sampler, uv + masked_norms).rgb, 1.0);

}

#import bevy_vfx_bag::post_processing_passthrough
14 changes: 7 additions & 7 deletions assets/shaders/wave.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@ struct Wave {
@group(1) @binding(2)
var<uniform> wave: Wave;

@fragment
fn fragment(
@builtin(position) position: vec4<f32>,
#import bevy_sprite::mesh2d_vertex_output
) -> @location(0) vec4<f32> {
let uv = coords_to_viewport_uv(position.xy, view.viewport);

fn fragment_impl(
position: vec4<f32>,
uv: vec2<f32>
) -> vec4<f32> {
let pi_uv = PI * uv;
let pi_time = PI * globals.time;

Expand All @@ -37,4 +34,7 @@ fn fragment(
let uv_displaced = vec2<f32>(uv.x + offset_x, uv.y + offset_y);

return vec4<f32>(textureSample(texture, our_sampler, uv_displaced).rgb, 1.0);

}

#import bevy_vfx_bag::post_processing_passthrough
22 changes: 12 additions & 10 deletions examples/examples_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ impl Default for ExampleText {

impl Plugin for SaneDefaultsPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(AssetServerSettings {
watch_for_changes: true,
..default()
})
.init_resource::<ExampleText>()
.add_plugins(DefaultPlugins)
.add_system(bevy::window::close_on_esc);
app.init_resource::<ExampleText>()
.add_plugins(
DefaultPlugins
.set(AssetPlugin {
watch_for_changes: true,
..default()
})
.set(ImagePlugin::default_nearest()),
)
.add_system(bevy::window::close_on_esc);
}
}

Expand Down Expand Up @@ -60,8 +63,7 @@ pub(crate) struct ShouldAdd3dCameraBundle(bool);

impl Plugin for ShapesExamplePlugin {
fn build(&self, app: &mut App) {
app.insert_resource(ImageSettings::default_nearest())
.insert_resource(ShouldAdd3dCameraBundle(self.add_3d_camera_bundle))
app.insert_resource(ShouldAdd3dCameraBundle(self.add_3d_camera_bundle))
.add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_startup_system(shapes::setup)
.add_startup_system(ui::setup)
Expand Down Expand Up @@ -223,7 +225,7 @@ mod ui {
"hello\nbevy!",
TextStyle {
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
font_size: 40.0,
font_size: 30.0,
color: Color::WHITE,
},
) // Set the alignment of the Text
Expand Down
Loading

0 comments on commit 7906a03

Please sign in to comment.