Full Code of eliotbo/bevy_shadertoy_wgsl for AI

main e3221a81dd6f cached
329 files
32.9 MB
409.7k tokens
169 symbols
1 requests
Download .txt
Showing preview only (1,190K chars total). Download the full file or copy to clipboard to get everything.
Repository: eliotbo/bevy_shadertoy_wgsl
Branch: main
Commit: e3221a81dd6f
Files: 329
Total size: 32.9 MB

Directory structure:
gitextract_8_6g6_1p/

├── .gitignore
├── Cargo.toml
├── LICENSES
├── README.md
├── assets/
│   └── shaders/
│       ├── clouds/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── dancing_tree/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── debugger/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── dry_ice/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── fire/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── fire2/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── fluid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── image_load.wgsl
│       ├── interactive_fluid_simulation/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── liquid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── liquid_toy/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── love_and_domination/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── minimal/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── mip_fluid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── mixing_liquid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── molecular_dynamics/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── paint/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   ├── common.wgsl
│       │   └── image.wgsl
│       ├── paint2/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   ├── common.wgsl
│       │   ├── image.wgsl
│       │   └── image2.wgsl
│       ├── paint_streams/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── paint_streams2/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── preludes/
│       │   └── image_prelude
│       ├── protean_clouds/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── seascape/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── simpler_particles/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── simplest_detailed_fluid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── soul/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       └── sunset/
│           ├── buffer_a.wgsl
│           ├── buffer_b.wgsl
│           ├── buffer_c.wgsl
│           ├── buffer_d.wgsl
│           └── image.wgsl
├── bin/
│   ├── assets/
│   │   └── shaders/
│   │       ├── image_load.wgsl
│   │       ├── interactive_fluid_simulation/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── liquid/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── minimal/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── mixing_liquid/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── paint/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   ├── common.wgsl
│   │       │   └── image.wgsl
│   │       ├── paint2/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   ├── common.wgsl
│   │       │   ├── image.wgsl
│   │       │   └── image2.wgsl
│   │       ├── paint_streams/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── preludes/
│   │       │   └── image_prelude
│   │       └── simplest_detailed_fluid/
│   │           ├── buffer_a.wgsl
│   │           ├── buffer_b.wgsl
│   │           ├── buffer_c.wgsl
│   │           ├── buffer_d.wgsl
│   │           └── image.wgsl
│   ├── examples/
│   │   ├── minimal/
│   │   │   ├── buffer_a.wgsl
│   │   │   ├── buffer_b.wgsl
│   │   │   ├── buffer_c.wgsl
│   │   │   ├── buffer_d.wgsl
│   │   │   ├── common.wgsl
│   │   │   └── image.wgsl
│   │   ├── mixing_liquid/
│   │   │   ├── buffer_a.wgsl
│   │   │   ├── buffer_b.wgsl
│   │   │   ├── buffer_c.wgsl
│   │   │   ├── buffer_d.wgsl
│   │   │   ├── common.wgsl
│   │   │   └── image.wgsl
│   │   ├── paint/
│   │   │   ├── buffer_a.wgsl
│   │   │   ├── buffer_b.wgsl
│   │   │   ├── buffer_c.wgsl
│   │   │   ├── buffer_d.wgsl
│   │   │   ├── common.wgsl
│   │   │   └── image.wgsl
│   │   └── paint_streams/
│   │       ├── buffer_a.wgsl
│   │       ├── buffer_b.wgsl
│   │       ├── buffer_c.wgsl
│   │       ├── buffer_d.wgsl
│   │       ├── common.wgsl
│   │       └── image.wgsl
│   ├── main.rs
│   ├── templates/
│   │   ├── buffer_a_template.wgsl
│   │   ├── buffer_b_template.wgsl
│   │   ├── buffer_c_template.wgsl
│   │   ├── buffer_d_template.wgsl
│   │   ├── common.wgsl
│   │   ├── common_prelude.wgsl
│   │   ├── image.wgsl
│   │   └── image_template.wgsl
│   ├── test_renderdoc
│   ├── test_renderdoc.d
│   ├── texture_a.rs
│   ├── texture_b.rs
│   ├── texture_c.rs
│   └── texture_d.rs
├── examples/
│   ├── debugger/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   └── image.wgsl
│   ├── dry_ice/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── dry_ice.rs
│   │   └── image.wgsl
│   ├── fire/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   └── image.wgsl
│   ├── fire2/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── fire2.rs
│   │   └── image.wgsl
│   ├── fluid/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── fluid.rs
│   │   └── image.wgsl
│   ├── liquid_toy/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── liquid_toy.rs
│   ├── minimal/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── minimal.rs
│   ├── paint/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── paint.rs
│   ├── paint_streams/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── paint_streams.rs
│   ├── protean_clouds/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── protean_clouds.rs
│   ├── seascape/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── seascape.rs
│   ├── simpler_particles/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── fps.rs
│   │   ├── image.wgsl
│   │   └── simpler_particles.rs
│   ├── soul/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── soul.rs
│   └── sunset/
│       ├── buffer_a.wgsl
│       ├── buffer_b.wgsl
│       ├── buffer_c.wgsl
│       ├── buffer_d.wgsl
│       ├── common.wgsl
│       ├── image.wgsl
│       └── sunset.rs
└── src/
    ├── lib.rs
    ├── templates/
    │   ├── buffer_a_template.wgsl
    │   ├── buffer_b_template.wgsl
    │   ├── buffer_c_template.wgsl
    │   ├── buffer_d_template.wgsl
    │   ├── common.wgsl
    │   ├── common_prelude.wgsl
    │   ├── debugger.wgsl
    │   ├── image.wgsl
    │   └── image_template.wgsl
    ├── texture_a.rs
    ├── texture_b.rs
    ├── texture_c.rs
    └── texture_d.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================

# Generated by Cargo
# will have compiled files and executables
/target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

.cargo/config.toml

================================================
FILE: Cargo.toml
================================================
[package]
name = "bevy_shadertoy_wgsl"
version = "0.1.0"
edition = "2021"
authors = ["Eliot Bolduc"]

[dependencies]
bytemuck = "1.5"
rand = "0.8"
rand_pcg = "0.3"
serde = { version = "1.0", features = ["derive"] }
anyhow = "1.0"
ron = "0.7"
bitflags = "1.3"
bevy = "0.8"
crevice = "0.11"



[[bin]]
edition = "2021"
name = "bevy_shadertoy_wgsl"
path = "src/main.rs"

# cargo build --release --target wasm32-unknown-unknown 
# wasm-bindgen --out-name wasm_shadertoy --out-dir wasm --target web target/wasm32-unknown-unknown/release/bevy_shadertoy_wgsl.wasm
[[example]]
name = "simpler_particles"
path = "examples/simpler_particles/simpler_particles.rs"

[[example]]
name = "liquid_toy"
path = "examples/liquid_toy/liquid_toy.rs"

[[example]]
name = "soul"
path = "examples/soul/soul.rs"


[[example]]
name = "paint_streams"
path = "examples/paint_streams/paint_streams.rs"

[[example]]
name = "minimal"
path = "examples/minimal/minimal.rs"

[[example]]
name = "paint"
path = "examples/paint/paint.rs"

[[example]]
name = "protean_clouds"
path = "examples/protean_clouds/protean_clouds.rs"

[[example]]
name = "seascape"
path = "examples/seascape/seascape.rs"

[[example]]
name = "fluid"
path = "examples/fluid/fluid.rs"

[[example]]
name = "fire2"
path = "examples/fire2/fire2.rs"

[[example]]
name = "fire"
path = "examples/fire/fire.rs"

[[example]]
name = "dry_ice"
path = "examples/dry_ice/dry_ice.rs"

[[example]]
name = "sunset"
path = "examples/sunset/sunset.rs"

================================================
FILE: LICENSES
================================================
bevy_shadertoy_wgsl is dual-licensed under either

* MIT License (docs/LICENSE-MIT or <http://opensource.org/licenses/MIT>)
* Apache License, Version 2.0 (docs/LICENSE-APACHE or <http://www.apache.org/licenses/LICENSE-2.0>)

at your option.
//
//
//
//

The licenses for the examples taken from shadertoy.com are the following:

seascape ->         Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
fire2 ->            MIT License
protean_clouds ->   License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
sunset ->           MIT License
fluid ->            License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
paint_streams ->    License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
dry_ice ->          License Creative Commons Attribution-NonCommercial-ShareAlike 3.0
soul ->             Attribution-NonCommercial 2.0 Generic (CC BY-NC 2.0)
liquid_toy ->       Attribution-NonCommercial 2.0 Generic (CC BY-NC 2.0)

authors (full name or Shadertoy username):
seascape ->         TDM
fire2 ->            Ian McEwan, Ashima Arts
protean_clouds ->   nimitz
sunset ->           Dimas Leenman
fluid ->            Wyatt Flanders
paint_streams ->    michael0884
dry_ice ->          David Gallardo
soul ->             leon
liquid_toy ->       leon

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

link to licenses:
<https://creativecommons.org/licenses/by-nc/2.0/>
<https://creativecommons.org/licenses/by-nc-sa/3.0/>


================================================
FILE: README.md
================================================
# bevy_shadertoy_wgsl

A Shadertoy clone for the Bevy game engine, where the glsl language is replaced by wgsl.


Clone the repo, and for example run the following command:
```
cargo run --release --features bevy/dynamic --example paint_streams
```
![](showcase.gif)

Here is a GLSL to WGLSL converter that might be helpful: [https://eliotbo.github.io/glsl2wgsl/](https://eliotbo.github.io/glsl2wgsl/)

TODO: make compatible with WASM

See the LICENSES file for the individual examples.


================================================
FILE: assets/shaders/clouds/buffer_a.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;







[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let color = vec4<f32>(0.5);
    textureStore(buffer_a, location, color);
}

================================================
FILE: assets/shaders/clouds/buffer_b.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;





[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/clouds/buffer_c.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;





[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/clouds/buffer_d.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;





[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}


================================================
FILE: assets/shaders/clouds/image.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;



// [[group(0), binding(1)]]
// var buffer_a: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(2)]]
// var buffer_b: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(3)]]
// var buffer_c: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(4)]]
// var buffer_d: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(5)]]
var texture: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(6)]]
// var font_texture: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(6)]]
var font_texture: texture_2d<f32>;

[[group(0), binding(7)]]
var font_texture_sampler: sampler;

[[group(0), binding(8)]]
var rgba_noise_256_texture: texture_2d<f32>;

[[group(0), binding(9)]]
var rgba_noise_256_texture_sampler: sampler;



// [[stage(compute), workgroup_size(8, 8, 1)]]
// fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
//     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
//     let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

//     let color = vec4<f32>(f32(0));
//     textureStore(texture, location, color);
// }





// Sample Pinning
// https://www.shadertoy.com/view/XdfXzn
// MIT License

var<private> STRUCTURED: bool;
var<private> sundir: vec3<f32>;
fn noise(x: vec3<f32>) -> f32 {
	var p: vec3<f32> = floor(x);
	var f: vec3<f32> = fract(x);
	f = f * f * (3. - 2. * f);
	let uv: vec2<f32> = p.xy + vec2<f32>(37., 17.) * p.z + f.xy;
	// let rg: vec2<f32> = textureLod(iChannel0, (uv + 0.5) / 256., 0.).yx;
    // let rg: vec2<f32> = textureLoad(rgba_noise_256_texture, vec2<i32>((uv + 0.5) ), 0).yx;

    let rg: vec2<f32> = textureSampleLevel(
        rgba_noise_256_texture,
        rgba_noise_256_texture_sampler,
        (uv + 0.5) / 256.,
        0.
    ).yx ;

	return mix(rg.x, rg.y, f.z);
} 

fn map(p: vec3<f32>) -> vec4<f32> {
	var d: f32 = 0.1 + 0.8 * sin(0.6 * p.z) * sin(0.5 * p.x) - p.y;
	var q: vec3<f32> = p;
	var f: f32;
	f = 0.5 * noise(q);
	q = q * 2.02;
	f = f + (0.25 * noise(q));
	q = q * 2.03;
	f = f + (0.125 * noise(q));
	q = q * 2.01;
	f = f + (0.0625 * noise(q));
	d = d + (2.75 * f);
	d = clamp(d, 0., 1.);
	var res: vec4<f32> = vec4<f32>(d);
	var col: vec3<f32> = 1.15 * vec3<f32>(1., 0.95, 0.8);
	col = col + (vec3<f32>(1., 0., 0.) * exp2(res.x * 10. - 10.));
	var resxyz = res.xyz;
	resxyz = mix(col, vec3<f32>(0.7, 0.7, 0.7), res.x);
	res.x = resxyz.x;
	res.y = resxyz.y;
	res.z = resxyz.z;
	return res;
} 

fn mysign(x: f32) -> f32 {

	if (x < 0.) { return -1.; } else { return 1.; };
} 

fn mysign2(x: vec2<f32>) -> vec2<f32> {
    var x2: vec2<f32>;
    if (x.x < 0.) { x2.x = -1.; } else { x2.x =1.; };
    if (x.y < 0.) { x2.y = -1.; } else { x2.y = 1.; }
	return x2;
} 

fn SetupSampling(t: ptr<function, vec2<f32>>, dt: ptr<function, vec2<f32>>, wt: ptr<function, vec2<f32>>, ro: vec3<f32>, rd: vec3<f32>)  {
	var rd_var = rd;
	if (!STRUCTURED) {
		(*dt) = vec2<f32>(1., 1.);
		(*t) = (*dt);
		(*wt) = vec2<f32>(0.5, 0.5);
		return ;
	}
	var n0: vec3<f32>; 
    if (abs(rd_var.x) > abs(rd_var.z)) { n0 = vec3<f32>(1., 0., 0.); } else { n0 = vec3<f32>(0., 0., 1.); };

	var n1: vec3<f32> = vec3<f32>(mysign(rd_var.x * rd_var.z), 0., 1.);
	let ln: vec2<f32> = vec2<f32>(length(n0), length(n1));
	n0 = n0 / (ln.x);
	n1 = n1 / (ln.y);
	let ndotro: vec2<f32> = vec2<f32>(dot(ro, n0), dot(ro, n1));
	var ndotrd: vec2<f32> = vec2<f32>(dot(rd_var, n0), dot(rd_var, n1));
	let period: vec2<f32> = ln * 1.;
	(*dt) = period / abs(ndotrd);
	let dist: vec2<f32> = abs(ndotro / ndotrd);
	(*t) = -mysign2(ndotrd) * (ndotro % period) / abs(ndotrd);

	if (ndotrd.x > 0.) { (*t).x = (*t).x + ((*dt).x); }
	if (ndotrd.y > 0.) { (*t).y = (*t).y + ((*dt).y); }
	let minperiod: f32 = 1.;
	let maxperiod: f32 = sqrt(2.) * 1.;
	(*wt) = smoothStep(vec2<f32>(maxperiod), vec2<f32>(minperiod), (*dt) / ln);
	(*wt) = (*wt) / ((*wt).x + (*wt).y);
} 

fn raymarch(ro: vec3<f32>, rd: vec3<f32>) -> vec4<f32> {
	var sum: vec4<f32> = vec4<f32>(0., 0., 0., 0.);
	var t: vec2<f32>;
	var dt: vec2<f32>;
	var wt: vec2<f32>;
	SetupSampling(&t, &dt, &wt, ro, rd);
	let f: f32 = 0.6;
	let endFade: f32 = f * f32(40.) * 1.;
	let startFade: f32 = 0.8 * endFade;

	for (var i: i32 = 0; i < 40; i = i + 1) {
		if (sum.a > 0.99) {		continue;
 }
		var data: vec4<f32>;
        if (t.x < t.y) { data = vec4<f32>(t.x, wt.x, dt.x, 0.); } else { data = vec4<f32>(t.y, wt.y, 0., dt.y); };

		let pos: vec3<f32> = ro + data.x * rd;
		var w: f32 = data.y;
		t = t + (data.zw);
		w = w * (smoothStep(endFade, startFade, data.x));
		var col: vec4<f32> = map(pos);
		let dif: f32 = clamp((col.w - map(pos + 0.6 * sundir).w) / 0.6, 0., 1.);
		let lin: vec3<f32> = vec3<f32>(0.51, 0.53, 0.63) * 1.35 + 0.55 * vec3<f32>(0.85, 0.57, 0.3) * dif;
		var colxyz = col.xyz;
	colxyz = col.xyz * (lin);
	col.x = colxyz.x;
	col.y = colxyz.y;
	col.z = colxyz.z;
		var colxyz = col.xyz;
	colxyz = col.xyz * (col.xyz);
	col.x = colxyz.x;
	col.y = colxyz.y;
	col.z = colxyz.z;
		col.a = col.a * (0.75);
		var colrgb = col.rgb;
	colrgb = col.rgb * (col.a);
	col.r = colrgb.r;
	col.g = colrgb.g;
	col.b = colrgb.b;
		sum = sum + (col * (1. - sum.a) * w);
	}

	var sumxyz = sum.xyz;
	sumxyz = sum.xyz / (0.001 + sum.w);
	sum.x = sumxyz.x;
	sum.y = sumxyz.y;
	sum.z = sumxyz.z;
	return clamp(sum, vec4<f32>(0.), vec4<f32>(1.));
} 

fn sky(rd: vec3<f32>) -> vec3<f32> {
	var col: vec3<f32> = vec3<f32>(0.);
	let hort: f32 = 1. - clamp(abs(rd.y), 0., 1.);
	col = col + (0.5 * vec3<f32>(0.99, 0.5, 0.) * exp2(hort * 8. - 8.));
	col = col + (0.1 * vec3<f32>(0.5, 0.9, 1.) * exp2(hort * 3. - 3.));
	col = col + (0.55 * vec3<f32>(0.6, 0.6, 0.9));
	let sun: f32 = clamp(dot(sundir, rd), 0., 1.);
	col = col + (0.2 * vec3<f32>(1., 0.3, 0.2) * pow(sun, 2.));
	col = col + (0.5 * vec3<f32>(1., 0.9, 0.9) * exp2(sun * 650. - 650.));
	col = col + (0.1 * vec3<f32>(1., 1., 0.1) * exp2(sun * 100. - 100.));
	col = col + (0.3 * vec3<f32>(1., 0.7, 0.) * exp2(sun * 50. - 50.));
	col = col + (0.5 * vec3<f32>(1., 0.3, 0.05) * exp2(sun * 10. - 10.));
	let ax: f32 = atan2(rd.y, length(rd.xz)) / 1.;
	let ay: f32 = atan2(rd.z, rd.x) / 2.;
    
	var st: f32 = textureLoad(rgba_noise_256_texture, vec2<i32>(vec2<f32>(ax, ay) * 255.), 0 ).x;

	let st2: f32 = textureLoad(rgba_noise_256_texture, vec2<i32>(0.25 * vec2<f32>(ax, ay) * 255.), 0 ).x;
	st = st * (st2);
	st = smoothStep(0.65, 0.9, st);
	col = mix(col, col + 1.8 * st, clamp(1. - 1.1 * length(col), 0., 1.));
	return col;
} 

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

	var fragColor: vec4<f32>;
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

	STRUCTURED = uni.iMouse.z <= 0.;
	sundir = normalize(vec3<f32>(-1., 0., -1.));
	let q: vec2<f32> = fragCoord.xy / uni.iResolution.xy;
	var p: vec2<f32> = -1. + 2. * q;
	p.x = p.x * (uni.iResolution.x / uni.iResolution.y);
	let mo: vec2<f32> = -1. + 2. * uni.iMouse.xy / uni.iResolution.xy;
	let lookDir: vec3<f32> = vec3<f32>(cos(0.53 * uni.iTime), 0., sin(uni.iTime));
	let camVel: vec3<f32> = vec3<f32>(-20., 0., 0.);
	let ro: vec3<f32> = vec3<f32>(0., 1.5, 0.) + uni.iTime * camVel;
	let ta: vec3<f32> = ro + lookDir;
	let ww: vec3<f32> = normalize(ta - ro);
	let uu: vec3<f32> = normalize(cross(vec3<f32>(0., 1., 0.), ww));
	let vv: vec3<f32> = normalize(cross(ww, uu));
	let fov: f32 = 1.;
	let rd: vec3<f32> = normalize(fov * p.x * uu + fov * 1.2 * p.y * vv + 1.5 * ww);
	var clouds: vec4<f32> = raymarch(ro, rd);
	var col: vec3<f32> = clouds.xyz;
	if (clouds.w <= 0.99) { col = mix(sky(rd), col, clouds.w); }
	col = clamp(col, vec3<f32>(0.), vec3<f32>(1.));
	col = smoothStep(vec3<f32>(0.), vec3<f32>(1.), col);
	col = col * (pow(16. * q.x * q.y * (1. - q.x) * (1. - q.y), 0.12));
	// (*fragColor) = vec4<f32>(col, 1.);
    textureStore(texture, y_inverted_location, vec4<f32>(col, 1.));

    let test: vec4<f32> = textureSampleLevel(
        rgba_noise_256_texture,
        rgba_noise_256_texture_sampler,
        vec2<f32>(location) / R * 2.0,
        0.
    ) ;

    // textureStore(texture, y_inverted_location, test);


} 




    



// [[stage(compute), workgroup_size(8, 8, 1)]]
// fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
//     let R: vec2<f32> = uni.iResolution.xy;
//     let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
//     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

// 	if (uni.iMouse.z > 0.) { useNewApproach = false; }
// 	let q: vec2<f32> = fragCoord.xy / uni.iResolution.xy;
// 	var p: vec2<f32> = -1. + 2. * q;
// 	p.x = p.x * (uni.iResolution.x / uni.iResolution.y);
// 	let mo: vec2<f32> = -1. + 2. * uni.iMouse.xy / uni.iResolution.xy;
// 	let ro: vec3<f32> = vec3<f32>(0., 1.9, 0.) + uni.iTime * camVel;
// 	let ta: vec3<f32> = ro + lookDir;
// 	let ww: vec3<f32> = normalize(ta - ro);
// 	let uu: vec3<f32> = normalize(cross(vec3<f32>(0., 1., 0.), ww));
// 	let vv: vec3<f32> = normalize(cross(ww, uu));
// 	let rd: vec3<f32> = normalize(p.x * uu + 1.2 * p.y * vv + 1.5 * ww);
// 	var col: vec3<f32> = sky(rd);
// 	let rd_layout: vec3<f32> = rd / mix(dot(rd, ww), 1., samplesCurvature);
// 	let clouds: vec4<f32> = raymarch(ro, rd_layout);
// 	col = mix(col, clouds.xyz, clouds.w);
// 	col = clamp(col, 0., 1.);
// 	col = smoothStep(0., 1., col);
// 	col = col * (pow(16. * q.x * q.y * (1. - q.x) * (1. - q.y), 0.12));
// 	// (*fragColor) = vec4<f32>(col, 1.);
//     textureStore(texture, y_inverted_location, vec4<f32>(col, 1.));

    
// } 



================================================
FILE: assets/shaders/dancing_tree/buffer_a.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;





[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let color = vec4<f32>(0.5);
    textureStore(buffer_a, location, color);
}

================================================
FILE: assets/shaders/dancing_tree/buffer_b.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;



[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/dancing_tree/buffer_c.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;



[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/dancing_tree/buffer_d.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;



[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}


================================================
FILE: assets/shaders/dancing_tree/image.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(5)]]
var texture: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(6)]]
// var font_texture: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(6)]]
var font_texture: texture_2d<f32>;

[[group(0), binding(7)]]
var font_texture_sampler: sampler;

[[group(0), binding(8)]]
var rgba_noise_256_texture: texture_2d<f32>;

[[group(0), binding(9)]]
var rgba_noise_256_texture_sampler: sampler;

// [[stage(compute), workgroup_size(8, 8, 1)]]
// fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
//     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
//     let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

//     let color = vec4<f32>(f32(0));
//     textureStore(texture, location, color);
// }

// Why are the characters so pixelated? 
// One possible reason is that we are in a compute shader and the textures are not
// filtered.

let backColorDebug: vec3<f32> = vec3<f32>(0.2, 0.2, 0.2);


var<private> uv_debug: vec2<f32> ;
var<private> tp_debug: vec2<f32> ;
var<private> align_debug: vec4<f32>; // north, east, south, west
var<private> font_size_debug: f32;
var<private> dotColor_debug: vec3<f32> = vec3<f32>(0.5, 0.5, 0.);
var<private> drawColorDebug: vec3<f32> = vec3<f32>(1., 1., 0.);
var<private> vColor: vec3<f32> = backColorDebug;
var<private> aspect_debug: f32 = 1.;
var<private> pixelPosDebug: vec2<f32> = vec2<f32>(0., 0.);

let FONT_SPACE_DEBUG: f32 = 0.5;
let headColorDebug: vec3<f32> = vec3<f32>(0.9, 0.6, 0.2);
let mpColorDebug: vec3<f32> = vec3<f32>(0.99, 0.99, 0.);
let mxColorDebug: vec3<f32> = vec3<f32>(1., 0., 0.);
let myColorDebug: vec3<f32> = vec3<f32>(0., 1., 0.);
let font_png_size_debug: vec2<f32> = vec2<f32>(1023.0, 1023.0);

fn char(ch: i32) -> f32 {

    let fr = fract(floor(vec2<f32>(f32(ch), 15.999 - f32(ch) / 16.)) / 16.);
	let q = clamp(tp_debug, vec2<f32>(0.), vec2<f32>(1.)) / 16. + fr ;
	let inverted_q = vec2<f32>(q.x, 1. - q.y);

	// // There is aliasing on the characters
	// let f = textureSampleGrad(font_texture,
    //                  font_texture_sampler,
    //                  inverted_q,
    //                   vec2<f32>(1.0, 0.0),
    //                  vec2<f32>(0.0, 1.0));

	// using textureLoad without sampler
    let q1 = vec2<i32>(font_png_size_debug  * q );
	let y_inverted_q1 = vec2<i32>(q1.x, i32(font_png_size_debug.y) - q1.y);

	var f: vec4<f32> = textureLoad(font_texture, y_inverted_q1 , 0);

	// smoothing out the aliasing
	let dx = vec2<i32>(1, 0);
	let dy = vec2<i32>(0, 1);

	let fx1: vec4<f32> = textureLoad(font_texture, y_inverted_q1 + dx, 0);
	let fx2: vec4<f32> = textureLoad(font_texture, y_inverted_q1 - dx, 0);
	let fy1: vec4<f32> = textureLoad(font_texture, y_inverted_q1 + dy, 0);
	let fy2: vec4<f32> = textureLoad(font_texture, y_inverted_q1 - dy, 0);

	let rp = 0.25;
	f = f * rp + (1.0 - rp) * (fx1 + fx2 + fy1 + fy2) / 4.0 ;

	return f.x * (f.y + 0.3) * (f.z + 0.3) * 2.;
} 

fn SetTextPosition(x: f32, y: f32)  {
	tp_debug =  10. * uv_debug;
	tp_debug.x = tp_debug.x + 17. - x;
	tp_debug.y = tp_debug.y - 9.4 + y;
} 

fn SetTextPositionAbs(x: f32, y: f32)  {
	tp_debug.x = 10. * uv_debug.x - x;
	tp_debug.y = 10. * uv_debug.y - y;
} 

fn drawFract(value: ptr<function, f32>, digits:  ptr<function, i32>) -> f32 {
	var c: f32 = 0.;
	*value = fract(*value) * 10.;

	for (var ni: i32 = 1; ni < 60; ni = ni + 1) {
		c = c + (char(48 + i32(*value)));
		tp_debug.x = tp_debug.x - (0.5);
		*digits = *digits - (1);
		*value = fract(*value) * 10.;

		if (*digits <= 0 || *value == 0.) {		
            break;
        }
	}

	tp_debug.x = tp_debug.x - (0.5 * f32(*digits));
	return c;
} 

fn maxInt(a: i32, b: i32) -> i32 {
    var ret: i32;
    if (a > b) { ret = a; } else { ret = b; };
	return ret;
} 

fn drawInt(value: ptr<function, i32>,  minDigits: ptr<function, i32>) -> f32 {
	var c: f32 = 0.;
	if (*value < 0) {
		*value = -*value;
		if (*minDigits < 1) {		
			*minDigits = 1;
		} else { 
			*minDigits = *minDigits - 1;
		}
		c = c + (char(45));
		tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

	}
	var fn2: i32 = *value;
	var digits: i32 = 1;

	for (var ni: i32 = 0; ni < 10; ni = ni + 1) {
		fn2 = fn2 / (10);
		if (fn2 == 0) {		break; }
		digits = digits + 1;
	}

	digits = maxInt(*minDigits, digits);
	tp_debug.x = tp_debug.x - (0.5 * f32(digits));

	for (var ni: i32 = 1; ni < 11; ni = ni + 1) {
		tp_debug.x = tp_debug.x + (0.5);
		c = c + (char(48 + *value % 10));
		*value = *value / (10);
		if (ni >= digits) {		break; }
	}

	tp_debug.x = tp_debug.x - (0.5 * f32(digits));
	return c;
} 

fn drawIntBackwards(value: ptr<function, i32>,  minDigits: ptr<function, i32>) -> f32 {
	var c: f32 = 0.;
	let original_value: i32 = *value;

	if (*value < 0) {
		*value = -*value;
		if (*minDigits < 1) {		
			*minDigits = 1;
		} else { 
			*minDigits = *minDigits - 1;
		}
		// tp_debug.x = tp_debug.x + (FONT_SPACE_DEBUG);
		// c = c + (char(45));
		

	}
	var fn2: i32 = *value;
	var digits: i32 = 1;

	for (var ni: i32 = 0; ni < 10; ni = ni + 1) {
		fn2 = fn2 / (10);
		if (fn2 == 0) {		break; }
		digits = digits + 1;
	}

	digits = maxInt(*minDigits, digits);
	// tp_debug.x = tp_debug.x - (0.5 * f32(digits));

	for (var ni: i32 = digits - 1; ni < 11; ni = ni - 1) {
		tp_debug.x = tp_debug.x + (0.5);
		c = c + (char(48 + *value % 10));
		*value = *value / (10);
		if (ni == 0) {		break; }
	}

	if (original_value < 0) {
		tp_debug.x = tp_debug.x + (FONT_SPACE_DEBUG);
		c = c + (char(45));
	}

	// tp_debug.x = tp_debug.x + (0.5 * f32(digits));
	return c;
} 

// fn drawFloat(value: ptr<function, f32>, prec: ptr<function, i32>, maxDigits: i32) -> f32 {
fn drawFloat(val: f32, prec: ptr<function, i32>, maxDigits: i32) -> f32 {
	// in case of 0.099999..., round up to 0.1000000
	var value = round(val * pow(10., f32(maxDigits))) / pow(10., f32(maxDigits));

	let tp_debugx: f32 = tp_debug.x - 0.5 * f32(maxDigits);
	var c: f32 = 0.;
	if (value < 0.) {
		c = char(45);
		value = -value;
	}
	tp_debug.x = tp_debug.x - (0.5);
    var ival = i32(value);

    var one: i32 = 1;

	c = c + (drawInt(&ival, &one));
	c = c + (char(46));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

    var frac_val = fract(value);
	c = c + (drawFract(&frac_val, prec));
	tp_debug.x = min(tp_debug.x, tp_debugx);

	return c;
}

fn drawFloat_f32(value:  f32) -> f32 {
    var two: i32 = 2;
	return drawFloat(value, &two, 5);
} 

fn drawFloat_f32_prec(value: f32, prec: ptr<function, i32>) -> f32 {
	return drawFloat(value, prec, 2);
} 

fn drawInt_i32_back(value: ptr<function, i32>) -> f32 {
    var one: i32 = 1;
	return drawIntBackwards(value, &one);
} 

fn drawInt_i32(value: ptr<function, i32>) -> f32 {
    var one: i32 = 1;
	return drawInt(value, &one);
} 





fn SetColor(red: f32, green: f32, blue: f32)  {
	drawColorDebug = vec3<f32>(red, green, blue);
} 

fn WriteFloat(fValue: f32, maxDigits: i32, decimalPlaces: ptr<function, i32>)  {

	// vColor = mix(vColor, drawColorDebug, drawFloat_f32_prec(fValue, decimalPlaces));
	vColor = mix(vColor, drawColorDebug, drawFloat(fValue, decimalPlaces, maxDigits));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
;
} 

fn WriteFloatBox(
	fValue: f32, 
	maxDigits: i32, 
	decimalPlaces: i32, 
	alpha: f32
)  {
	var decs = decimalPlaces;
	vColor = mix(vColor, drawColorDebug, drawFloat(fValue, &decs, maxDigits) * alpha);
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
;
} 

fn WriteInteger(iValue: ptr<function, i32>)  {
	vColor = mix(vColor, drawColorDebug, drawInt_i32(iValue));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

} 

fn WriteIntegerBack(iValue: ptr<function, i32>)  {
	vColor = mix(vColor, drawColorDebug, drawInt_i32_back(iValue));
	tp_debug.x = tp_debug.x + (FONT_SPACE_DEBUG);

} 



fn WriteFPS()  {
	var fps: f32 = f32(uni.iSampleRate);
	SetColor(0.8, 0.6, 0.3);
	var max_digits_one = 1;
	WriteFloat(fps, 5, &max_digits_one);
	var c: f32 = 0.;
	c = c + (char(102));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

	c = c + (char(112));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

	c = c + (char(115));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	// let c2 = smoothStep(0.0, 1.0, c );

	vColor = mix(vColor, drawColorDebug, c);
} 

fn WriteMousePos(mPos: vec2<f32>, y_pos: f32)  {
	let digits: i32 = 3;
	let radius: f32 =  uni.iResolution.x / 400.;
	if (uni.iMouse.z > 0.) { dotColor_debug = mpColorDebug; }
	let r: f32 = length(abs(mPos.xy) - pixelPosDebug) - radius;
	// vColor = vColor + (mix(vec3<f32>(0.), dotColor_debug, 1. - clamp(r, 0., 1.)));

	var max_digits_three: i32 = 3;
	var mposxi: i32 = i32(mPos.x);
	var mposyi: i32 = i32(mPos.y);

	var mposx: f32 = (mPos.x);
	var mposy: f32 = (mPos.y);


	let x_pos = align_debug.y - 1. * FONT_SPACE_DEBUG;
		
	SetTextPositionAbs(
		 x_pos,
		 y_pos,
	);

	drawColorDebug = myColorDebug;
	WriteIntegerBack(&mposyi);

	SetTextPositionAbs(
		 x_pos - 7. *  FONT_SPACE_DEBUG,
		 y_pos,
	);

	drawColorDebug = mxColorDebug;

	WriteIntegerBack(&mposxi);

} 


fn sdRoundedBox(p: vec2<f32>, b: vec2<f32>, r: vec4<f32>) -> f32 {
  var x = r.x;
  var y = r.y;
  x = select(r.z, r.x, p.x > 0.);
  y = select(r.w, r.y, p.x > 0.);
  x  = select(y, x, p.y > 0.);
  let q = abs(p) - b + x;
  return min(max(q.x, q.y), 0.) + length(max(q, vec2<f32>(0.))) - x;
}



fn WriteRGBAValues(
	location: vec2<i32>, 
	value: vec4<f32>, 
	screen_poz: vec2<f32>,
	alpha: f32,
 )  {
	let poz = screen_poz / uni.iResolution * 20. * vec2<f32>(aspect_debug, 1.0);
	let window_ajusted = uni.iResolution / vec2<f32>(960., 600.);

	let box_pos = vec2<f32>(align_debug.w, align_debug.x - FONT_SPACE_DEBUG ) / 10.;
	// let box_pos = mp;

	// // box location follows mouse position
	// let box_location = vec2<f32>(
	// 	uni.iMouse.x + 100. * window_ajusted.x /  ( aspect_debug / 1.6 ) , 
	// 	uni.iMouse.y - 48. * window_ajusted.y
	// );


	let box_location  = vec2<f32>(
		100. * window_ajusted.x /  ( aspect_debug / 1.6 ) , 
		uni.iResolution.y - 60. * window_ajusted.y,
	);
	
	let inverted_screen_poz = vec2<f32>(screen_poz.x,  -screen_poz.y) ; // / vec2<f32>(aspect_debug, 1.) ;

	let d_box = sdRoundedBox(
		 vec2<f32>(location) - box_location - inverted_screen_poz, 
		 vec2<f32>(73. /  ( aspect_debug / 1.6 ), 75.) * window_ajusted, 
		vec4<f32>(5.,5.,5.,5.)  * 5.0 
	);

	// let alpha = 0.225;
	let decimal_places = 3;
	SetColor(1., 1., 1.);
	var c: f32 = 0.;
	let lspace = 0.8;

	let bg_color = vec3<f32>(.8, .7, .9);
	vColor = mix( vColor, bg_color,  (1.0 -  step(0.0, d_box)) * alpha ); 

	// red
	SetTextPosition(
		10. *  (box_pos.x +1. + lspace) + poz.x, 
		10. * (-box_pos.y +1.) - 0.0 + poz.y
	) ;
	c = c + (char(114)); // r
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	c = c + (char(58)); // colon
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	WriteFloatBox(value.r, 3, decimal_places, alpha );

	// green
	SetTextPosition(
		10. *  ((box_pos.x +1. + lspace)) + poz.x, 
		10. * (-box_pos.y +1. ) + 1.0 + poz.y,
	) ;
	c = c + (char(103)); // g
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	c = c + (char(58)); // colon
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	WriteFloatBox(value.g, 3, decimal_places, alpha );

	// blue
	SetTextPosition(
		10. *  (box_pos.x +1. + lspace) + poz.x, 
		10. * (-box_pos.y +1. ) + 2.0 + poz.y,
		) ;
	c = c + (char(98)); // b
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	c = c + (char(58)); // colon
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	WriteFloatBox(value.b, 4, decimal_places, alpha );

	// alpha
	SetTextPosition(
		10. *  (box_pos.x +1. + lspace) + poz.x, 
		10. * (-box_pos.y +1. ) + 3.0 + poz.y,
	) ;
	c = c + (char(97)); // a
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	c = c + (char(58)); // colon
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	WriteFloatBox(value.a, 4, decimal_places, alpha );

	vColor = mix(vColor, drawColorDebug, c * alpha);
}

fn sdSegment(p: vec2<f32>, a: vec2<f32>, b: vec2<f32>) -> f32 {
    let pa = p - a;
    let ba = b - a;
    let h = clamp(dot(pa, ba) / dot(ba, ba), 0., 1.);
    return length(pa - ba * h);
}

fn ring(pos: vec2<f32>, radius: f32, thick: f32) -> f32 {
	return mix(1., 0., smoothStep(thick, thick + 0.01, abs(length(uv_debug - pos) - radius)));
} 

fn sdCircle(p: vec2<f32>, c: vec2<f32>, r: f32) -> f32 {
    let d = length(p - c);
    return d - r;
}

fn draw_ring(location: vec2<i32>) {
	let mouse_click_poz = vec2<f32>(abs(uni.iMouse.z) , abs(uni.iMouse.w));

	let alpha = 0.75;
	let ring_dist = sdCircle(vec2<f32>(location) , mouse_click_poz, 2.3);
	let d = smoothStep(0.5, 1.5, abs(ring_dist - 1.));
	vColor = mix(vColor, headColorDebug,   (1. - d) * alpha );
}

fn draw_crossair(location: vec2<i32>)  {

	let start = 5.0;
	let end = 20.;
	let segment1 = sdSegment(
		vec2<f32>(location) - uni.iMouse.xy, 
		vec2<f32>(start, 0.), 
		vec2<f32>(end, 0.)
	);

	let segment2 = sdSegment(
		vec2<f32>(location) - uni.iMouse.xy, 
		vec2<f32>(-start, 0.), 
		vec2<f32>(-end, 0.)
	);

	let segment3 = sdSegment(
		vec2<f32>(location) - uni.iMouse.xy, 
		vec2<f32>(0., start), 
		vec2<f32>(0., end)
	);

	let segment4 = sdSegment(
		vec2<f32>(location) - uni.iMouse.xy, 
		vec2<f32>(0., -start), 
		vec2<f32>(0., -end)
	);

	var alpha = 0.75;
	if (uni.iMouse.z > 0.) {
		alpha = 1.0;
	}

	let d = smoothStep(0.5, 1.5, segment1);
	vColor = mix(vColor, headColorDebug, (1.0 -  d) * alpha );

	let d = smoothStep(0.5, 1.5, segment2);
	vColor = mix(vColor, headColorDebug, (1.0 -  d) * alpha );

	let d = smoothStep(0.5, 1.5, segment3);
	vColor = mix(vColor, headColorDebug, (1.0 -  d) * alpha );

	let d = smoothStep(0.5, 1.5, segment4);
	vColor = mix(vColor, headColorDebug, (1.0 -  d) * alpha );
}

fn show_debug_info(location: vec2<i32>, color: vec3<f32>) -> vec4<f32> {    
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );
    vColor = color;


	aspect_debug =  uni.iResolution.x /  uni.iResolution.y;

	let ratio: vec2<f32> = vec2<f32>(aspect_debug, 1.);
	pixelPosDebug = fragCoord.xy;
	// mousePosDebug = uni.iMouse.xy;
	uv_debug = (2. * fragCoord.xy /  uni.iResolution.xy - 1.) * ratio;

	align_debug = 10. * vec4<f32>(
		1.,      // North
		aspect_debug,  // East
		-1.,     // South
		-aspect_debug, // West
	);


	WriteMousePos(uni.iMouse.zw, align_debug.z + 2.0 * FONT_SPACE_DEBUG); // Click position
	WriteMousePos(uni.iMouse.xy, align_debug.z + 0.2 * FONT_SPACE_DEBUG); // Current mouse position

	var c: f32 = 0.;

	SetTextPositionAbs(
		 align_debug.y -      FONT_SPACE_DEBUG,
		 align_debug.x - 2. * FONT_SPACE_DEBUG,
	);

	SetColor(0.8, 0.8, 0.8);
	var resx = i32(uni.iResolution.x);
	var resy = i32(uni.iResolution.y);


	WriteIntegerBack(&resx);
	c = c + (char(28));
	tp_debug.x = tp_debug.x + 0. * (FONT_SPACE_DEBUG);
	WriteIntegerBack(&resy);


	SetTextPositionAbs(
		 align_debug.w - 1. * FONT_SPACE_DEBUG,
		 align_debug.z - 0. * FONT_SPACE_DEBUG,
	);

	WriteFPS();
	SetColor(0.9, 0.7, 0.8);

	let fragColor = vec4<f32>(vColor, 1.);

	let poz = vec2<f32>(0., uni.iResolution.y / 2.);
	
	// // RGBA probe labels follow mouse
	// let poz = vec2<f32>(uni.iMouse.x , uni.iResolution.y - uni.iMouse.y);
	
	let inverted_y_mouse_location = vec2<i32>(vec2<f32>(uni.iMouse.x, uni.iResolution.y - uni.iMouse.y));
	let value: vec4<f32> = textureLoad(texture, inverted_y_mouse_location);
	WriteRGBAValues(location, value, poz, 0.85);

	let inverted_y_mouseclick_location = vec2<i32>(vec2<f32>(abs(uni.iMouse.z), uni.iResolution.y - abs(uni.iMouse.w)));
	let value2: vec4<f32> = textureLoad(texture, inverted_y_mouseclick_location);
	WriteRGBAValues(location, value2, vec2<f32>(0.), 0.65);

	draw_crossair(location);

	draw_ring(location);

	let fragColor = vec4<f32>(vColor, 1.);

	

	return fragColor;
} 




// displays a gray screen by setting the color in buffer_a.wglsl and loading buffer_a
// here

// TODO: 
//
// 1. ar<private> light: vec3<f32>; for global variables
//
// 2. p.xy = ...
// pattern -> 
//  var pxy = p.xy;
//  pxy = pxy * matrix;
//  p.x = pxy.x;
//  p.y = pxy.y ;

let pi = 3.1415926;
type v2 = vec2<f32>;

var<private> light: vec3<f32>;

fn ln(p2: vec3<f32>, a: vec3<f32>, b: vec3<f32>, R: f32) -> f32 {
	var r: f32 = dot(p2 - a, b - a) / dot(b - a, b - a);
	r = clamp(r, 0., 1.);
    var p = p2;
	p.x = p.x + (0.2 * sqrt(R) * smoothStep(1., 0., abs(r * 2. - 1.)) * cos(pi * (2. * uni.iTime)));
	return length(p - a - (b - a) * r) - R * (1.5 - 0.4 * r);

} 

fn ro(a: f32) -> mat2x2<f32> {
	let s: f32 = sin(a);
	let c: f32 = cos(a);
	return mat2x2<f32>(c, -s, s, c);

} 

fn map(p2: vec3<f32>) -> f32 {
    var p = p2;
	var l: f32 = length(p - light) - 0.01;
	l = min(l, abs(p.y + 0.4) - 0.01);
	l = min(l, abs(p.z - 0.4) - 0.01);
	l = min(l, abs(p.x - 0.7) - 0.01);
	p.y = p.y + (0.4);
	p.z = p.z + (0.1);
    var pzx = p.zx;
    pzx = pzx * ro(0.1 * uni.iTime);

	p.z = pzx.x;
    p.x = pzx.y;

	var rl: vec2<f32> = vec2<f32>(0.02, 0.25 + 0.01 * sin(pi * 4. * uni.iTime));
	for (var i: i32 = 1; i < 11; i = i + 1) {
		l = min(l, ln(p, vec3<f32>(0.), vec3<f32>(0., rl.y, 0.), rl.x));
		p.y = p.y - (rl.y);

        var pxy = p.xy;
        pxy = pxy * (ro(0.2 * sin(3.1 * uni.iTime + f32(i)) + sin(0.222 * uni.iTime) * (-0.1 * sin(0.4 * pi * uni.iTime) + sin(0.543 * uni.iTime) / max(f32(i), 2.))));
		p.x = pxy.x;
        p.y = pxy.y ;
		p.x = abs(p.x);

        var pxy = p.xy;
        pxy = pxy *(ro(0.6 + 0.4 * sin(uni.iTime) * sin(0.871 * uni.iTime) + 0.05 * f32(i) * sin(2. * uni.iTime)));
		p.x = pxy.x ; 
		p.y = pxy.y ;
		
        var pzx = p.zx;
        pzx = pzx * (ro(0.5 * pi + 0.2 * sin(0.5278 * uni.iTime) + 0.8 * f32(i) * (sin(0.1 * uni.iTime) * (sin(0.1 * pi * uni.iTime) + sin(0.333 * uni.iTime) + 0.2 * sin(1.292 * uni.iTime)))));
        p.z = pzx.x;  
		p.x = pzx.y; 
		
        rl = rl * (0.7 + 0.015 * f32(i) * (sin(uni.iTime) + 0.1 * sin(4. * pi * uni.iTime)));
		l = min(l, length(p) - 0.15 * sqrt(rl.x));
	
	}	return l;

} 

fn march(p2: vec3<f32>, d: vec3<f32>) -> vec3<f32> {
	let o: f32 = 1000.;
    var p = p2;
	for (var i: i32 = 0; i < 24; i = i + 1) {
		let l: f32 = map(p);
		p = p + (l * d);
		if (l < 0.001) {		break;
		}
	
	}	return p;

} 

fn norm(p: vec3<f32>) -> vec3<f32> {
	let e: vec2<f32> = vec2<f32>(0.001, 0.);
	return normalize(vec3<f32>(map(p + e.xyy) - map(p - e.xyy), map(p + e.yxy) - map(p - e.yxy), map(p + e.yyx) - map(p - e.yyx)));

} 



[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
	let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));

	light = vec3<f32>(0.2 * sin(uni.iTime), 0.5, -0.5);
	if (uni.iMouse.z > 0.) {	
        light = vec3<f32>(vec2<f32>(-0.5, 0.5) * 0. + 0.7 * (uni.iMouse.xy - 0.5 * R) / R.y, -0.3);
	}
	
    var U = (vec2<f32>(location) - 0.5 * R) / R.y;
    // U = vec2<f32>(U.x, -U.y);

	var p: vec3<f32> = vec3<f32>(0., 0., -1.);
	var d: vec3<f32> = normalize(vec3<f32>(U, 1.));
	p = march(p, d);
	let n: vec3<f32> = norm(p);
	var C = 0.6 + 0.4 * sin(1.1 * vec4<f32>(1., 2., 3., 4.) * dot(d, n));
	let D: vec3<f32> = light - p;
	d = normalize(D);
	let lp: vec3<f32> = march(p + d * 0.01, d);
	C = C * (2.5 * dot(d, n) * (0.3 + 0.7 * length(lp - p) / length(light - p)));
	C = atan(C) / pi * 2.;


	textureStore(texture, y_inverted_location, C);


} 



================================================
FILE: assets/shaders/debugger/buffer_a.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;

// Converts a color from sRGB gamma to linear light gamma
fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
    let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
    let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
    let lower = sRGB / vec4<f32>(12.92);

    return mix(higher, lower, cutoff);
}



[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let color = vec4<f32>(0.5);
    textureStore(buffer_a, location, color);
}

================================================
FILE: assets/shaders/debugger/buffer_b.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;

// Converts a color from sRGB gamma to linear light gamma
fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
    let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
    let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
    let lower = sRGB / vec4<f32>(12.92);

    return mix(higher, lower, cutoff);
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/debugger/buffer_c.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;

// Converts a color from sRGB gamma to linear light gamma
fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
    let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
    let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
    let lower = sRGB / vec4<f32>(12.92);

    return mix(higher, lower, cutoff);
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/debugger/buffer_d.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;

// Converts a color from sRGB gamma to linear light gamma
fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
    let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
    let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
    let lower = sRGB / vec4<f32>(12.92);

    return mix(higher, lower, cutoff);
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}


================================================
FILE: assets/shaders/debugger/image.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(5)]]
var texture: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(6)]]
// var font_texture: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(6)]]
var font_texture: texture_2d<f32>;

[[group(0), binding(7)]]
var font_texture_sampler: sampler;

// [[stage(compute), workgroup_size(8, 8, 1)]]
// fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
//     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
//     let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

//     let color = vec4<f32>(f32(0));
//     textureStore(texture, location, color);
// }

// Why are the characters so pixelated? 
// One possible reason is that we are in a compute shader and the textures are not
// filtered.

let backColorDebug: vec3<f32> = vec3<f32>(0.2, 0.2, 0.2);


var<private> uv_debug: vec2<f32> ;
var<private> tp_debug: vec2<f32> ;
var<private> align_debug: vec4<f32>; // north, east, south, west
var<private> font_size_debug: f32;
var<private> dotColor_debug: vec3<f32> = vec3<f32>(0.5, 0.5, 0.);
var<private> drawColorDebug: vec3<f32> = vec3<f32>(1., 1., 0.);
var<private> vColor: vec3<f32> = backColorDebug;
var<private> aspect_debug: f32 = 1.;
var<private> pixelPosDebug: vec2<f32> = vec2<f32>(0., 0.);

let FONT_SPACE_DEBUG: f32 = 0.5;
let headColorDebug: vec3<f32> = vec3<f32>(0.9, 0.6, 0.2);
let mpColorDebug: vec3<f32> = vec3<f32>(0.99, 0.99, 0.);
let mxColorDebug: vec3<f32> = vec3<f32>(1., 0., 0.);
let myColorDebug: vec3<f32> = vec3<f32>(0., 1., 0.);
let font_png_size_debug: vec2<f32> = vec2<f32>(1023.0, 1023.0);

fn char(ch: i32) -> f32 {

    let fr = fract(floor(vec2<f32>(f32(ch), 15.999 - f32(ch) / 16.)) / 16.);
	let q = clamp(tp_debug, vec2<f32>(0.), vec2<f32>(1.)) / 16. + fr ;
	let inverted_q = vec2<f32>(q.x, 1. - q.y);

	// // There is aliasing on the characters
	// let f = textureSampleGrad(font_texture,
    //                  font_texture_sampler,
    //                  inverted_q,
    //                   vec2<f32>(1.0, 0.0),
    //                  vec2<f32>(0.0, 1.0));

	// using textureLoad without sampler
    let q1 = vec2<i32>(font_png_size_debug  * q );
	let y_inverted_q1 = vec2<i32>(q1.x, i32(font_png_size_debug.y) - q1.y);

	var f: vec4<f32> = textureLoad(font_texture, y_inverted_q1 , 0);

	// smoothing out the aliasing
	let dx = vec2<i32>(1, 0);
	let dy = vec2<i32>(0, 1);

	let fx1: vec4<f32> = textureLoad(font_texture, y_inverted_q1 + dx, 0);
	let fx2: vec4<f32> = textureLoad(font_texture, y_inverted_q1 - dx, 0);
	let fy1: vec4<f32> = textureLoad(font_texture, y_inverted_q1 + dy, 0);
	let fy2: vec4<f32> = textureLoad(font_texture, y_inverted_q1 - dy, 0);

	let rp = 0.25;
	f = f * rp + (1.0 - rp) * (fx1 + fx2 + fy1 + fy2) / 4.0 ;

	return f.x * (f.y + 0.3) * (f.z + 0.3) * 2.;
} 

fn SetTextPosition(x: f32, y: f32)  {
	tp_debug =  10. * uv_debug;
	tp_debug.x = tp_debug.x + 17. - x;
	tp_debug.y = tp_debug.y - 9.4 + y;
} 

fn SetTextPositionAbs(x: f32, y: f32)  {
	tp_debug.x = 10. * uv_debug.x - x;
	tp_debug.y = 10. * uv_debug.y - y;
} 

fn drawFract(value: ptr<function, f32>, digits:  ptr<function, i32>) -> f32 {
	var c: f32 = 0.;
	*value = fract(*value) * 10.;

	for (var ni: i32 = 1; ni < 60; ni = ni + 1) {
		c = c + (char(48 + i32(*value)));
		tp_debug.x = tp_debug.x - (0.5);
		*digits = *digits - (1);
		*value = fract(*value) * 10.;

		if (*digits <= 0 || *value == 0.) {		
            break;
        }
	}

	tp_debug.x = tp_debug.x - (0.5 * f32(*digits));
	return c;
} 

fn maxInt(a: i32, b: i32) -> i32 {
    var ret: i32;
    if (a > b) { ret = a; } else { ret = b; };
	return ret;
} 

fn drawInt(value: ptr<function, i32>,  minDigits: ptr<function, i32>) -> f32 {
	var c: f32 = 0.;
	if (*value < 0) {
		*value = -*value;
		if (*minDigits < 1) {		
			*minDigits = 1;
		} else { 
			*minDigits = *minDigits - 1;
		}
		c = c + (char(45));
		tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

	}
	var fn2: i32 = *value;
	var digits: i32 = 1;

	for (var ni: i32 = 0; ni < 10; ni = ni + 1) {
		fn2 = fn2 / (10);
		if (fn2 == 0) {		break; }
		digits = digits + 1;
	}

	digits = maxInt(*minDigits, digits);
	tp_debug.x = tp_debug.x - (0.5 * f32(digits));

	for (var ni: i32 = 1; ni < 11; ni = ni + 1) {
		tp_debug.x = tp_debug.x + (0.5);
		c = c + (char(48 + *value % 10));
		*value = *value / (10);
		if (ni >= digits) {		break; }
	}

	tp_debug.x = tp_debug.x - (0.5 * f32(digits));
	return c;
} 

fn drawIntBackwards(value: ptr<function, i32>,  minDigits: ptr<function, i32>) -> f32 {
	var c: f32 = 0.;
	let original_value: i32 = *value;

	if (*value < 0) {
		*value = -*value;
		if (*minDigits < 1) {		
			*minDigits = 1;
		} else { 
			*minDigits = *minDigits - 1;
		}
		// tp_debug.x = tp_debug.x + (FONT_SPACE_DEBUG);
		// c = c + (char(45));
		

	}
	var fn2: i32 = *value;
	var digits: i32 = 1;

	for (var ni: i32 = 0; ni < 10; ni = ni + 1) {
		fn2 = fn2 / (10);
		if (fn2 == 0) {		break; }
		digits = digits + 1;
	}

	digits = maxInt(*minDigits, digits);
	// tp_debug.x = tp_debug.x - (0.5 * f32(digits));

	for (var ni: i32 = digits - 1; ni < 11; ni = ni - 1) {
		tp_debug.x = tp_debug.x + (0.5);
		c = c + (char(48 + *value % 10));
		*value = *value / (10);
		if (ni == 0) {		break; }
	}

	if (original_value < 0) {
		tp_debug.x = tp_debug.x + (FONT_SPACE_DEBUG);
		c = c + (char(45));
	}

	// tp_debug.x = tp_debug.x + (0.5 * f32(digits));
	return c;
} 

// fn drawFloat(value: ptr<function, f32>, prec: ptr<function, i32>, maxDigits: i32) -> f32 {
fn drawFloat(val: f32, prec: ptr<function, i32>, maxDigits: i32) -> f32 {
	// in case of 0.099999..., round up to 0.1000000
	var value = round(val * pow(10., f32(maxDigits))) / pow(10., f32(maxDigits));

	let tp_debugx: f32 = tp_debug.x - 0.5 * f32(maxDigits);
	var c: f32 = 0.;
	if (value < 0.) {
		c = char(45);
		value = -value;
	}
	tp_debug.x = tp_debug.x - (0.5);
    var ival = i32(value);

    var one: i32 = 1;

	c = c + (drawInt(&ival, &one));
	c = c + (char(46));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

    var frac_val = fract(value);
	c = c + (drawFract(&frac_val, prec));
	tp_debug.x = min(tp_debug.x, tp_debugx);

	return c;
}

fn drawFloat_f32(value:  f32) -> f32 {
    var two: i32 = 2;
	return drawFloat(value, &two, 5);
} 

fn drawFloat_f32_prec(value: f32, prec: ptr<function, i32>) -> f32 {
	return drawFloat(value, prec, 2);
} 

fn drawInt_i32_back(value: ptr<function, i32>) -> f32 {
    var one: i32 = 1;
	return drawIntBackwards(value, &one);
} 

fn drawInt_i32(value: ptr<function, i32>) -> f32 {
    var one: i32 = 1;
	return drawInt(value, &one);
} 





fn SetColor(red: f32, green: f32, blue: f32)  {
	drawColorDebug = vec3<f32>(red, green, blue);
} 

fn WriteFloat(fValue: f32, maxDigits: i32, decimalPlaces: ptr<function, i32>)  {

	// vColor = mix(vColor, drawColorDebug, drawFloat_f32_prec(fValue, decimalPlaces));
	vColor = mix(vColor, drawColorDebug, drawFloat(fValue, decimalPlaces, maxDigits));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
;
} 

fn WriteFloatBox(
	fValue: f32, 
	maxDigits: i32, 
	decimalPlaces: i32, 
	alpha: f32
)  {
	var decs = decimalPlaces;
	vColor = mix(vColor, drawColorDebug, drawFloat(fValue, &decs, maxDigits) * alpha);
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
;
} 

fn WriteInteger(iValue: ptr<function, i32>)  {
	vColor = mix(vColor, drawColorDebug, drawInt_i32(iValue));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

} 

fn WriteIntegerBack(iValue: ptr<function, i32>)  {
	vColor = mix(vColor, drawColorDebug, drawInt_i32_back(iValue));
	tp_debug.x = tp_debug.x + (FONT_SPACE_DEBUG);

} 



fn WriteFPS()  {
	var fps: f32 = f32(uni.iSampleRate);
	SetColor(0.8, 0.6, 0.3);
	var max_digits_one = 1;
	WriteFloat(fps, 5, &max_digits_one);
	var c: f32 = 0.;
	c = c + (char(102));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

	c = c + (char(112));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);

	c = c + (char(115));
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	// let c2 = smoothStep(0.0, 1.0, c );

	vColor = mix(vColor, drawColorDebug, c);
} 

fn WriteMousePos(mPos: vec2<f32>, y_pos: f32)  {
	let digits: i32 = 3;
	let radius: f32 =  uni.iResolution.x / 400.;
	if (uni.iMouse.z > 0.) { dotColor_debug = mpColorDebug; }
	let r: f32 = length(abs(mPos.xy) - pixelPosDebug) - radius;
	// vColor = vColor + (mix(vec3<f32>(0.), dotColor_debug, 1. - clamp(r, 0., 1.)));

	var max_digits_three: i32 = 3;
	var mposxi: i32 = i32(mPos.x);
	var mposyi: i32 = i32(mPos.y);

	var mposx: f32 = (mPos.x);
	var mposy: f32 = (mPos.y);


	let x_pos = align_debug.y - 1. * FONT_SPACE_DEBUG;
		
	SetTextPositionAbs(
		 x_pos,
		 y_pos,
	);

	drawColorDebug = myColorDebug;
	WriteIntegerBack(&mposyi);

	SetTextPositionAbs(
		 x_pos - 7. *  FONT_SPACE_DEBUG,
		 y_pos,
	);

	drawColorDebug = mxColorDebug;

	WriteIntegerBack(&mposxi);

} 


fn sdRoundedBox(p: vec2<f32>, b: vec2<f32>, r: vec4<f32>) -> f32 {
  var x = r.x;
  var y = r.y;
  x = select(r.z, r.x, p.x > 0.);
  y = select(r.w, r.y, p.x > 0.);
  x  = select(y, x, p.y > 0.);
  let q = abs(p) - b + x;
  return min(max(q.x, q.y), 0.) + length(max(q, vec2<f32>(0.))) - x;
}



fn WriteRGBAValues(
	location: vec2<i32>, 
	value: vec4<f32>, 
	screen_poz: vec2<f32>,
	alpha: f32,
 )  {
	let poz = screen_poz / uni.iResolution * 20. * vec2<f32>(aspect_debug, 1.0);
	let window_ajusted = uni.iResolution / vec2<f32>(960., 600.);

	let box_pos = vec2<f32>(align_debug.w, align_debug.x - FONT_SPACE_DEBUG ) / 10.;
	// let box_pos = mp;

	// // box location follows mouse position
	// let box_location = vec2<f32>(
	// 	uni.iMouse.x + 100. * window_ajusted.x /  ( aspect_debug / 1.6 ) , 
	// 	uni.iMouse.y - 48. * window_ajusted.y
	// );


	let box_location  = vec2<f32>(
		100. * window_ajusted.x /  ( aspect_debug / 1.6 ) , 
		uni.iResolution.y - 60. * window_ajusted.y,
	);
	
	let inverted_screen_poz = vec2<f32>(screen_poz.x,  -screen_poz.y) ; // / vec2<f32>(aspect_debug, 1.) ;

	let d_box = sdRoundedBox(
		 vec2<f32>(location) - box_location - inverted_screen_poz, 
		 vec2<f32>(73. /  ( aspect_debug / 1.6 ), 75.) * window_ajusted, 
		vec4<f32>(5.,5.,5.,5.)  * 5.0 
	);

	// let alpha = 0.225;
	let decimal_places = 3;
	SetColor(1., 1., 1.);
	var c: f32 = 0.;
	let lspace = 0.8;

	let bg_color = vec3<f32>(.8, .7, .9);
	vColor = mix( vColor, bg_color,  (1.0 -  step(0.0, d_box)) * alpha ); 

	// red
	SetTextPosition(
		10. *  (box_pos.x +1. + lspace) + poz.x, 
		10. * (-box_pos.y +1.) - 0.0 + poz.y
	) ;
	c = c + (char(114)); // r
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	c = c + (char(58)); // colon
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	WriteFloatBox(value.r, 3, decimal_places, alpha );

	// green
	SetTextPosition(
		10. *  ((box_pos.x +1. + lspace)) + poz.x, 
		10. * (-box_pos.y +1. ) + 1.0 + poz.y,
	) ;
	c = c + (char(103)); // g
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	c = c + (char(58)); // colon
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	WriteFloatBox(value.g, 3, decimal_places, alpha );

	// blue
	SetTextPosition(
		10. *  (box_pos.x +1. + lspace) + poz.x, 
		10. * (-box_pos.y +1. ) + 2.0 + poz.y,
		) ;
	c = c + (char(98)); // b
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	c = c + (char(58)); // colon
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	WriteFloatBox(value.b, 4, decimal_places, alpha );

	// alpha
	SetTextPosition(
		10. *  (box_pos.x +1. + lspace) + poz.x, 
		10. * (-box_pos.y +1. ) + 3.0 + poz.y,
	) ;
	c = c + (char(97)); // a
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	c = c + (char(58)); // colon
	tp_debug.x = tp_debug.x - (FONT_SPACE_DEBUG);
	WriteFloatBox(value.a, 4, decimal_places, alpha );

	vColor = mix(vColor, drawColorDebug, c * alpha);
}

fn sdSegment(p: vec2<f32>, a: vec2<f32>, b: vec2<f32>) -> f32 {
    let pa = p - a;
    let ba = b - a;
    let h = clamp(dot(pa, ba) / dot(ba, ba), 0., 1.);
    return length(pa - ba * h);
}

fn ring(pos: vec2<f32>, radius: f32, thick: f32) -> f32 {
	return mix(1., 0., smoothStep(thick, thick + 0.01, abs(length(uv_debug - pos) - radius)));
} 

fn sdCircle(p: vec2<f32>, c: vec2<f32>, r: f32) -> f32 {
    let d = length(p - c);
    return d - r;
}

fn draw_ring(location: vec2<i32>) {
	let mouse_click_poz = vec2<f32>(abs(uni.iMouse.z) , abs(uni.iMouse.w));

	let alpha = 0.75;
	let ring_dist = sdCircle(vec2<f32>(location) , mouse_click_poz, 2.3);
	let d = smoothStep(0.5, 1.5, abs(ring_dist - 1.));
	vColor = mix(vColor, headColorDebug,   (1. - d) * alpha );
}

fn draw_crossair(location: vec2<i32>)  {

	let start = 5.0;
	let end = 20.;
	let segment1 = sdSegment(
		vec2<f32>(location) - uni.iMouse.xy, 
		vec2<f32>(start, 0.), 
		vec2<f32>(end, 0.)
	);

	let segment2 = sdSegment(
		vec2<f32>(location) - uni.iMouse.xy, 
		vec2<f32>(-start, 0.), 
		vec2<f32>(-end, 0.)
	);

	let segment3 = sdSegment(
		vec2<f32>(location) - uni.iMouse.xy, 
		vec2<f32>(0., start), 
		vec2<f32>(0., end)
	);

	let segment4 = sdSegment(
		vec2<f32>(location) - uni.iMouse.xy, 
		vec2<f32>(0., -start), 
		vec2<f32>(0., -end)
	);

	var alpha = 0.75;
	if (uni.iMouse.z > 0.) {
		alpha = 1.0;
	}

	let d = smoothStep(0.5, 1.5, segment1);
	vColor = mix(vColor, headColorDebug, (1.0 -  d) * alpha );

	let d = smoothStep(0.5, 1.5, segment2);
	vColor = mix(vColor, headColorDebug, (1.0 -  d) * alpha );

	let d = smoothStep(0.5, 1.5, segment3);
	vColor = mix(vColor, headColorDebug, (1.0 -  d) * alpha );

	let d = smoothStep(0.5, 1.5, segment4);
	vColor = mix(vColor, headColorDebug, (1.0 -  d) * alpha );
}

fn show_debug_info(location: vec2<i32>, color: vec3<f32>) -> vec4<f32> {    
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );
    vColor = color;


	aspect_debug =  uni.iResolution.x /  uni.iResolution.y;

	let ratio: vec2<f32> = vec2<f32>(aspect_debug, 1.);
	pixelPosDebug = fragCoord.xy;
	// mousePosDebug = uni.iMouse.xy;
	uv_debug = (2. * fragCoord.xy /  uni.iResolution.xy - 1.) * ratio;

	align_debug = 10. * vec4<f32>(
		1.,      // North
		aspect_debug,  // East
		-1.,     // South
		-aspect_debug, // West
	);


	WriteMousePos(uni.iMouse.zw, align_debug.z + 2.0 * FONT_SPACE_DEBUG); // Click position
	WriteMousePos(uni.iMouse.xy, align_debug.z + 0.2 * FONT_SPACE_DEBUG); // Current mouse position

	var c: f32 = 0.;

	SetTextPositionAbs(
		 align_debug.y -      FONT_SPACE_DEBUG,
		 align_debug.x - 2. * FONT_SPACE_DEBUG,
	);

	SetColor(0.8, 0.8, 0.8);
	var resx = i32(uni.iResolution.x);
	var resy = i32(uni.iResolution.y);


	WriteIntegerBack(&resx);
	c = c + (char(28));
	tp_debug.x = tp_debug.x + 0. * (FONT_SPACE_DEBUG);
	WriteIntegerBack(&resy);


	SetTextPositionAbs(
		 align_debug.w - 1. * FONT_SPACE_DEBUG,
		 align_debug.z - 0. * FONT_SPACE_DEBUG,
	);

	WriteFPS();
	SetColor(0.9, 0.7, 0.8);

	let fragColor = vec4<f32>(vColor, 1.);

	let poz = vec2<f32>(0., uni.iResolution.y / 2.);
	
	// // RGBA probe labels follow mouse
	// let poz = vec2<f32>(uni.iMouse.x , uni.iResolution.y - uni.iMouse.y);
	
	let inverted_y_mouse_location = vec2<i32>(vec2<f32>(uni.iMouse.x, uni.iResolution.y - uni.iMouse.y));
	let value: vec4<f32> = textureLoad(texture, inverted_y_mouse_location);
	WriteRGBAValues(location, value, poz, 0.5);

	let inverted_y_mouseclick_location = vec2<i32>(vec2<f32>(abs(uni.iMouse.z), uni.iResolution.y - abs(uni.iMouse.w)));
	let value2: vec4<f32> = textureLoad(texture, inverted_y_mouseclick_location);
	WriteRGBAValues(location, value2, vec2<f32>(0.), 0.25);

	draw_crossair(location);

	draw_ring(location);

	let fragColor = vec4<f32>(vColor, 1.);

	return fragColor;
} 


// Converts a color from sRGB gamma to linear light gamma
fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
    let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
    let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
    let lower = sRGB / vec4<f32>(12.92);

    return mix(higher, lower, cutoff);
}

// Why are the characters so pixelated? 
// One possible reason is that we are in a compute shader and the textures are not
// filtered.

// type ivec2 = vec2<i32>;
// type v2 = vec2<f32>;

// let backColor: vec3<f32> = vec3<f32>(0.2, 0.2, 0.2);

// var<private> R: vec2<f32>;
// var<private> uv: vec2<f32> ;
// var<private> tp: vec2<f32> ;
// var<private> alignment: vec4<f32>; // north, east, south, west
// var<private> font_size: f32;
// var<private> dotColor: vec3<f32> = vec3<f32>(0.5, 0.5, 0.);
// var<private> drawColor: vec3<f32> = vec3<f32>(1., 1., 0.);
// var<private> vColor: vec3<f32> = backColor;
// var<private> aspect: f32 = 1.;
// var<private> pixelPos: vec2<f32> = vec2<f32>(0., 0.);
// var<private> mousePos: vec2<f32> = vec2<f32>(200., 200.);
// var<private> lp: vec2<f32> = vec2<f32>(0.5, 0.5);
// var<private> mp: vec2<f32> = vec2<f32>(0.5, 0.5);
// var<private> resolution: vec2<f32>;


// let FONT_SPACE: f32 = 0.5;
// let headColor: vec3<f32> = vec3<f32>(0.9, 0.6, 0.2);
// let mpColor: vec3<f32> = vec3<f32>(0.99, 0.99, 0.);
// let mxColor: vec3<f32> = vec3<f32>(1., 0., 0.);
// let myColor: vec3<f32> = vec3<f32>(0., 1., 0.);
// let font_png_size: vec2<f32> = vec2<f32>(1023.0, 1023.0);


// fn char(ch: i32) -> f32 {

//     let fr = fract(floor(vec2<f32>(f32(ch), 15.999 - f32(ch) / 16.)) / 16.);
// 	let q = clamp(tp, v2(0.), v2(1.)) / 16. + fr ;
// 	let inverted_q = v2(q.x, 1. - q.y);

// 	// // There is aliasing on the characters
// 	// let f = textureSampleGrad(font_texture,
//     //                  font_texture_sampler,
//     //                  inverted_q,
//     //                   vec2<f32>(1.0, 0.0),
//     //                  vec2<f32>(0.0, 1.0));

// 	// using textureLoad without sampler
//     let q1 = ivec2(font_png_size  * q );
// 	let y_inverted_q1 = ivec2(q1.x, i32(font_png_size.y) - q1.y);

// 	var f: vec4<f32> = textureLoad(font_texture, y_inverted_q1 , 0);

// 	// smoothing out the aliasing
// 	let dx = vec2<i32>(1, 0);
// 	let dy = vec2<i32>(0, 1);

// 	let fx1: vec4<f32> = textureLoad(font_texture, y_inverted_q1 + dx, 0);
// 	let fx2: vec4<f32> = textureLoad(font_texture, y_inverted_q1 - dx, 0);
// 	let fy1: vec4<f32> = textureLoad(font_texture, y_inverted_q1 + dy, 0);
// 	let fy2: vec4<f32> = textureLoad(font_texture, y_inverted_q1 - dy, 0);

// 	let rp = 0.25;
// 	f = f * rp + (1.0 - rp) * (fx1 + fx2 + fy1 + fy2) / 4.0 ;

// 	return f.x * (f.y + 0.3) * (f.z + 0.3) * 2.;
// } 

// fn SetTextPosition(x: f32, y: f32)  {
// 	tp =  10. * uv;
// 	tp.x = tp.x + 17. - x;
// 	tp.y = tp.y - 9.4 + y;
// } 

// fn SetTextPositionAbs(x: f32, y: f32)  {
// 	tp.x = 10. * uv.x - x;
// 	tp.y = 10. * uv.y - y;
// } 

// fn drawFract(value: ptr<function, f32>, digits:  ptr<function, i32>) -> f32 {
// 	var c: f32 = 0.;
// 	*value = fract(*value) * 10.;

// 	for (var ni: i32 = 1; ni < 60; ni = ni + 1) {
// 		c = c + (char(48 + i32(*value)));
// 		tp.x = tp.x - (0.5);
// 		*digits = *digits - (1);
// 		*value = fract(*value) * 10.;

// 		if (*digits <= 0 || *value == 0.) {		
//             break;
//         }
// 	}

// 	tp.x = tp.x - (0.5 * f32(*digits));
// 	return c;
// } 

// fn maxInt(a: i32, b: i32) -> i32 {
//     var ret: i32;
//     if (a > b) { ret = a; } else { ret = b; };
// 	return ret;
// } 

// fn drawInt(value: ptr<function, i32>,  minDigits: ptr<function, i32>) -> f32 {
// 	var c: f32 = 0.;
// 	if (*value < 0) {
// 		*value = -*value;
// 		if (*minDigits < 1) {		
// 			*minDigits = 1;
// 		} else { 
// 			*minDigits = *minDigits - 1;
// 		}
// 		c = c + (char(45));
// 		tp.x = tp.x - (FONT_SPACE);

// 	}
// 	var fn2: i32 = *value;
// 	var digits: i32 = 1;

// 	for (var ni: i32 = 0; ni < 10; ni = ni + 1) {
// 		fn2 = fn2 / (10);
// 		if (fn2 == 0) {		break; }
// 		digits = digits + 1;
// 	}

// 	digits = maxInt(*minDigits, digits);
// 	tp.x = tp.x - (0.5 * f32(digits));

// 	for (var ni: i32 = 1; ni < 11; ni = ni + 1) {
// 		tp.x = tp.x + (0.5);
// 		c = c + (char(48 + *value % 10));
// 		*value = *value / (10);
// 		if (ni >= digits) {		break; }
// 	}

// 	tp.x = tp.x - (0.5 * f32(digits));
// 	return c;
// } 

// fn drawIntBackwards(value: ptr<function, i32>,  minDigits: ptr<function, i32>) -> f32 {
// 	var c: f32 = 0.;
// 	let original_value: i32 = *value;

// 	if (*value < 0) {
// 		*value = -*value;
// 		if (*minDigits < 1) {		
// 			*minDigits = 1;
// 		} else { 
// 			*minDigits = *minDigits - 1;
// 		}
// 		// tp.x = tp.x + (FONT_SPACE);
// 		// c = c + (char(45));
		

// 	}
// 	var fn2: i32 = *value;
// 	var digits: i32 = 1;

// 	for (var ni: i32 = 0; ni < 10; ni = ni + 1) {
// 		fn2 = fn2 / (10);
// 		if (fn2 == 0) {		break; }
// 		digits = digits + 1;
// 	}

// 	digits = maxInt(*minDigits, digits);
// 	// tp.x = tp.x - (0.5 * f32(digits));

// 	for (var ni: i32 = digits - 1; ni < 11; ni = ni - 1) {
// 		tp.x = tp.x + (0.5);
// 		c = c + (char(48 + *value % 10));
// 		*value = *value / (10);
// 		if (ni == 0) {		break; }
// 	}

// 	if (original_value < 0) {
// 		tp.x = tp.x + (FONT_SPACE);
// 		c = c + (char(45));
// 	}

// 	// tp.x = tp.x + (0.5 * f32(digits));
// 	return c;
// } 

// // fn drawFloat(value: ptr<function, f32>, prec: ptr<function, i32>, maxDigits: i32) -> f32 {
// fn drawFloat(val: f32, prec: ptr<function, i32>, maxDigits: i32) -> f32 {
// 	// in case of 0.099999..., round up to 0.1000000
// 	var value = round(val * pow(10., f32(maxDigits))) / pow(10., f32(maxDigits));

// 	let tpx: f32 = tp.x - 0.5 * f32(maxDigits);
// 	var c: f32 = 0.;
// 	if (value < 0.) {
// 		c = char(45);
// 		value = -value;
// 	}
// 	tp.x = tp.x - (0.5);
//     var ival = i32(value);

//     var one: i32 = 1;

// 	c = c + (drawInt(&ival, &one));
// 	c = c + (char(46));
// 	tp.x = tp.x - (FONT_SPACE);

//     var frac_val = fract(value);
// 	c = c + (drawFract(&frac_val, prec));
// 	tp.x = min(tp.x, tpx);

// 	return c;
// }

// fn drawFloat_f32(value:  f32) -> f32 {
//     var two: i32 = 2;
// 	return drawFloat(value, &two, 5);
// } 

// fn drawFloat_f32_prec(value: f32, prec: ptr<function, i32>) -> f32 {
// 	return drawFloat(value, prec, 2);
// } 

// fn drawInt_i32_back(value: ptr<function, i32>) -> f32 {
//     var one: i32 = 1;
// 	return drawIntBackwards(value, &one);
// } 

// fn drawInt_i32(value: ptr<function, i32>) -> f32 {
//     var one: i32 = 1;
// 	return drawInt(value, &one);
// } 





// fn SetColor(red: f32, green: f32, blue: f32)  {
// 	drawColor = vec3<f32>(red, green, blue);
// } 

// fn WriteFloat(fValue: f32, maxDigits: i32, decimalPlaces: ptr<function, i32>)  {

// 	// vColor = mix(vColor, drawColor, drawFloat_f32_prec(fValue, decimalPlaces));
// 	vColor = mix(vColor, drawColor, drawFloat(fValue, decimalPlaces, maxDigits));
// 	tp.x = tp.x - (FONT_SPACE);
// ;
// } 

// fn WriteFloatBox(
// 	fValue: f32, 
// 	maxDigits: i32, 
// 	decimalPlaces: i32, 
// 	alpha: f32
// )  {
// 	var decs = decimalPlaces;
// 	vColor = mix(vColor, drawColor, drawFloat(fValue, &decs, maxDigits) * alpha);
// 	tp.x = tp.x - (FONT_SPACE);
// ;
// } 

// fn WriteInteger(iValue: ptr<function, i32>)  {
// 	vColor = mix(vColor, drawColor, drawInt_i32(iValue));
// 	tp.x = tp.x - (FONT_SPACE);

// } 

// fn WriteIntegerBack(iValue: ptr<function, i32>)  {
// 	vColor = mix(vColor, drawColor, drawInt_i32_back(iValue));
// 	tp.x = tp.x + (FONT_SPACE);

// } 



// fn WriteFPS()  {
// 	var fps: f32 = f32(uni.iSampleRate);
// 	SetColor(0.8, 0.6, 0.3);
// 	var max_digits_one = 1;
// 	WriteFloat(fps, 5, &max_digits_one);
// 	var c: f32 = 0.;
// 	c = c + (char(102));
// 	tp.x = tp.x - (FONT_SPACE);

// 	c = c + (char(112));
// 	tp.x = tp.x - (FONT_SPACE);

// 	c = c + (char(115));
// 	tp.x = tp.x - (FONT_SPACE);
// 	// let c2 = smoothStep(0.0, 1.0, c );

// 	vColor = mix(vColor, drawColor, c);
// } 

// fn WriteMousePos(mPos: vec2<f32>, y_pos: f32)  {
// 	let digits: i32 = 3;
// 	let radius: f32 = resolution.x / 400.;
// 	if (uni.iMouse.z > 0.) { dotColor = mpColor; }
// 	let r: f32 = length(abs(mPos.xy) - pixelPos) - radius;
// 	// vColor = vColor + (mix(vec3<f32>(0.), dotColor, 1. - clamp(r, 0., 1.)));

// 	var max_digits_three: i32 = 3;
// 	var mposxi: i32 = i32(mPos.x);
// 	var mposyi: i32 = i32(mPos.y);

// 	var mposx: f32 = (mPos.x);
// 	var mposy: f32 = (mPos.y);


// 	let x_pos = alignment.y - 1. * FONT_SPACE;
		
// 	SetTextPositionAbs(
// 		 x_pos,
// 		 y_pos,
// 	);

// 	drawColor = myColor;
// 	WriteIntegerBack(&mposyi);

// 	SetTextPositionAbs(
// 		 x_pos - 7. *  FONT_SPACE,
// 		 y_pos,
// 	);

// 	drawColor = mxColor;

// 	WriteIntegerBack(&mposxi);

// } 


// fn sdRoundedBox(p: vec2<f32>, b: vec2<f32>, r: vec4<f32>) -> f32 {
//   var x = r.x;
//   var y = r.y;
//   x = select(r.z, r.x, p.x > 0.);
//   y = select(r.w, r.y, p.x > 0.);
//   x  = select(y, x, p.y > 0.);
//   let q = abs(p) - b + x;
//   return min(max(q.x, q.y), 0.) + length(max(q, vec2<f32>(0.))) - x;
// }



// fn WriteRGBAValues(
// 	location: vec2<i32>, 
// 	value: vec4<f32>, 
// 	screen_poz: vec2<f32>,
// 	alpha: f32,
//  )  {
// 	let poz = screen_poz / uni.iResolution * 20. * vec2<f32>(aspect, 1.0);
// 	let window_ajusted = uni.iResolution / v2(960., 600.);

// 	let box_pos = vec2<f32>(alignment.w, alignment.x - FONT_SPACE ) / 10.;
// 	// let box_pos = mp;

// 	// // box location follows mouse position
// 	// let box_location = v2(
// 	// 	uni.iMouse.x + 100. * window_ajusted.x /  ( aspect / 1.6 ) , 
// 	// 	uni.iMouse.y - 48. * window_ajusted.y
// 	// );


// 	let box_location  = v2(
// 		100. * window_ajusted.x /  ( aspect / 1.6 ) , 
// 		uni.iResolution.y - 60. * window_ajusted.y,
// 	);
	
// 	let inverted_screen_poz = vec2<f32>(screen_poz.x,  -screen_poz.y) ; // / vec2<f32>(aspect, 1.) ;

// 	let d_box = sdRoundedBox(
// 		 vec2<f32>(location) - box_location - inverted_screen_poz, 
// 		 vec2<f32>(73. /  ( aspect / 1.6 ), 75.) * window_ajusted, 
// 		vec4<f32>(5.,5.,5.,5.)  * 5.0 
// 	);

// 	// let alpha = 0.225;
// 	let decimal_places = 3;
// 	SetColor(1., 1., 1.);
// 	var c: f32 = 0.;
// 	let lspace = 0.8;

// 	let bg_color = vec3<f32>(.8, .7, .9);
// 	vColor = mix( vColor, bg_color,  (1.0 -  step(0.0, d_box)) * alpha ); 

// 	// red
// 	SetTextPosition(
// 		10. *  (box_pos.x +1. + lspace) + poz.x, 
// 		10. * (-box_pos.y +1.) - 0.0 + poz.y
// 	) ;
// 	c = c + (char(114)); // r
// 	tp.x = tp.x - (FONT_SPACE);
// 	c = c + (char(58)); // colon
// 	tp.x = tp.x - (FONT_SPACE);
// 	WriteFloatBox(value.r, 3, decimal_places, alpha );

// 	// green
// 	SetTextPosition(
// 		10. *  ((box_pos.x +1. + lspace)) + poz.x, 
// 		10. * (-box_pos.y +1. ) + 1.0 + poz.y,
// 	) ;
// 	c = c + (char(103)); // g
// 	tp.x = tp.x - (FONT_SPACE);
// 	c = c + (char(58)); // colon
// 	tp.x = tp.x - (FONT_SPACE);
// 	WriteFloatBox(value.g, 3, decimal_places, alpha );

// 	// blue
// 	SetTextPosition(
// 		10. *  (box_pos.x +1. + lspace) + poz.x, 
// 		10. * (-box_pos.y +1. ) + 2.0 + poz.y,
// 		) ;
// 	c = c + (char(98)); // b
// 	tp.x = tp.x - (FONT_SPACE);
// 	c = c + (char(58)); // colon
// 	tp.x = tp.x - (FONT_SPACE);
// 	WriteFloatBox(value.b, 4, decimal_places, alpha );

// 	// alpha
// 	SetTextPosition(
// 		10. *  (box_pos.x +1. + lspace) + poz.x, 
// 		10. * (-box_pos.y +1. ) + 3.0 + poz.y,
// 	) ;
// 	c = c + (char(97)); // a
// 	tp.x = tp.x - (FONT_SPACE);
// 	c = c + (char(58)); // colon
// 	tp.x = tp.x - (FONT_SPACE);
// 	WriteFloatBox(value.a, 4, decimal_places, alpha );

// 	vColor = mix(vColor, drawColor, c * alpha);
// }

// fn sdSegment(p: vec2<f32>, a: vec2<f32>, b: vec2<f32>) -> f32 {
//     let pa = p - a;
//     let ba = b - a;
//     let h = clamp(dot(pa, ba) / dot(ba, ba), 0., 1.);
//     return length(pa - ba * h);
// }

// fn ring(pos: vec2<f32>, radius: f32, thick: f32) -> f32 {
// 	return mix(1., 0., smoothStep(thick, thick + 0.01, abs(length(uv - pos) - radius)));
// } 

// fn sdCircle(p: vec2<f32>, c: vec2<f32>, r: f32) -> f32 {
//     let d = length(p - c);
//     return d - r;
// }

// fn draw_ring(location: vec2<i32>) {
// 	let mouse_click_poz = vec2<f32>(abs(uni.iMouse.z) , abs(uni.iMouse.w));

// 	let alpha = 0.75;
// 	let ring_dist = sdCircle(vec2<f32>(location) , mouse_click_poz, 2.3);
// 	let d = smoothStep(0.5, 1.5, abs(ring_dist - 1.));
// 	vColor = mix(vColor, headColor,   (1. - d) * alpha );
// }

// fn draw_crossair(location: vec2<i32>)  {

// 	let start = 5.0;
// 	let end = 20.;
// 	let segment1 = sdSegment(
// 		vec2<f32>(location) - uni.iMouse.xy, 
// 		vec2<f32>(start, 0.), 
// 		vec2<f32>(end, 0.)
// 	);

// 	let segment2 = sdSegment(
// 		vec2<f32>(location) - uni.iMouse.xy, 
// 		vec2<f32>(-start, 0.), 
// 		vec2<f32>(-end, 0.)
// 	);

// 	let segment3 = sdSegment(
// 		vec2<f32>(location) - uni.iMouse.xy, 
// 		vec2<f32>(0., start), 
// 		vec2<f32>(0., end)
// 	);

// 	let segment4 = sdSegment(
// 		vec2<f32>(location) - uni.iMouse.xy, 
// 		vec2<f32>(0., -start), 
// 		vec2<f32>(0., -end)
// 	);

// 	var alpha = 0.75;
// 	if (uni.iMouse.z > 0.) {
// 		alpha = 1.0;
// 	}

// 	let d = smoothStep(0.5, 1.5, segment1);
// 	vColor = mix(vColor, headColor, (1.0 -  d) * alpha );

// 	let d = smoothStep(0.5, 1.5, segment2);
// 	vColor = mix(vColor, headColor, (1.0 -  d) * alpha );

// 	let d = smoothStep(0.5, 1.5, segment3);
// 	vColor = mix(vColor, headColor, (1.0 -  d) * alpha );

// 	let d = smoothStep(0.5, 1.5, segment4);
// 	vColor = mix(vColor, headColor, (1.0 -  d) * alpha );
// }

// fn show_debug_info(location: vec2<i32>) -> vec4<f32> {    


// 	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

// 	resolution = uni.iResolution.xy;
// 	aspect = resolution.x / resolution.y;

// 	let ratio: vec2<f32> = vec2<f32>(aspect, 1.);
// 	pixelPos = fragCoord.xy;
// 	mousePos = uni.iMouse.xy;
// 	uv = (2. * fragCoord.xy / resolution.xy - 1.) * ratio;

// 	alignment = 10. * vec4<f32>(
// 		1.,      // North
// 		aspect,  // East
// 		-1.,     // South
// 		-aspect, // West
// 	);

// 	mp = (2. * abs(uni.iMouse.xy) / resolution.xy - 1.) * ratio; // Mouse position in uv coordinates

// 	WriteMousePos(uni.iMouse.zw, alignment.z + 2.0 * FONT_SPACE); // Click position
// 	WriteMousePos(uni.iMouse.xy, alignment.z + 0.2 * FONT_SPACE); // Current mouse position

// 	var c: f32 = 0.;

// 	SetTextPositionAbs(
// 		 alignment.y -      FONT_SPACE,
// 		 alignment.x - 2. * FONT_SPACE,
// 	);

// 	SetColor(0.8, 0.8, 0.8);
// 	var resx = i32(uni.iResolution.x);
// 	var resy = i32(uni.iResolution.y);


// 	WriteIntegerBack(&resx);
// 	c = c + (char(28));
// 	tp.x = tp.x + 0. * (FONT_SPACE);
// 	WriteIntegerBack(&resy);


// 	SetTextPositionAbs(
// 		 alignment.w - 1. * FONT_SPACE,
// 		 alignment.z - 0. * FONT_SPACE,
// 	);

// 	WriteFPS();
// 	SetColor(0.9, 0.7, 0.8);

// 	let fragColor = vec4<f32>(vColor, 1.);

// 	let poz = vec2<f32>(0., uni.iResolution.y / 2.);
	
// 	// // RGBA probe labels follow mouse
// 	// let poz = vec2<f32>(uni.iMouse.x , uni.iResolution.y - uni.iMouse.y);
	
// 	let inverted_y_mouse_location = vec2<i32>(v2(uni.iMouse.x, uni.iResolution.y - uni.iMouse.y));
// 	let value: vec4<f32> = textureLoad(texture, inverted_y_mouse_location);
// 	WriteRGBAValues(location, value, poz, 0.5);

// 	let inverted_y_mouseclick_location = vec2<i32>(v2(abs(uni.iMouse.z), uni.iResolution.y - abs(uni.iMouse.w)));
// 	let value2: vec4<f32> = textureLoad(texture, inverted_y_mouseclick_location);
// 	WriteRGBAValues(location, value2, vec2<f32>(0.), 0.25);

// 	draw_crossair(location);

// 	draw_ring(location);

// 	let fragColor = vec4<f32>(vColor, 1.);

// 	return fragColor;
// } 


[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
	
	let y_inverted_location = vec2<i32>((location.x), i32(uni.iResolution.y) - (location.y));


	let fragColor = show_debug_info(location, vec3<f32>(0.5, 0.2, 0.1));
	textureStore(texture, y_inverted_location, toLinear(fragColor));
}



================================================
FILE: assets/shaders/dry_ice/buffer_a.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;



let dissipation: f32 = 0.95;
let ballRadius: f32 = 0.06;
let fogHeigth: f32 = 0.24;
let nbSlice: i32 = 24;
let fogSlice: f32 = 0.01;
let nbSphere: i32 = 3;
let shadowDensity: f32 = 25.;
let fogDensity: f32 = 20.;
let lightHeight: f32 = 1.;
let tau: f32 = 6.28318530718;

fn hash12(p: vec2<f32>) -> f32 {
	var p3: vec3<f32> = fract(vec3<f32>(p.xyx) * 0.1031);
	p3 = p3 + (dot(p3, p3.yzx + 33.33));
	return fract((p3.x + p3.y) * p3.z);
} 

fn hash41(p: f32) -> vec4<f32> {
	var p4: vec4<f32> = fract(vec4<f32>(p) * vec4<f32>(0.1031, 0.103, 0.0973, 0.1099));
	p4 = p4 + (dot(p4, p4.wzxy + 33.33));
	return fract((p4.xxyz + p4.yzzw) * p4.zywx);
} 

fn rotate(angle: f32, radius: f32) -> vec2<f32> {
	return vec2<f32>(cos(angle), -sin(angle)) * radius;
} 

fn floorIntersect(ro: vec3<f32>, rd: vec3<f32>, floorHeight: f32, t: ptr<function, f32>) -> bool {
	var ro_var = ro;
	ro_var.y = ro_var.y - (floorHeight);
	if (rd.y < -0.01) {
		(*t) = ro_var.y / -rd.y;
		return true;
	}
	return false;
} 

fn sphIntersect(ro: vec3<f32>, rd: vec3<f32>, ce: vec3<f32>, ra: f32) -> vec2<f32> {
	let oc: vec3<f32> = ro - ce;
	let b: f32 = dot(oc, rd);
	let c: f32 = dot(oc, oc) - ra * ra;
	var h: f32 = b * b - c;
	if (h < 0.) {	return vec2<f32>(-1.);
 }
	h = sqrt(h);
	return vec2<f32>(-b - h, -b + h);
} 

fn boxIntersection(ro: vec3<f32>, rd: vec3<f32>, rad: vec3<f32>, center: vec3<f32>, oN: ptr<function, vec3<f32>>) -> vec2<f32> {
	var ro_var = ro;
	ro_var = ro_var - (center);
	let m: vec3<f32> = 1. / rd;
	let n: vec3<f32> = m * ro_var;
	let k: vec3<f32> = abs(m) * rad;
	let t1: vec3<f32> = -n - k;
	let t2: vec3<f32> = -n + k;
	let tN: f32 = max(max(t1.x, t1.y), t1.z);
	let tF: f32 = min(min(t2.x, t2.y), t2.z);
	if (tN > tF || tF < 0.) {	return vec2<f32>(-1.);
 }
	(*oN) = -sign(rd) * step(t1.yzx, t1.xyz) * step(t1.zxy, t1.xyz);
	return vec2<f32>(tN, tF);
} 

fn spherePosition(id: i32, frame: i32) -> vec2<f32> {
	let offset: vec4<f32> = hash41(f32(id)) * tau;
	let fframe: f32 = f32(frame);
	return vec2<f32>(cos(offset.x + fframe * 0.015) + cos(offset.y + fframe * 0.02), cos(offset.z + fframe * 0.017) + cos(offset.w + fframe * 0.022)) * vec2<f32>(1., 0.5) * 0.9;
} 

fn dist2(v: vec3<f32>) -> f32 {
	return dot(v, v);
} 


fn sample_texture(ch: texture_storage_2d<rgba32float, read_write>, U01: vec2<f32>) -> vec4<f32> {
	let U = U01 * uni.iResolution;
	let f = vec2<i32>(floor(U));
	let c = vec2<i32>(ceil(U));
	let fr = fract(U);

	let upleft =    vec2<i32>( f.x,  c.y );
	let upright =   vec2<i32>( c.x , c.y );
	let downleft =  vec2<i32>( f.x,  f.y );
	let downright = vec2<i32>( c.x , f.y );


	let interpolated_2d = (
		 (1. - fr.x) * (1. - fr.y) 	* textureLoad(ch, downleft)
		+ (1. - fr.x) * fr.y 		* textureLoad(ch, upleft)
		+ fr.x * fr.y  				* textureLoad(ch, upright)
		+  fr.x * (1. - fr.y) 		* textureLoad(ch, downright)
	);

	return interpolated_2d;
} 


fn noise(p_in: vec3<f32>) -> f32 {
    var p = p_in;
	let ip: vec3<f32> = floor(p);
	p = p - (ip);
	let s: vec3<f32> = vec3<f32>(7., 157., 113.);
	var h: vec4<f32> = vec4<f32>(0., s.yz, s.y + s.z) + dot(ip, s);
	p = p * p * (3. - 2. * p);
	h = mix(fract(sin(h) * 43758.5), fract(sin(h + s.x) * 43758.5), p.x);
	var hxy = h.xy;
	hxy = mix(h.xz, h.yw, p.y);
	h.x = hxy.x;
	h.y = hxy.y;
	return mix(h.x, h.y, p.z);
} 

fn fbm(p_in: vec3<f32>, octaveNum: i32) -> vec2<f32> {
    var p = p_in;
	var octaveNum_var = octaveNum;
	var acc: vec2<f32> = vec2<f32>(0.);
	let freq: f32 = 1.;
	var amp: f32 = 0.5;
	let shift: vec3<f32> = vec3<f32>(100.);

	for (var i: i32 = 0; i < octaveNum_var; i = i + 1) {
		acc = acc + (vec2<f32>(noise(p), noise(p + vec3<f32>(0., 0., 10.))) * amp);
		p = p * 2. + shift;
		amp = amp * (0.5);
	}

	return acc;
} 

fn sampleMinusGradient(coord: vec2<f32>) -> vec3<f32> {
	var veld: vec3<f32> = sample_texture(buffer_a, (coord / uni.iResolution.xy)).xyz;
	let left: f32 = sample_texture(buffer_d, ((coord + vec2<f32>(-1., 0.)) / uni.iResolution.xy)).x;
	let right: f32 = sample_texture(buffer_d, ((coord + vec2<f32>(1., 0.)) / uni.iResolution.xy)).x;
	let bottom: f32 = sample_texture(buffer_d, ((coord + vec2<f32>(0., -1.)) / uni.iResolution.xy)).x;
	let top: f32 = sample_texture(buffer_d, ((coord + vec2<f32>(0., 1.)) / uni.iResolution.xy)).x;
	let grad: vec2<f32> = vec2<f32>(right - left, top - bottom) * 0.5;
	return vec3<f32>(veld.xy - grad, veld.z);
} 

fn vignette(color: vec3<f32>, q: vec2<f32>, v: f32) -> vec3<f32> {
	var color_var = color;
	color_var = color_var * (mix(1., pow(16. * q.x * q.y * (1. - q.x) * (1. - q.y), v), 0.02));
	return color_var;
} 

@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
	var fragColor: vec4<f32>;
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

	var velocity: vec2<f32> = sampleMinusGradient(fragCoord).xy;
	var veld: vec3<f32> = sampleMinusGradient(fragCoord - dissipation * velocity).xyz;
	var density: f32 = veld.z;
	velocity = veld.xy;
	let uv: vec2<f32> = (2. * fragCoord - uni.iResolution.xy) / uni.iResolution.y;
	let detailNoise: vec2<f32> = fbm(vec3<f32>(uv * 40., uni.iTime * 0.5 + 30.), 7) - 0.5;
	velocity = velocity + (detailNoise * 0.2);
	density = density + (length(detailNoise) * 0.01);
	let injectionNoise: vec2<f32> = fbm(vec3<f32>(uv * 1.5, uni.iTime * 0.1 + 30.), 7) - 0.5;
	velocity = velocity + (injectionNoise * 0.1);
	density = density + (max(length(injectionNoise) * 0.04, 0.));
	let influenceRadius: f32 = ballRadius * 2.;

	for (var i: i32 = 0; i < nbSphere; i = i + 1) {
		let p: vec2<f32> = spherePosition(i, i32(uni.iFrame));
		let dist: f32 = distance(uv, p);
		if (dist < influenceRadius) {
			let op: vec2<f32> = spherePosition(i, i32(uni.iFrame) + 1);
			let ballVelocity: vec2<f32> = p - op;
			density = density - ((influenceRadius - dist) / influenceRadius * 0.15);
			density = max(0., density);
			velocity = velocity - (ballVelocity * 5.);
		}
	}

	density = min(1., density);
	density = density * (0.99);
	veld = vec3<f32>(vec3<f32>(velocity, density));
	veld = vignette(veld, fragCoord / uni.iResolution.xy, 1.);
	fragColor = vec4<f32>(veld, 1.);

    textureStore(buffer_a, location, fragColor);
} 



// fn noise(p_in: vec3<f32>) -> f32 {
//     var p = p_in;
// 	let ip: vec3<f32> = floor(p);
// 	p = p - (ip);
// 	let s: vec3<f32> = vec3<f32>(7., 157., 113.);
// 	var h: vec4<f32> = vec4<f32>(0., s.yz, s.y + s.z) + dot(ip, s);
// 	p = p * p * (3. - 2. * p);
// 	h = mix(fract(sin(h) * 43758.5), fract(sin(h + s.x) * 43758.5), p.x);
// 	var hxy = h.xy;
// 	hxy = mix(h.xz, h.yw, p.y);
// 	h.x = hxy.x;
// 	h.y = hxy.y;
// 	return mix(h.x, h.y, p.z);
// } 

// fn fbm(p_in: vec3<f32>, octaveNum: i32) -> vec2<f32> {
//     var p = p_in;
// 	var octaveNum_var = octaveNum;
// 	var acc: vec2<f32> = vec2<f32>(0.);
// 	let freq: f32 = 1.;
// 	var amp: f32 = 0.5;
// 	let shift: vec3<f32> = vec3<f32>(100.);

// 	for (var i: i32 = 0; i < octaveNum_var; i = i + 1) {
// 		acc = acc + (vec2<f32>(noise(p), noise(p + vec3<f32>(0., 0., 10.))) * amp);
// 		p = p * 2. + shift;
// 		amp = amp * (0.5);
// 	}

// 	return acc;
// } 

// fn sampleMinusGradient(coord: vec2<f32>) -> vec3<f32> {
// 	var veld: vec3<f32> = sample_texture(buffer_a,(coord / uni.iResolution.xy)).xyz;
// 	let left: f32 = sample_texture(buffer_d, ((coord + vec2<f32>(-1., 0.)) / uni.iResolution.xy)).x;
// 	let right: f32 = sample_texture(buffer_d, ((coord + vec2<f32>(1., 0.)) / uni.iResolution.xy)).x;
// 	let bottom: f32 = sample_texture(buffer_d, ((coord + vec2<f32>(0., -1.)) / uni.iResolution.xy)).x;
// 	let top: f32 = sample_texture(buffer_d, ((coord + vec2<f32>(0., 1.)) / uni.iResolution.xy)).x;
// 	let grad: vec2<f32> = vec2<f32>(right - left, top - bottom) * 0.5;
// 	return vec3<f32>(veld.xy - grad, veld.z);
// } 

// fn vignette(color: vec3<f32>, q: vec2<f32>, v: f32) -> vec3<f32> {
// 	var color_var = color;
// 	color_var = color_var * (mix(1., pow(16. * q.x * q.y * (1. - q.x) * (1. - q.y), v), 0.02));
// 	return color_var;
// } 

// [[stage(compute), workgroup_size(8, 8, 1)]]
// fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
//     let R: vec2<f32> = uni.iResolution.xy;
//     let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
//     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
// 	var fragColor: vec4<f32> = vec4<f32>(0.);
// 	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

// 	var velocity: vec2<f32> = sampleMinusGradient(fragCoord).xy;
// 	var veld: vec3<f32> = sampleMinusGradient(fragCoord - dissipation * velocity).xyz;
// 	var density: f32 = veld.z;
// 	velocity = veld.xy;
// 	let uv: vec2<f32> = (2. * fragCoord - uni.iResolution.xy) / uni.iResolution.y;


// 	let detailNoise: vec2<f32> = fbm(vec3<f32>(uv * 40., uni.iTime * 0.5 + 30.), 7) - 0.5;
// 	velocity = velocity + (detailNoise * 0.2);
// 	density = density + (length(detailNoise) * 0.01);

// 	let injectionNoise: vec2<f32> = fbm(vec3<f32>(uv * 1.5, uni.iTime * 0.1 + 30.), 7) - 0.5;
// 	velocity = velocity + (injectionNoise * 0.1);
// 	density = density + (max(length(injectionNoise) * 0.04, 0.));

// 	let influenceRadius: f32 = ballRadius * 2.;

// 	for (var i: i32 = 0; i < nbSphere; i = i + 1) {
// 		let p: vec2<f32> = spherePosition(i, i32(uni.iFrame));
// 		let dist: f32 = distance(uv, p);
// 		if (dist < influenceRadius) {
// 			let op: vec2<f32> = spherePosition(i, i32(uni.iFrame) + 1);
// 			let ballVelocity: vec2<f32> = p - op;
// 			density = density - ((influenceRadius - dist) / influenceRadius * 0.15);
// 			density = max(0., density);
// 			velocity = velocity - (ballVelocity * 5.);
// 		}
// 	}

// 	density = min(1., density);
// 	density = density * (0.99);
// 	veld = vec3<f32>(vec3<f32>(velocity, density));
// 	// veld = vignette(veld, fragCoord / uni.iResolution.xy, 1.);
// 	fragColor = vec4<f32>(veld, 1.);

//     textureStore(buffer_a, location, fragColor);

// } 



================================================
FILE: assets/shaders/dry_ice/buffer_b.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;



let dissipation: f32 = 0.95;
let ballRadius: f32 = 0.06;
let fogHeigth: f32 = 0.24;
let nbSlice: i32 = 24;
let fogSlice: f32 = 0.01;
let nbSphere: i32 = 3;
let shadowDensity: f32 = 25.;
let fogDensity: f32 = 20.;
let lightHeight: f32 = 1.;
let tau: f32 = 6.28318530718;

fn hash12(p: vec2<f32>) -> f32 {
	var p3: vec3<f32> = fract(vec3<f32>(p.xyx) * 0.1031);
	p3 = p3 + (dot(p3, p3.yzx + 33.33));
	return fract((p3.x + p3.y) * p3.z);
} 

fn hash41(p: f32) -> vec4<f32> {
	var p4: vec4<f32> = fract(vec4<f32>(p) * vec4<f32>(0.1031, 0.103, 0.0973, 0.1099));
	p4 = p4 + (dot(p4, p4.wzxy + 33.33));
	return fract((p4.xxyz + p4.yzzw) * p4.zywx);
} 

fn rotate(angle: f32, radius: f32) -> vec2<f32> {
	return vec2<f32>(cos(angle), -sin(angle)) * radius;
} 

fn floorIntersect(ro: vec3<f32>, rd: vec3<f32>, floorHeight: f32, t: ptr<function, f32>) -> bool {
	var ro_var = ro;
	ro_var.y = ro_var.y - (floorHeight);
	if (rd.y < -0.01) {
		(*t) = ro_var.y / -rd.y;
		return true;
	}
	return false;
} 

fn sphIntersect(ro: vec3<f32>, rd: vec3<f32>, ce: vec3<f32>, ra: f32) -> vec2<f32> {
	let oc: vec3<f32> = ro - ce;
	let b: f32 = dot(oc, rd);
	let c: f32 = dot(oc, oc) - ra * ra;
	var h: f32 = b * b - c;
	if (h < 0.) {	return vec2<f32>(-1.);
 }
	h = sqrt(h);
	return vec2<f32>(-b - h, -b + h);
} 

fn boxIntersection(ro: vec3<f32>, rd: vec3<f32>, rad: vec3<f32>, center: vec3<f32>, oN: ptr<function, vec3<f32>>) -> vec2<f32> {
	var ro_var = ro;
	ro_var = ro_var - (center);
	let m: vec3<f32> = 1. / rd;
	let n: vec3<f32> = m * ro_var;
	let k: vec3<f32> = abs(m) * rad;
	let t1: vec3<f32> = -n - k;
	let t2: vec3<f32> = -n + k;
	let tN: f32 = max(max(t1.x, t1.y), t1.z);
	let tF: f32 = min(min(t2.x, t2.y), t2.z);
	if (tN > tF || tF < 0.) {	return vec2<f32>(-1.);
 }
	(*oN) = -sign(rd) * step(t1.yzx, t1.xyz) * step(t1.zxy, t1.xyz);
	return vec2<f32>(tN, tF);
} 

fn spherePosition(id: i32, frame: i32) -> vec2<f32> {
	let offset: vec4<f32> = hash41(f32(id)) * tau;
	let fframe: f32 = f32(frame);
	return vec2<f32>(cos(offset.x + fframe * 0.015) + cos(offset.y + fframe * 0.02), cos(offset.z + fframe * 0.017) + cos(offset.w + fframe * 0.022)) * vec2<f32>(1., 0.5) * 0.9;
} 

fn dist2(v: vec3<f32>) -> f32 {
	return dot(v, v);
} 


fn sample_texture(ch: texture_storage_2d<rgba32float, read_write>, U01: vec2<f32>) -> vec4<f32> {
	let U = U01 * uni.iResolution;
	let f = vec2<i32>(floor(U));
	let c = vec2<i32>(ceil(U));
	let fr = fract(U);

	let upleft =    vec2<i32>( f.x,  c.y );
	let upright =   vec2<i32>( c.x , c.y );
	let downleft =  vec2<i32>( f.x,  f.y );
	let downright = vec2<i32>( c.x , f.y );


	let interpolated_2d = (
		 (1. - fr.x) * (1. - fr.y) 	* textureLoad(ch, downleft)
		+ (1. - fr.x) * fr.y 		* textureLoad(ch, upleft)
		+ fr.x * fr.y  				* textureLoad(ch, upright)
		+  fr.x * (1. - fr.y) 		* textureLoad(ch, downright)
	);

	return interpolated_2d;
} 



@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
	var fragColor: vec4<f32>;
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

	let icoord: vec2<i32> = vec2<i32>(fragCoord);
	let vel_x_left: f32 = textureLoad(buffer_a, vec2<i32>(icoord + vec2<i32>(-1, 0))).x;
	let vel_x_right: f32 = textureLoad(buffer_a, vec2<i32>(icoord + vec2<i32>(1, 0))).x;
	let vel_y_bottom: f32 = textureLoad(buffer_a, vec2<i32>(icoord + vec2<i32>(0, -1))).y;
	let vel_y_top: f32 = textureLoad(buffer_a, vec2<i32>(icoord + vec2<i32>(0, 1))).y;
	let divergence: f32 = (vel_x_right - vel_x_left + vel_y_top - vel_y_bottom) * 0.5;
	fragColor = vec4<f32>(divergence, vec3<f32>(1.));
    textureStore(buffer_b, location, fragColor);
} 

// [[stage(compute), workgroup_size(8, 8, 1)]]
// fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
//     let R: vec2<f32> = uni.iResolution.xy;
//     let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
//     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
// 	var fragColor: vec4<f32> = vec4<f32>(0.0, 0.0, 0.0, 1.0);
// 	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

// 	let icoord: vec2<i32> = vec2<i32>(fragCoord);
// 	let vel_x_left: f32 = sample_texture(buffer_a, vec2<f32>(icoord + vec2<i32>(-1, 0))).x;
// 	let vel_x_right: f32 = sample_texture(buffer_a, vec2<f32>(icoord + vec2<i32>(1, 0))).x;
// 	let vel_y_bottom: f32 = sample_texture(buffer_a, vec2<f32>(icoord + vec2<i32>(0, -1))).y;
// 	let vel_y_top: f32 = sample_texture(buffer_a, vec2<f32>(icoord + vec2<i32>(0, 1))).y;
// 	let divergence: f32 = (vel_x_right - vel_x_left + vel_y_top - vel_y_bottom) * 0.5;
// 	fragColor = vec4<f32>(divergence, vec3<f32>(1.));
//     textureStore(buffer_b, location, fragColor);


// } 



================================================
FILE: assets/shaders/dry_ice/buffer_c.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;



let dissipation: f32 = 0.95;
let ballRadius: f32 = 0.06;
let fogHeigth: f32 = 0.24;
let nbSlice: i32 = 24;
let fogSlice: f32 = 0.01;
let nbSphere: i32 = 3;
let shadowDensity: f32 = 25.;
let fogDensity: f32 = 20.;
let lightHeight: f32 = 1.;
let tau: f32 = 6.28318530718;

fn hash12(p: vec2<f32>) -> f32 {
	var p3: vec3<f32> = fract(vec3<f32>(p.xyx) * 0.1031);
	p3 = p3 + (dot(p3, p3.yzx + 33.33));
	return fract((p3.x + p3.y) * p3.z);
} 

fn hash41(p: f32) -> vec4<f32> {
	var p4: vec4<f32> = fract(vec4<f32>(p) * vec4<f32>(0.1031, 0.103, 0.0973, 0.1099));
	p4 = p4 + (dot(p4, p4.wzxy + 33.33));
	return fract((p4.xxyz + p4.yzzw) * p4.zywx);
} 

fn rotate(angle: f32, radius: f32) -> vec2<f32> {
	return vec2<f32>(cos(angle), -sin(angle)) * radius;
} 

fn floorIntersect(ro: vec3<f32>, rd: vec3<f32>, floorHeight: f32, t: ptr<function, f32>) -> bool {
	var ro_var = ro;
	ro_var.y = ro_var.y - (floorHeight);
	if (rd.y < -0.01) {
		(*t) = ro_var.y / -rd.y;
		return true;
	}
	return false;
} 

fn sphIntersect(ro: vec3<f32>, rd: vec3<f32>, ce: vec3<f32>, ra: f32) -> vec2<f32> {
	let oc: vec3<f32> = ro - ce;
	let b: f32 = dot(oc, rd);
	let c: f32 = dot(oc, oc) - ra * ra;
	var h: f32 = b * b - c;
	if (h < 0.) {	return vec2<f32>(-1.);
 }
	h = sqrt(h);
	return vec2<f32>(-b - h, -b + h);
} 

fn boxIntersection(ro: vec3<f32>, rd: vec3<f32>, rad: vec3<f32>, center: vec3<f32>, oN: ptr<function, vec3<f32>>) -> vec2<f32> {
	var ro_var = ro;
	ro_var = ro_var - (center);
	let m: vec3<f32> = 1. / rd;
	let n: vec3<f32> = m * ro_var;
	let k: vec3<f32> = abs(m) * rad;
	let t1: vec3<f32> = -n - k;
	let t2: vec3<f32> = -n + k;
	let tN: f32 = max(max(t1.x, t1.y), t1.z);
	let tF: f32 = min(min(t2.x, t2.y), t2.z);
	if (tN > tF || tF < 0.) {	return vec2<f32>(-1.);
 }
	(*oN) = -sign(rd) * step(t1.yzx, t1.xyz) * step(t1.zxy, t1.xyz);
	return vec2<f32>(tN, tF);
} 

fn spherePosition(id: i32, frame: i32) -> vec2<f32> {
	let offset: vec4<f32> = hash41(f32(id)) * tau;
	let fframe: f32 = f32(frame);
	return vec2<f32>(cos(offset.x + fframe * 0.015) + cos(offset.y + fframe * 0.02), cos(offset.z + fframe * 0.017) + cos(offset.w + fframe * 0.022)) * vec2<f32>(1., 0.5) * 0.9;
} 

fn dist2(v: vec3<f32>) -> f32 {
	return dot(v, v);
} 


fn sample_texture(ch: texture_storage_2d<rgba32float, read_write>, U01: vec2<f32>) -> vec4<f32> {
	let U = U01 * uni.iResolution;
	let f = vec2<i32>(floor(U));
	let c = vec2<i32>(ceil(U));
	let fr = fract(U);

	let upleft =    vec2<i32>( f.x,  c.y );
	let upright =   vec2<i32>( c.x , c.y );
	let downleft =  vec2<i32>( f.x,  f.y );
	let downright = vec2<i32>( c.x , f.y );


	let interpolated_2d = (
		 (1. - fr.x) * (1. - fr.y) 	* textureLoad(ch, downleft)
		+ (1. - fr.x) * fr.y 		* textureLoad(ch, upleft)
		+ fr.x * fr.y  				* textureLoad(ch, upright)
		+  fr.x * (1. - fr.y) 		* textureLoad(ch, downright)
	);

	return interpolated_2d;
} 


var<private> location: vec2<i32>;

fn div(x: i32, y: i32) -> f32 {
	return textureLoad(buffer_b, vec2<i32>(location + vec2<i32>(x, y))).x;
} 

fn getDiv() -> f32 {
	var p: f32 = 0.;
	p = p + (1. * div(-9, 0));
	p = p + (9. * div(-8, -1));
	p = p + (4. * div(-8, 0));
	p = p + (9. * div(-8, 1));
	p = p + (36. * div(-7, -2));
	p = p + (32. * div(-7, -1));
	p = p + (97. * div(-7, 0));
	p = p + (32. * div(-7, 1));
	p = p + (36. * div(-7, 2));
	p = p + (84. * div(-6, -3));
	p = p + (112. * div(-6, -2));
	p = p + (436. * div(-6, -1));
	p = p + (320. * div(-6, 0));
	p = p + (436. * div(-6, 1));
	p = p + (112. * div(-6, 2));
	p = p + (84. * div(-6, 3));
	p = p + (126. * div(-5, -4));
	p = p + (224. * div(-5, -3));
	p = p + (1092. * div(-5, -2));
	p = p + (1280. * div(-5, -1));
	p = p + (2336. * div(-5, 0));
	p = p + (1280. * div(-5, 1));
	p = p + (1092. * div(-5, 2));
	p = p + (224. * div(-5, 3));
	p = p + (126. * div(-5, 4));
	p = p + (126. * div(-4, -5));
	p = p + (280. * div(-4, -4));
	p = p + (1694. * div(-4, -3));
	p = p + (2752. * div(-4, -2));
	p = p + (6656. * div(-4, -1));
	p = p + (6464. * div(-4, 0));
	p = p + (6656. * div(-4, 1));
	p = p + (2752. * div(-4, 2));
	p = p + (1694. * div(-4, 3));
	p = p + (280. * div(-4, 4));
	p = p + (126. * div(-4, 5));
	p = p + (84. * div(-3, -6));
	p = p + (224. * div(-3, -5));
	p = p + (1694. * div(-3, -4));
	p = p + (3520. * div(-3, -3));
	p = p + (11016. * div(-3, -2));
	p = p + (16128. * div(-3, -1));
	p = p + (24608. * div(-3, 0));
	p = p + (16128. * div(-3, 1));
	p = p + (11016. * div(-3, 2));
	p = p + (3520. * div(-3, 3));
	p = p + (1694. * div(-3, 4));
	p = p + (224. * div(-3, 5));
	p = p + (84. * div(-3, 6));
	p = p + (36. * div(-2, -7));
	p = p + (112. * div(-2, -6));
	p = p + (1092. * div(-2, -5));
	p = p + (2752. * div(-2, -4));
	p = p + (11016. * div(-2, -3));
	p = p + (21664. * div(-2, -2));
	p = p + (47432. * div(-2, -1));
	p = p + (59712. * div(-2, 0));
	p = p + (47432. * div(-2, 1));
	p = p + (21664. * div(-2, 2));
	p = p + (11016. * div(-2, 3));
	p = p + (2752. * div(-2, 4));
	p = p + (1092. * div(-2, 5));
	p = p + (112. * div(-2, 6));
	p = p + (36. * div(-2, 7));
	p = p + (9. * div(-1, -8));
	p = p + (32. * div(-1, -7));
	p = p + (436. * div(-1, -6));
	p = p + (1280. * div(-1, -5));
	p = p + (6656. * div(-1, -4));
	p = p + (16128. * div(-1, -3));
	p = p + (47432. * div(-1, -2));
	p = p + (92224. * div(-1, -1));
	p = p + (163476. * div(-1, 0));
	p = p + (92224. * div(-1, 1));
	p = p + (47432. * div(-1, 2));
	p = p + (16128. * div(-1, 3));
	p = p + (6656. * div(-1, 4));
	p = p + (1280. * div(-1, 5));
	p = p + (436. * div(-1, 6));
	p = p + (32. * div(-1, 7));
	p = p + (9. * div(-1, 8));
	p = p + (1. * div(0, -9));
	p = p + (4. * div(0, -8));
	p = p + (97. * div(0, -7));
	p = p + (320. * div(0, -6));
	p = p + (2336. * div(0, -5));
	p = p + (6464. * div(0, -4));
	p = p + (24608. * div(0, -3));
	p = p + (59712. * div(0, -2));
	p = p + (163476. * div(0, -1));
	p = p + (409744. * div(0, 0));
	p = p + (163476. * div(0, 1));
	p = p + (59712. * div(0, 2));
	p = p + (24608. * div(0, 3));
	p = p + (6464. * div(0, 4));
	p = p + (2336. * div(0, 5));
	p = p + (320. * div(0, 6));
	p = p + (97. * div(0, 7));
	p = p + (4. * div(0, 8));
	p = p + (1. * div(0, 9));
	p = p + (9. * div(1, -8));
	p = p + (32. * div(1, -7));
	p = p + (436. * div(1, -6));
	p = p + (1280. * div(1, -5));
	p = p + (6656. * div(1, -4));
	p = p + (16128. * div(1, -3));
	p = p + (47432. * div(1, -2));
	p = p + (92224. * div(1, -1));
	p = p + (163476. * div(1, 0));
	p = p + (92224. * div(1, 1));
	p = p + (47432. * div(1, 2));
	p = p + (16128. * div(1, 3));
	p = p + (6656. * div(1, 4));
	p = p + (1280. * div(1, 5));
	p = p + (436. * div(1, 6));
	p = p + (32. * div(1, 7));
	p = p + (9. * div(1, 8));
	p = p + (36. * div(2, -7));
	p = p + (112. * div(2, -6));
	p = p + (1092. * div(2, -5));
	p = p + (2752. * div(2, -4));
	p = p + (11016. * div(2, -3));
	p = p + (21664. * div(2, -2));
	p = p + (47432. * div(2, -1));
	p = p + (59712. * div(2, 0));
	p = p + (47432. * div(2, 1));
	p = p + (21664. * div(2, 2));
	p = p + (11016. * div(2, 3));
	p = p + (2752. * div(2, 4));
	p = p + (1092. * div(2, 5));
	p = p + (112. * div(2, 6));
	p = p + (36. * div(2, 7));
	p = p + (84. * div(3, -6));
	p = p + (224. * div(3, -5));
	p = p + (1694. * div(3, -4));
	p = p + (3520. * div(3, -3));
	p = p + (11016. * div(3, -2));
	p = p + (16128. * div(3, -1));
	p = p + (24608. * div(3, 0));
	p = p + (16128. * div(3, 1));
	p = p + (11016. * div(3, 2));
	p = p + (3520. * div(3, 3));
	p = p + (1694. * div(3, 4));
	p = p + (224. * div(3, 5));
	p = p + (84. * div(3, 6));
	p = p + (126. * div(4, -5));
	p = p + (280. * div(4, -4));
	p = p + (1694. * div(4, -3));
	p = p + (2752. * div(4, -2));
	p = p + (6656. * div(4, -1));
	p = p + (6464. * div(4, 0));
	p = p + (6656. * div(4, 1));
	p = p + (2752. * div(4, 2));
	p = p + (1694. * div(4, 3));
	p = p + (280. * div(4, 4));
	p = p + (126. * div(4, 5));
	p = p + (126. * div(5, -4));
	p = p + (224. * div(5, -3));
	p = p + (1092. * div(5, -2));
	p = p + (1280. * div(5, -1));
	p = p + (2336. * div(5, 0));
	p = p + (1280. * div(5, 1));
	p = p + (1092. * div(5, 2));
	p = p + (224. * div(5, 3));
	p = p + (126. * div(5, 4));
	p = p + (84. * div(6, -3));
	p = p + (112. * div(6, -2));
	p = p + (436. * div(6, -1));
	p = p + (320. * div(6, 0));
	p = p + (436. * div(6, 1));
	p = p + (112. * div(6, 2));
	p = p + (84. * div(6, 3));
	p = p + (36. * div(7, -2));
	p = p + (32. * div(7, -1));
	p = p + (97. * div(7, 0));
	p = p + (32. * div(7, 1));
	p = p + (36. * div(7, 2));
	p = p + (9. * div(8, -1));
	p = p + (4. * div(8, 0));
	p = p + (9. * div(8, 1));
	p = p + (1. * div(9, 0));
	return p / 1048576.;
} 

fn pre(x: i32, y: i32) -> f32 {
	return textureLoad(buffer_d, vec2<i32>(location + vec2<i32>(x, y))).x;
} 

fn getPre() -> f32 {
	var p: f32 = 0.;
	p = p + (1. * pre(-10, 0));
	p = p + (10. * pre(-9, -1));
	p = p + (10. * pre(-9, 1));
	p = p + (45. * pre(-8, -2));
	p = p + (100. * pre(-8, 0));
	p = p + (45. * pre(-8, 2));
	p = p + (120. * pre(-7, -3));
	p = p + (450. * pre(-7, -1));
	p = p + (450. * pre(-7, 1));
	p = p + (120. * pre(-7, 3));
	p = p + (210. * pre(-6, -4));
	p = p + (1200. * pre(-6, -2));
	p = p + (2025. * pre(-6, 0));
	p = p + (1200. * pre(-6, 2));
	p = p + (210. * pre(-6, 4));
	p = p + (252. * pre(-5, -5));
	p = p + (2100. * pre(-5, -3));
	p = p + (5400. * pre(-5, -1));
	p = p + (5400. * pre(-5, 1));
	p = p + (2100. * pre(-5, 3));
	p = p + (252. * pre(-5, 5));
	p = p + (210. * pre(-4, -6));
	p = p + (2520. * pre(-4, -4));
	p = p + (9450. * pre(-4, -2));
	p = p + (14400. * pre(-4, 0));
	p = p + (9450. * pre(-4, 2));
	p = p + (2520. * pre(-4, 4));
	p = p + (210. * pre(-4, 6));
	p = p + (120. * pre(-3, -7));
	p = p + (2100. * pre(-3, -5));
	p = p + (11340. * pre(-3, -3));
	p = p + (25200. * pre(-3, -1));
	p = p + (25200. * pre(-3, 1));
	p = p + (11340. * pre(-3, 3));
	p = p + (2100. * pre(-3, 5));
	p = p + (120. * pre(-3, 7));
	p = p + (45. * pre(-2, -8));
	p = p + (1200. * pre(-2, -6));
	p = p + (9450. * pre(-2, -4));
	p = p + (30240. * pre(-2, -2));
	p = p + (44100. * pre(-2, 0));
	p = p + (30240. * pre(-2, 2));
	p = p + (9450. * pre(-2, 4));
	p = p + (1200. * pre(-2, 6));
	p = p + (45. * pre(-2, 8));
	p = p + (10. * pre(-1, -9));
	p = p + (450. * pre(-1, -7));
	p = p + (5400. * pre(-1, -5));
	p = p + (25200. * pre(-1, -3));
	p = p + (52920. * pre(-1, -1));
	p = p + (52920. * pre(-1, 1));
	p = p + (25200. * pre(-1, 3));
	p = p + (5400. * pre(-1, 5));
	p = p + (450. * pre(-1, 7));
	p = p + (10. * pre(-1, 9));
	p = p + (1. * pre(0, -10));
	p = p + (100. * pre(0, -8));
	p = p + (2025. * pre(0, -6));
	p = p + (14400. * pre(0, -4));
	p = p + (44100. * pre(0, -2));
	p = p + (63504. * pre(0, 0));
	p = p + (44100. * pre(0, 2));
	p = p + (14400. * pre(0, 4));
	p = p + (2025. * pre(0, 6));
	p = p + (100. * pre(0, 8));
	p = p + (1. * pre(0, 10));
	p = p + (10. * pre(1, -9));
	p = p + (450. * pre(1, -7));
	p = p + (5400. * pre(1, -5));
	p = p + (25200. * pre(1, -3));
	p = p + (52920. * pre(1, -1));
	p = p + (52920. * pre(1, 1));
	p = p + (25200. * pre(1, 3));
	p = p + (5400. * pre(1, 5));
	p = p + (450. * pre(1, 7));
	p = p + (10. * pre(1, 9));
	p = p + (45. * pre(2, -8));
	p = p + (1200. * pre(2, -6));
	p = p + (9450. * pre(2, -4));
	p = p + (30240. * pre(2, -2));
	p = p + (44100. * pre(2, 0));
	p = p + (30240. * pre(2, 2));
	p = p + (9450. * pre(2, 4));
	p = p + (1200. * pre(2, 6));
	p = p + (45. * pre(2, 8));
	p = p + (120. * pre(3, -7));
	p = p + (2100. * pre(3, -5));
	p = p + (11340. * pre(3, -3));
	p = p + (25200. * pre(3, -1));
	p = p + (25200. * pre(3, 1));
	p = p + (11340. * pre(3, 3));
	p = p + (2100. * pre(3, 5));
	p = p + (120. * pre(3, 7));
	p = p + (210. * pre(4, -6));
	p = p + (2520. * pre(4, -4));
	p = p + (9450. * pre(4, -2));
	p = p + (14400. * pre(4, 0));
	p = p + (9450. * pre(4, 2));
	p = p + (2520. * pre(4, 4));
	p = p + (210. * pre(4, 6));
	p = p + (252. * pre(5, -5));
	p = p + (2100. * pre(5, -3));
	p = p + (5400. * pre(5, -1));
	p = p + (5400. * pre(5, 1));
	p = p + (2100. * pre(5, 3));
	p = p + (252. * pre(5, 5));
	p = p + (210. * pre(6, -4));
	p = p + (1200. * pre(6, -2));
	p = p + (2025. * pre(6, 0));
	p = p + (1200. * pre(6, 2));
	p = p + (210. * pre(6, 4));
	p = p + (120. * pre(7, -3));
	p = p + (450. * pre(7, -1));
	p = p + (450. * pre(7, 1));
	p = p + (120. * pre(7, 3));
	p = p + (45. * pre(8, -2));
	p = p + (100. * pre(8, 0));
	p = p + (45. * pre(8, 2));
	p = p + (10. * pre(9, -1));
	p = p + (10. * pre(9, 1));
	p = p + (1. * pre(10, 0));
	return p / 1048576.;
} 

@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
	var fragColor: vec4<f32> = vec4<f32>(0.0, 0.0, 0.0, 0.0);
	var C = vec2<f32>(f32(location.x), f32(location.y) );

	let div: f32 = getDiv();
	let p: f32 = getPre() - div;
	fragColor = vec4<f32>(p, div, vec2<f32>(1.));

    textureStore(buffer_c, location, fragColor);
} 



================================================
FILE: assets/shaders/dry_ice/buffer_d.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;



let dissipation: f32 = 0.95;
let ballRadius: f32 = 0.06;
let fogHeigth: f32 = 0.24;
let nbSlice: i32 = 24;
let fogSlice: f32 = 0.01;
let nbSphere: i32 = 3;
let shadowDensity: f32 = 25.;
let fogDensity: f32 = 20.;
let lightHeight: f32 = 1.;
let tau: f32 = 6.28318530718;

fn hash12(p: vec2<f32>) -> f32 {
	var p3: vec3<f32> = fract(vec3<f32>(p.xyx) * 0.1031);
	p3 = p3 + (dot(p3, p3.yzx + 33.33));
	return fract((p3.x + p3.y) * p3.z);
} 

fn hash41(p: f32) -> vec4<f32> {
	var p4: vec4<f32> = fract(vec4<f32>(p) * vec4<f32>(0.1031, 0.103, 0.0973, 0.1099));
	p4 = p4 + (dot(p4, p4.wzxy + 33.33));
	return fract((p4.xxyz + p4.yzzw) * p4.zywx);
} 

fn rotate(angle: f32, radius: f32) -> vec2<f32> {
	return vec2<f32>(cos(angle), -sin(angle)) * radius;
} 

fn floorIntersect(ro: vec3<f32>, rd: vec3<f32>, floorHeight: f32, t: ptr<function, f32>) -> bool {
	var ro_var = ro;
	ro_var.y = ro_var.y - (floorHeight);
	if (rd.y < -0.01) {
		(*t) = ro_var.y / -rd.y;
		return true;
	}
	return false;
} 

fn sphIntersect(ro: vec3<f32>, rd: vec3<f32>, ce: vec3<f32>, ra: f32) -> vec2<f32> {
	let oc: vec3<f32> = ro - ce;
	let b: f32 = dot(oc, rd);
	let c: f32 = dot(oc, oc) - ra * ra;
	var h: f32 = b * b - c;
	if (h < 0.) {	return vec2<f32>(-1.);
 }
	h = sqrt(h);
	return vec2<f32>(-b - h, -b + h);
} 

fn boxIntersection(ro: vec3<f32>, rd: vec3<f32>, rad: vec3<f32>, center: vec3<f32>, oN: ptr<function, vec3<f32>>) -> vec2<f32> {
	var ro_var = ro;
	ro_var = ro_var - (center);
	let m: vec3<f32> = 1. / rd;
	let n: vec3<f32> = m * ro_var;
	let k: vec3<f32> = abs(m) * rad;
	let t1: vec3<f32> = -n - k;
	let t2: vec3<f32> = -n + k;
	let tN: f32 = max(max(t1.x, t1.y), t1.z);
	let tF: f32 = min(min(t2.x, t2.y), t2.z);
	if (tN > tF || tF < 0.) {	return vec2<f32>(-1.);
 }
	(*oN) = -sign(rd) * step(t1.yzx, t1.xyz) * step(t1.zxy, t1.xyz);
	return vec2<f32>(tN, tF);
} 

fn spherePosition(id: i32, frame: i32) -> vec2<f32> {
	let offset: vec4<f32> = hash41(f32(id)) * tau;
	let fframe: f32 = f32(frame);
	return vec2<f32>(cos(offset.x + fframe * 0.015) + cos(offset.y + fframe * 0.02), cos(offset.z + fframe * 0.017) + cos(offset.w + fframe * 0.022)) * vec2<f32>(1., 0.5) * 0.9;
} 

fn dist2(v: vec3<f32>) -> f32 {
	return dot(v, v);
} 


fn sample_texture(ch: texture_storage_2d<rgba32float, read_write>, U01: vec2<f32>) -> vec4<f32> {
	let U = U01 * uni.iResolution;
	let f = vec2<i32>(floor(U));
	let c = vec2<i32>(ceil(U));
	let fr = fract(U);

	let upleft =    vec2<i32>( f.x,  c.y );
	let upright =   vec2<i32>( c.x , c.y );
	let downleft =  vec2<i32>( f.x,  f.y );
	let downright = vec2<i32>( c.x , f.y );


	let interpolated_2d = (
		 (1. - fr.x) * (1. - fr.y) 	* textureLoad(ch, downleft)
		+ (1. - fr.x) * fr.y 		* textureLoad(ch, upleft)
		+ fr.x * fr.y  				* textureLoad(ch, upright)
		+  fr.x * (1. - fr.y) 		* textureLoad(ch, downright)
	);

	return interpolated_2d;
} 



var<private> location: vec2<i32>;

fn div(x: i32, y: i32) -> f32 {
	return textureLoad(buffer_c, vec2<i32>(location + vec2<i32>(x, y))).y;
} 

fn pre(x: i32, y: i32) -> f32 {
	return textureLoad(buffer_c, vec2<i32>(location + vec2<i32>(x, y))).x;
} 

fn getPre() -> f32 {
	var p: f32 = 0.;
	p = p + (1. * pre(-10, 0));
	p = p + (10. * pre(-9, -1));
	p = p + (10. * pre(-9, 1));
	p = p + (45. * pre(-8, -2));
	p = p + (100. * pre(-8, 0));
	p = p + (45. * pre(-8, 2));
	p = p + (120. * pre(-7, -3));
	p = p + (450. * pre(-7, -1));
	p = p + (450. * pre(-7, 1));
	p = p + (120. * pre(-7, 3));
	p = p + (210. * pre(-6, -4));
	p = p + (1200. * pre(-6, -2));
	p = p + (2025. * pre(-6, 0));
	p = p + (1200. * pre(-6, 2));
	p = p + (210. * pre(-6, 4));
	p = p + (252. * pre(-5, -5));
	p = p + (2100. * pre(-5, -3));
	p = p + (5400. * pre(-5, -1));
	p = p + (5400. * pre(-5, 1));
	p = p + (2100. * pre(-5, 3));
	p = p + (252. * pre(-5, 5));
	p = p + (210. * pre(-4, -6));
	p = p + (2520. * pre(-4, -4));
	p = p + (9450. * pre(-4, -2));
	p = p + (14400. * pre(-4, 0));
	p = p + (9450. * pre(-4, 2));
	p = p + (2520. * pre(-4, 4));
	p = p + (210. * pre(-4, 6));
	p = p + (120. * pre(-3, -7));
	p = p + (2100. * pre(-3, -5));
	p = p + (11340. * pre(-3, -3));
	p = p + (25200. * pre(-3, -1));
	p = p + (25200. * pre(-3, 1));
	p = p + (11340. * pre(-3, 3));
	p = p + (2100. * pre(-3, 5));
	p = p + (120. * pre(-3, 7));
	p = p + (45. * pre(-2, -8));
	p = p + (1200. * pre(-2, -6));
	p = p + (9450. * pre(-2, -4));
	p = p + (30240. * pre(-2, -2));
	p = p + (44100. * pre(-2, 0));
	p = p + (30240. * pre(-2, 2));
	p = p + (9450. * pre(-2, 4));
	p = p + (1200. * pre(-2, 6));
	p = p + (45. * pre(-2, 8));
	p = p + (10. * pre(-1, -9));
	p = p + (450. * pre(-1, -7));
	p = p + (5400. * pre(-1, -5));
	p = p + (25200. * pre(-1, -3));
	p = p + (52920. * pre(-1, -1));
	p = p + (52920. * pre(-1, 1));
	p = p + (25200. * pre(-1, 3));
	p = p + (5400. * pre(-1, 5));
	p = p + (450. * pre(-1, 7));
	p = p + (10. * pre(-1, 9));
	p = p + (1. * pre(0, -10));
	p = p + (100. * pre(0, -8));
	p = p + (2025. * pre(0, -6));
	p = p + (14400. * pre(0, -4));
	p = p + (44100. * pre(0, -2));
	p = p + (63504. * pre(0, 0));
	p = p + (44100. * pre(0, 2));
	p = p + (14400. * pre(0, 4));
	p = p + (2025. * pre(0, 6));
	p = p + (100. * pre(0, 8));
	p = p + (1. * pre(0, 10));
	p = p + (10. * pre(1, -9));
	p = p + (450. * pre(1, -7));
	p = p + (5400. * pre(1, -5));
	p = p + (25200. * pre(1, -3));
	p = p + (52920. * pre(1, -1));
	p = p + (52920. * pre(1, 1));
	p = p + (25200. * pre(1, 3));
	p = p + (5400. * pre(1, 5));
	p = p + (450. * pre(1, 7));
	p = p + (10. * pre(1, 9));
	p = p + (45. * pre(2, -8));
	p = p + (1200. * pre(2, -6));
	p = p + (9450. * pre(2, -4));
	p = p + (30240. * pre(2, -2));
	p = p + (44100. * pre(2, 0));
	p = p + (30240. * pre(2, 2));
	p = p + (9450. * pre(2, 4));
	p = p + (1200. * pre(2, 6));
	p = p + (45. * pre(2, 8));
	p = p + (120. * pre(3, -7));
	p = p + (2100. * pre(3, -5));
	p = p + (11340. * pre(3, -3));
	p = p + (25200. * pre(3, -1));
	p = p + (25200. * pre(3, 1));
	p = p + (11340. * pre(3, 3));
	p = p + (2100. * pre(3, 5));
	p = p + (120. * pre(3, 7));
	p = p + (210. * pre(4, -6));
	p = p + (2520. * pre(4, -4));
	p = p + (9450. * pre(4, -2));
	p = p + (14400. * pre(4, 0));
	p = p + (9450. * pre(4, 2));
	p = p + (2520. * pre(4, 4));
	p = p + (210. * pre(4, 6));
	p = p + (252. * pre(5, -5));
	p = p + (2100. * pre(5, -3));
	p = p + (5400. * pre(5, -1));
	p = p + (5400. * pre(5, 1));
	p = p + (2100. * pre(5, 3));
	p = p + (252. * pre(5, 5));
	p = p + (210. * pre(6, -4));
	p = p + (1200. * pre(6, -2));
	p = p + (2025. * pre(6, 0));
	p = p + (1200. * pre(6, 2));
	p = p + (210. * pre(6, 4));
	p = p + (120. * pre(7, -3));
	p = p + (450. * pre(7, -1));
	p = p + (450. * pre(7, 1));
	p = p + (120. * pre(7, 3));
	p = p + (45. * pre(8, -2));
	p = p + (100. * pre(8, 0));
	p = p + (45. * pre(8, 2));
	p = p + (10. * pre(9, -1));
	p = p + (10. * pre(9, 1));
	p = p + (1. * pre(10, 0));
	return p / 1048576.;
} 

@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
	var fragColor: vec4<f32> = vec4<f32>(0.0, 0.0, 0.0, 0.0);
	var C = vec2<f32>(f32(location.x), f32(location.y) );

	let p: f32 = getPre() - div(0, 0);
	fragColor = vec4<f32>(p, vec3<f32>(1.));
    textureStore(buffer_d, location, fragColor);
} 




================================================
FILE: assets/shaders/dry_ice/image.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;



@group(0) @binding(5)
var texture: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(6)]]
// var font_texture: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(6)
var font_texture: texture_2d<f32>;

@group(0) @binding(7)
var font_texture_sampler: sampler;

@group(0) @binding(8)
var rgba_noise_256_texture: texture_2d<f32>;

@group(0) @binding(9)
var rgba_noise_256_texture_sampler: sampler;

@group(0) @binding(10)
var blue_noise_texture: texture_2d<f32>;

@group(0) @binding(11)
var blue_noise_texture_sampler: sampler;




let dissipation: f32 = 0.95;
let ballRadius: f32 = 0.06;
let fogHeigth: f32 = 0.24;
let nbSlice: i32 = 24;
let fogSlice: f32 = 0.01;
let nbSphere: i32 = 3;
let shadowDensity: f32 = 25.;
let fogDensity: f32 = 20.;
let lightHeight: f32 = 1.;
let tau: f32 = 6.28318530718;

fn hash12(p: vec2<f32>) -> f32 {
	var p3: vec3<f32> = fract(vec3<f32>(p.xyx) * 0.1031);
	p3 = p3 + (dot(p3, p3.yzx + 33.33));
	return fract((p3.x + p3.y) * p3.z);
} 

fn hash41(p: f32) -> vec4<f32> {
	var p4: vec4<f32> = fract(vec4<f32>(p) * vec4<f32>(0.1031, 0.103, 0.0973, 0.1099));
	p4 = p4 + (dot(p4, p4.wzxy + 33.33));
	return fract((p4.xxyz + p4.yzzw) * p4.zywx);
} 

fn rotate(angle: f32, radius: f32) -> vec2<f32> {
	return vec2<f32>(cos(angle), -sin(angle)) * radius;
} 

fn floorIntersect(ro: vec3<f32>, rd: vec3<f32>, floorHeight: f32, t: ptr<function, f32>) -> bool {
	var ro_var = ro;
	ro_var.y = ro_var.y - (floorHeight);
	if (rd.y < -0.01) {
		(*t) = ro_var.y / -rd.y;
		return true;
	}
	return false;
} 

fn sphIntersect(ro: vec3<f32>, rd: vec3<f32>, ce: vec3<f32>, ra: f32) -> vec2<f32> {
	let oc: vec3<f32> = ro - ce;
	let b: f32 = dot(oc, rd);
	let c: f32 = dot(oc, oc) - ra * ra;
	var h: f32 = b * b - c;
	if (h < 0.) {	return vec2<f32>(-1.);
 }
	h = sqrt(h);
	return vec2<f32>(-b - h, -b + h);
} 

fn boxIntersection(ro: vec3<f32>, rd: vec3<f32>, rad: vec3<f32>, center: vec3<f32>, oN: ptr<function, vec3<f32>>) -> vec2<f32> {
	var ro_var = ro;
	ro_var = ro_var - (center);
	let m: vec3<f32> = 1. / rd;
	let n: vec3<f32> = m * ro_var;
	let k: vec3<f32> = abs(m) * rad;
	let t1: vec3<f32> = -n - k;
	let t2: vec3<f32> = -n + k;
	let tN: f32 = max(max(t1.x, t1.y), t1.z);
	let tF: f32 = min(min(t2.x, t2.y), t2.z);
	if (tN > tF || tF < 0.) {	return vec2<f32>(-1.);
 }
	(*oN) = -sign(rd) * step(t1.yzx, t1.xyz) * step(t1.zxy, t1.xyz);
	return vec2<f32>(tN, tF);
} 

fn spherePosition(id: i32, frame: i32) -> vec2<f32> {
	let offset: vec4<f32> = hash41(f32(id)) * tau;
	let fframe: f32 = f32(frame);
	return vec2<f32>(cos(offset.x + fframe * 0.015) + cos(offset.y + fframe * 0.02), cos(offset.z + fframe * 0.017) + cos(offset.w + fframe * 0.022)) * vec2<f32>(1., 0.5) * 0.9;
} 

fn dist2(v: vec3<f32>) -> f32 {
	return dot(v, v);
} 


fn sample_texture(ch: texture_storage_2d<rgba32float, read_write>, U01: vec2<f32>) -> vec4<f32> {
	let U = U01 * uni.iResolution;
	let f = vec2<i32>(floor(U));
	let c = vec2<i32>(ceil(U));
	let fr = fract(U);

	let upleft =    vec2<i32>( f.x,  c.y );
	let upright =   vec2<i32>( c.x , c.y );
	let downleft =  vec2<i32>( f.x,  f.y );
	let downright = vec2<i32>( c.x , f.y );


	let interpolated_2d = (
		 (1. - fr.x) * (1. - fr.y) 	* textureLoad(ch, downleft)
		+ (1. - fr.x) * fr.y 		* textureLoad(ch, upleft)
		+ fr.x * fr.y  				* textureLoad(ch, upright)
		+  fr.x * (1. - fr.y) 		* textureLoad(ch, downright)
	);

	return interpolated_2d;
} 


// https://www.shadertoy.com/view/WlVyRV
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0

fn sceneIntersection(ro: vec3<f32>, rd: vec3<f32>, inter: ptr<function, vec3<f32>>, normal: ptr<function, vec3<f32>>, color: ptr<function, vec3<f32>>, dist: f32, lightPos: ptr<function, vec3<f32>>) -> f32 {
	var mint: f32 = dist;
	(*inter) = vec3<f32>(0.);
	(*normal) = vec3<f32>(0.);
	(*color) = vec3<f32>(0.);

	for (var i: i32 = 0; i < nbSphere; i = i + 1) {
		let p2d: vec2<f32> = spherePosition(i, i32(uni.iFrame));
		let pos: vec3<f32> = vec3<f32>(p2d.x, ballRadius, p2d.y);
		var ballColor: vec3<f32> = vec3<f32>(1., 0., 0.);
		if (i == 0) {
			ballColor = vec3<f32>(1.);
			(*lightPos) = pos + vec3<f32>(0., lightHeight, 0.);
		}
		var t: f32 = sphIntersect(ro, rd, pos, ballRadius).x;
		if (t > 0. && t < mint) {
			mint = t;
			(*inter) = ro + mint * rd;
			(*normal) = normalize((*inter) - pos);
			(*color) = ballColor;
		}
	}


		let aspecRatio: f32 = uni.iResolution.x / uni.iResolution.y;
		var boxNormal: vec3<f32>;
		let t: f32 = boxIntersection(ro, rd, vec3<f32>(aspecRatio, 0.1, 1.), vec3<f32>(0., -0.1, 0.), &boxNormal).x;
		if (t > 0. && t < mint) {
			mint = t;
			(*inter) = ro + mint * rd;
			(*normal) = boxNormal;
			let tileId: vec2<i32> = vec2<i32>(vec2<f32>((*inter).x, (*inter).z) * 3. + 100.);
			 if ((tileId.x & 1 ^ tileId.y & 1) == 0) { (*color) =vec3<f32>(0.3); } else { (*color) =vec3<f32>(0.15); };
		}
	return mint;
} 

fn sampleFog(pos: vec3<f32>) -> f32 {
	var uv: vec2<f32> = pos.xz;
	uv.x = uv.x * (uni.iResolution.y / uni.iResolution.x);
	uv = uv * 0.5 + 0.5;
	if (max(uv.x, uv.y) > 1. || min(uv.x, uv.y) < 0.) {
		return 0.;
	}
	return sample_texture(buffer_a, uv).z;
} 

fn Render(ro: vec3<f32>, rd: vec3<f32>, dist: f32, fudge: f32) -> vec3<f32> {
	var inter: vec3<f32>;
	var normal: vec3<f32>;
	var baseColor: vec3<f32>;
	var lightPos: vec3<f32>;
	let mint: f32 = sceneIntersection(ro, rd, &inter, &normal, &baseColor, dist, &lightPos);
	var color: vec3<f32> = vec3<f32>(0.);
	if (mint < dist) {
		var lightDir: vec3<f32> = normalize(lightPos - inter);
		var lightDist2: f32 = dist2(lightPos - inter);
		var shadowStep: vec3<f32> = fogHeigth / f32(nbSlice) * lightDir / lightDir.y;
		var shadowDist: f32 = 0.;

		for (var i: i32 = 0; i < nbSlice; i = i + 1) {
			var shadowPos: vec3<f32> = inter + shadowStep * f32(i);
			let v: f32 = sampleFog(shadowPos) * fogHeigth;
			shadowDist = shadowDist + (min(max(0., v - shadowPos.y), fogSlice) * length(shadowStep) / fogSlice);
		}

		var shadowFactor: f32 = exp(-shadowDist * shadowDensity * 0.25);
		color = baseColor * (max(0., dot(normal, lightDir) * shadowFactor) + 0.2) / lightDist2;
	} else { 
		color = vec3<f32>(0.);
	}
	var t: f32;
	if (floorIntersect(ro, rd, fogHeigth, &t)) {
		var curPos: vec3<f32> = ro + rd * t;
		let fogStep: vec3<f32> = fogHeigth / f32(nbSlice) * rd / abs(rd.y);
		curPos = curPos + (fudge * fogStep);
		let stepLen: f32 = length(fogStep);
		var curDensity: f32 = 0.;
		var transmittance: f32 = 1.;
		var lightEnergy: f32 = 0.;

		for (var i: i32 = 0; i < nbSlice; i = i + 1) {
			if (dot(curPos - ro, rd) > mint) {			break;
 }
			let curHeigth: f32 = sampleFog(curPos) * fogHeigth;
			let curSample: f32 = min(max(0., curHeigth - curPos.y), fogSlice) * stepLen / fogSlice;
			if (curSample > 0.001) {
				let lightDir: vec3<f32> = normalize(lightPos - curPos);
				let shadowStep: vec3<f32> = fogHeigth / f32(nbSlice) * lightDir / lightDir.y;
				let lightDist2: f32 = dist2(lightPos - curPos);
				var shadowPos: vec3<f32> = curPos + shadowStep * fudge;
				var shadowDist: f32 = 0.;

				for (var j: i32 = 0; j < nbSlice; j = j + 1) {
					shadowPos = shadowPos + (shadowStep);
					if (shadowPos.y > fogHeigth) {
						break;
					}
					let curHeight: f32 = sampleFog(shadowPos) * fogHeigth;
					shadowDist = shadowDist + (min(max(0., curHeight - shadowPos.y), fogSlice) * length(shadowStep) / fogSlice);
				}

				let shadowFactor: f32 = exp(-shadowDist * shadowDensity) / lightDist2;
				curDensity = curSample * fogDensity;
				let absorbedlight: f32 = shadowFactor * (1. * curDensity);
				lightEnergy = lightEnergy + (absorbedlight * transmittance);
				transmittance = transmittance * (1. - curDensity);
			}
			curPos = curPos + (fogStep);
		}

		color = mix(color, vec3<f32>(lightEnergy), 1. - transmittance);
	}
	return color;
} 

fn vignette(color: vec3<f32>, q: vec2<f32>, v: f32) -> vec3<f32> {
	var color_var = color;
	color_var = color_var * (0.3 + 0.8 * pow(16. * q.x * q.y * (1. - q.x) * (1. - q.y), v));
	return color_var;
} 

fn setCamera(ro: vec3<f32>, ta: vec3<f32>) -> mat3x3<f32> {
	let cw: vec3<f32> = normalize(ta - ro);
	let up: vec3<f32> = vec3<f32>(0., 1., 0.);
	let cu: vec3<f32> = normalize(cross(cw, up));
	let cv: vec3<f32> = normalize(cross(cu, cw));
	return mat3x3<f32>(cu, cv, cw);
} 

fn radians (degrees: f32) -> f32 {
    return degrees * ( 3.1416 / 180.);
}

fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
    let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
    let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
    let lower = sRGB / vec4<f32>(12.92);

    return mix(higher, lower, cutoff);
}


@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
	var fragColor: vec4<f32>;
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

	var tot: vec3<f32> = vec3<f32>(0.);
	let p: vec2<f32> = (-uni.iResolution.xy + 2. * fragCoord) / uni.iResolution.y;
	let theta: f32 = radians(360.) * (uni.iMouse.x / uni.iResolution.x - 0.5) - radians(90.);
	let phi: f32 = -radians(30.);
	let ro: vec3<f32> = 2. * vec3<f32>(sin(phi) * cos(theta), cos(phi), sin(phi) * sin(theta));
	let ta: vec3<f32> = vec3<f32>(0.);
	let ca: mat3x3<f32> = setCamera(ro, ta);
	let rd: vec3<f32> = ca * normalize(vec3<f32>(p, 1.5));
	let col: vec3<f32> = Render(ro, rd, 6., hash12(fragCoord + uni.iTime));
	tot = tot + (col);
	tot = vignette(tot, fragCoord / uni.iResolution.xy, 0.6);
	fragColor = vec4<f32>(sqrt(tot), 1.);

    textureStore(texture, y_inverted_location, toLinear(fragColor));
} 




// fn sceneIntersection(
//     ro: vec3<f32>, 
//     rd: vec3<f32>, 
//     inter: ptr<function, vec3<f32>>, 
//     normal: ptr<function, vec3<f32>>, 
//     color: ptr<function, vec3<f32>>, 
//     dist: f32, 
//     lightPos: ptr<function, vec3<f32>>
// ) -> f32 {
// 	var mint: f32 = dist;
// 	(*inter) = vec3<f32>(0.);
// 	(*normal) = vec3<f32>(0.);
// 	(*color) = vec3<f32>(0.);

// 	for (var i: i32 = 0; i < nbSphere; i = i + 1) {
// 		let p2d: vec2<f32> = spherePosition(i, i32(uni.iFrame));
// 		let pos: vec3<f32> = vec3<f32>(p2d.x, ballRadius, p2d.y);
// 		var ballColor: vec3<f32> = vec3<f32>(1., 0., 0.);
// 		if (i == 0) {
// 			ballColor = vec3<f32>(1.);
// 			(*lightPos) = pos + vec3<f32>(0., lightHeight, 0.);
// 		}
// 		var t: f32 = sphIntersect(ro, rd, pos, ballRadius).x;
// 		if (t > 0. && t < mint) {
// 			mint = t;
// 			(*inter) = ro + mint * rd;
// 			(*normal) = normalize((*inter) - pos);
// 			(*color) = ballColor;
// 		}
// 	}


// 		let aspecRatio: f32 = uni.iResolution.x / uni.iResolution.y;
// 		var boxNormal: vec3<f32> = vec3<f32>(0. );
// 		let t: f32 = boxIntersection(ro, rd, vec3<f32>(aspecRatio, 0.1, 1.), vec3<f32>(0., -0.1, 0.), &boxNormal).x;

// 		if (t > 0. && t < mint) {
// 			mint = t;
// 			(*inter) = ro + mint * rd;
// 			(*normal) = boxNormal;
// 			let tileId: vec2<i32> = vec2<i32>(vec2<f32>((*inter).x, (*inter).z) * 3. + 100.);
// 			 if ((tileId.x & 1 ^ tileId.y & 1) == 0) {(*color) = vec3<f32>(0.3); } else { (*color) = vec3<f32>(0.15); };
// 		}

// 	return mint;
// } 

// fn sampleFog(pos: vec3<f32>) -> f32 {
// 	var uv: vec2<f32> = pos.xz;
// 	uv.x = uv.x * (uni.iResolution.y / uni.iResolution.x);
// 	uv = uv * 0.5 + 0.5;
// 	if (max(uv.x, uv.y) > 1. || min(uv.x, uv.y) < 0.) {
// 		return 0.;
// 	}
// 	return sample_texture(buffer_a, uv).z;
// } 

// fn Render(ro: vec3<f32>, rd: vec3<f32>, dist: f32, fudge: f32) -> vec3<f32> {
// 	var inter: vec3<f32> = vec3<f32>(0.);
// 	var normal: vec3<f32> = vec3<f32>(0.);
// 	var baseColor: vec3<f32> = vec3<f32>(0.);
// 	var lightPos: vec3<f32> = vec3<f32>(0.);
// 	let mint: f32 = sceneIntersection(ro, rd, &inter, &normal, &baseColor, dist, &lightPos);
// 	var color: vec3<f32> = vec3<f32>(0.);
// 	if (mint < dist) {
// 		var lightDir: vec3<f32> = normalize(lightPos - inter);
// 		var lightDist2: f32 = dist2(lightPos - inter);
// 		var shadowStep: vec3<f32> = fogHeigth / f32(nbSlice) * lightDir / lightDir.y;
// 		var shadowDist: f32 = 0.;

// 		for (var i: i32 = 0; i < nbSlice; i = i + 1) {
// 			var shadowPos: vec3<f32> = inter + shadowStep * f32(i);
// 			let v: f32 = sampleFog(shadowPos) * fogHeigth;
// 			shadowDist = shadowDist + (min(max(0., v - shadowPos.y), fogSlice) * length(shadowStep) / fogSlice);
// 		}

// 		var shadowFactor: f32 = exp(-shadowDist * shadowDensity * 0.25);
// 		color = baseColor * (max(0., dot(normal, lightDir) * shadowFactor) + 0.2) / lightDist2;
// 	} else { 
// 		color = vec3<f32>(0.);
// 	}
// 	var t: f32 = 0.;
// 	if (floorIntersect(ro, rd, fogHeigth, &t)) {
// 		var curPos: vec3<f32> = ro + rd * t;
// 		let fogStep: vec3<f32> = fogHeigth / f32(nbSlice) * rd / abs(rd.y);
// 		curPos = curPos + (fudge * fogStep);
// 		let stepLen: f32 = length(fogStep);
// 		var curDensity: f32 = 0.;
// 		var transmittance: f32 = 1.;
// 		var lightEnergy: f32 = 0.;

// 		for (var i: i32 = 0; i < nbSlice; i = i + 1) {
// 			if (dot(curPos - ro, rd) > mint) {			break;
//  }
// 			let curHeigth: f32 = sampleFog(curPos) * fogHeigth;
// 			let curSample: f32 = min(max(0., curHeigth - curPos.y), fogSlice) * stepLen / fogSlice;
// 			if (curSample > 0.001) {
// 				let lightDir: vec3<f32> = normalize(lightPos - curPos);
// 				let shadowStep: vec3<f32> = fogHeigth / f32(nbSlice) * lightDir / lightDir.y;
// 				let lightDist2: f32 = dist2(lightPos - curPos);
// 				var shadowPos: vec3<f32> = curPos + shadowStep * fudge;
// 				var shadowDist: f32 = 0.;

// 				for (var j: i32 = 0; j < nbSlice; j = j + 1) {
// 					shadowPos = shadowPos + (shadowStep);
// 					if (shadowPos.y > fogHeigth) {
// 						break;
// 					}
// 					let curHeight: f32 = sampleFog(shadowPos) * fogHeigth;
// 					shadowDist = shadowDist + (min(max(0., curHeight - shadowPos.y), fogSlice) * length(shadowStep) / fogSlice);
// 				}

// 				let shadowFactor: f32 = exp(-shadowDist * shadowDensity) / lightDist2;
// 				curDensity = curSample * fogDensity;
// 				let absorbedlight: f32 = shadowFactor * (1. * curDensity);
// 				lightEnergy = lightEnergy + (absorbedlight * transmittance);
// 				transmittance = transmittance * (1. - curDensity);
// 			}
// 			curPos = curPos + (fogStep);
// 		}

// 		color = mix(color, vec3<f32>(lightEnergy), 1. - transmittance);
// 	}
// 	return color;
// } 

// fn vignette(color: vec3<f32>, q: vec2<f32>, v: f32) -> vec3<f32> {
// 	var color_var = color;
// 	color_var = color_var * (0.3 + 0.8 * pow(16. * q.x * q.y * (1. - q.x) * (1. - q.y), v));
// 	return color_var;
// } 

// fn setCamera(ro: vec3<f32>, ta: vec3<f32>) -> mat3x3<f32> {
// 	let cw: vec3<f32> = normalize(ta - ro);
// 	let up: vec3<f32> = vec3<f32>(0., 1., 0.);
// 	let cu: vec3<f32> = normalize(cross(cw, up));
// 	let cv: vec3<f32> = normalize(cross(cu, cw));
// 	return mat3x3<f32>(cu, cv, cw);
// } 

// fn radians(in: f32) -> f32 {
//     return in * (3.141592653589793 / 180.);
// }

// fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
//     let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
//     let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
//     let lower = sRGB / vec4<f32>(12.92);

//     return mix(higher, lower, cutoff);
// }

// [[stage(compute), workgroup_size(8, 8, 1)]]
// fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
//     let R: vec2<f32> = uni.iResolution.xy;
//     let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
//     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
// 	var fragColor: vec4<f32>;
// 	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

// 	var tot: vec3<f32> = vec3<f32>(0.);
// 	var rook: array<vec2<f32>,4>;
// 	rook[0] = vec2<f32>(1. / 8., 3. / 8.);
// 	rook[1] = vec2<f32>(3. / 8., -1. / 8.);
// 	rook[2] = vec2<f32>(-1. / 8., -3. / 8.);
// 	rook[3] = vec2<f32>(-3. / 8., 1. / 8.);

// 	for (var n: i32 = 0; n < 4; n  = n + 1) {
// 		let o: vec2<f32> = rook[n];
// 		let p: vec2<f32> = (-uni.iResolution.xy + 2. * (fragCoord + o)) / uni.iResolution.y;
// 		let theta: f32 = radians(360.) * (uni.iMouse.x / uni.iResolution.x - 0.5) - radians(90.);
// 		let phi: f32 = -radians(30.);
// 		let ro: vec3<f32> = 2. * vec3<f32>(sin(phi) * cos(theta), cos(phi), sin(phi) * sin(theta));
// 		let ta: vec3<f32> = vec3<f32>(0.);
// 		let ca: mat3x3<f32> = setCamera(ro, ta);
// 		let rd: vec3<f32> = ca * normalize(vec3<f32>(p, 1.5));
// 		let col: vec3<f32> = Render(ro, rd, 6., hash12(fragCoord + uni.iTime));
// 		tot = tot + (col);
// 	}

// 	tot = tot / (4.);
// 	tot = vignette(tot, fragCoord / uni.iResolution.xy, 0.6);
// 	fragColor = vec4<f32>(sqrt(tot), 1.);

//     textureStore(texture, y_inverted_location, toLinear(fragColor));
// } 


// // fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
// //     let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
// //     let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
// //     let lower = sRGB / vec4<f32>(12.92);

// //     return mix(higher, lower, cutoff);
// // }

// // [[stage(compute), workgroup_size(8, 8, 1)]]
// // fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
// //     let R: vec2<f32> = uni.iResolution.xy;
// //     let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
// //     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
// // 	var fragColor: vec4<f32>;
// // 	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

// // 	fragColor = vec4<f32>(vec3<f32>(sample_texture(buffer_a, fragCoord / uni.iResolution).z), 1.);
// //     textureStore(texture, y_inverted_location, toLinear(fragColor));
// // } 



================================================
FILE: assets/shaders/fire/buffer_a.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;







[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let color = vec4<f32>(0.5);
    textureStore(buffer_a, location, color);
}

================================================
FILE: assets/shaders/fire/buffer_b.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;





[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/fire/buffer_c.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;





[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/fire/buffer_d.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;





[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {

}


================================================
FILE: assets/shaders/fire/image.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;
    
    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba32float, read_write>;



// [[group(0), binding(1)]]
// var buffer_a: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(2)]]
// var buffer_b: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(3)]]
// var buffer_c: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(4)]]
// var buffer_d: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(5)]]
var texture: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(6)]]
// var font_texture: texture_storage_2d<rgba32float, read_write>;

[[group(0), binding(6)]]
var font_texture: texture_2d<f32>;

[[group(0), binding(7)]]
var font_texture_sampler: sampler;

[[group(0), binding(8)]]
var rgba_noise_256_texture: texture_2d<f32>;

[[group(0), binding(9)]]
var rgba_noise_256_texture_sampler: sampler;



// [[stage(compute), workgroup_size(8, 8, 1)]]
// fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
//     let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
//     let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

//     let color = vec4<f32>(f32(0));
//     textureStore(texture, location, color);
// }





// https://www.shadertoy.com/view/XsXSWS
// no licence

fn hash(p: vec2<f32>) -> vec2<f32> {
	var p_var = p;
	p_var = vec2<f32>(dot(p_var, vec2<f32>(127.1, 311.7)), dot(p_var, vec2<f32>(269.5, 183.3)));
	return -1. + 2. * fract(sin(p_var) * 43758.547);
} 

fn noise(p: vec2<f32>) -> f32 {
	let K1: f32 = 0.36602542;
	let K2: f32 = 0.21132487;
	let i: vec2<f32> = floor(p + (p.x + p.y) * K1);
	var a: vec2<f32> = p - i + (i.x + i.y) * K2;
	var o: vec2<f32>; 
    if (a.x > a.y) { o = vec2<f32>(1., 0.); } else { o = vec2<f32>(0., 1.); };
	let b: vec2<f32> = a - o + K2;
	var c: vec2<f32> = a - 1. + 2. * K2;
	let h: vec3<f32> = max(0.5 - vec3<f32>(dot(a, a), dot(b, b), dot(c, c)), vec3<f32>(0.));
	var n: vec3<f32> = h * h * h * h * vec3<f32>(dot(a, hash(i + 0.)), dot(b, hash(i + o)), dot(c, hash(i + 1.)));
	return dot(n, vec3<f32>(70.));
} 

fn fbm(uv_in: vec2<f32>) -> f32 {
	var f: f32;
    var uv = uv_in;
	let m: mat2x2<f32> = mat2x2<f32>(1.6, 1.2, -1.2, 1.6);
	f = 0.5 * noise(uv);
	uv = m * uv;
	f = f + (0.25 * noise(uv));
	uv = m * uv;
	f = f + (0.125 * noise(uv));
	uv = m * uv;
	f = f + (0.0625 * noise(uv));
	uv = m * uv;
	f = 0.5 + 0.5 * f;
	return f;
} 

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

	var fragColor: vec4<f32>;
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );
	let uv: vec2<f32> = fragCoord.xy / uni.iResolution.xy;
	var q: vec2<f32> = uv;
	q.x = q.x * (5.);
	q.y = q.y * (2.);
	let strength: f32 = floor(q.x + 1.);
	let T3: f32 = max(3., 1.25 * strength) * uni.iTime;
	q.x = (q.x % 1.) - 0.5;
	q.y = q.y - (0.25);
	let n: f32 = fbm(strength * q - vec2<f32>(0., T3));
	let c: f32 = 1. - 16. * pow(max(0., length(q * vec2<f32>(1.8 + q.y * 1.5, 0.75)) - n * max(0., q.y + 0.25)), 1.2);
	var c1: f32 = n * c * (1.5 - pow(2.5 * uv.y, 4.));
	c1 = clamp(c1, 0., 1.);
	let col: vec3<f32> = vec3<f32>(1.5 * c1, 1.5 * c1 * c1 * c1, c1 * c1 * c1 * c1 * c1 * c1);
	let a: f32 = c * (1. - pow(uv.y, 3.));
	fragColor = vec4<f32>(mix(vec3<f32>(0.), col, a), 1.);

    textureStore(texture, y_inverted_location, fragColor);
} 





================================================
FILE: assets/shaders/fire2/buffer_a.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;







@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let color = vec4<f32>(0.5);
    textureStore(buffer_a, location, color);
}

================================================
FILE: assets/shaders/fire2/buffer_b.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;





@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/fire2/buffer_c.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;





@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {

}

================================================
FILE: assets/shaders/fire2/buffer_d.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;





@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {

}


================================================
FILE: assets/shaders/fire2/image.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;



@group(0) @binding(5)
var texture: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(6)]]
// var font_texture: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(6)
var font_texture: texture_2d<f32>;

@group(0) @binding(7)
var font_texture_sampler: sampler;

@group(0) @binding(8)
var rgba_noise_256_texture: texture_2d<f32>;

@group(0) @binding(9)
var rgba_noise_256_texture_sampler: sampler;

@group(0) @binding(10)
var blue_noise_texture: texture_2d<f32>;

@group(0) @binding(11)
var blue_noise_texture_sampler: sampler;






// original code: https://www.shadertoy.com/view/MlKSWm
// MIT licence

fn mod289(x: vec3<f32>) -> vec3<f32> {
	return x - floor(x * (1. / 289.)) * 289.;
} 

fn mod289_4(x: vec4<f32>) -> vec4<f32> {
	return x - floor(x * (1. / 289.)) * 289.;
} 

fn permute(x: vec4<f32>) -> vec4<f32> {
	return mod289_4((x * 34. + 1.) * x);
} 

fn taylorInvSqrt(r: vec4<f32>) -> vec4<f32> {
	return 1.7928429 - 0.85373473 * r;
} 

fn snoise(v: vec3<f32>) -> f32 {
	let C: vec2<f32> = vec2<f32>(1. / 6., 1. / 3.);
	let D: vec4<f32> = vec4<f32>(0., 0.5, 1., 2.);

	// First corner
	var i: vec3<f32> = floor(v + dot(v, C.yyy));
	let x0: vec3<f32> = v - i + dot(i, C.xxx);

	// Other corners
	let g: vec3<f32> = step(x0.yzx, x0.xyz);
	let l: vec3<f32> = 1. - g;
	let i1: vec3<f32> = min(g.xyz, l.zxy);
	let i2: vec3<f32> = max(g.xyz, l.zxy);
	let x1: vec3<f32> = x0 - i1 + C.xxx;
	let x2: vec3<f32> = x0 - i2 + C.yyy;
	let x3: vec3<f32> = x0 - D.yyy;

	// Permutations
	i = mod289(i);
	let p: vec4<f32> = permute(permute(permute(i.z + vec4<f32>(0., i1.z, i2.z, 1.)) + i.y + vec4<f32>(0., i1.y, i2.y, 1.)) + i.x + vec4<f32>(0., i1.x, i2.x, 1.));
	
	// Gradients: 7x7 points over a square, mapped onto an octahedron.
	// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
	let n_: f32 = 0.14285715;
	let ns: vec3<f32> = n_ * D.wyz - D.xzx;
	let j: vec4<f32> = p - 49. * floor(p * ns.z * ns.z);
	let x_: vec4<f32> = floor(j * ns.z);
	let y_: vec4<f32> = floor(j - 7. * x_);
	var x: vec4<f32> = x_ * ns.x + ns.yyyy;
	var y: vec4<f32> = y_ * ns.x + ns.yyyy;
	let h: vec4<f32> = 1. - abs(x) - abs(y);
	let b0: vec4<f32> = vec4<f32>(x.xy, y.xy);
	let b1: vec4<f32> = vec4<f32>(x.zw, y.zw);
	let s0: vec4<f32> = floor(b0) * 2. + 1.;
	let s1: vec4<f32> = floor(b1) * 2. + 1.;
	let sh: vec4<f32> = -step(h, vec4<f32>(0.));
	let a0: vec4<f32> = b0.xzyw + s0.xzyw * sh.xxyy;
	let a1: vec4<f32> = b1.xzyw + s1.xzyw * sh.zzww;

	//Normalise gradients
	var p0: vec3<f32> = vec3<f32>(a0.xy, h.x);
	var p1: vec3<f32> = vec3<f32>(a0.zw, h.y);
	var p2: vec3<f32> = vec3<f32>(a1.xy, h.z);
	var p3: vec3<f32> = vec3<f32>(a1.zw, h.w);
	let norm: vec4<f32> = inverseSqrt(vec4<f32>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
	p0 = p0 * (norm.x);
	p1 = p1 * (norm.y);
	p2 = p2 * (norm.z);
	p3 = p3 * (norm.w);

	// Mix final noise value
	var m: vec4<f32> = max(0.6 - vec4<f32>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), vec4<f32>(0.));
	m = m * m;
	return 42. * dot(m * m, vec4<f32>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3)));
} 

// PRNG
// From https://www.shadertoy.com/view/4djSRW
fn prng(seed: vec2<f32>) -> f32 {
	var seed_var = seed;
	seed_var = fract(seed_var * vec2<f32>(5.3983, 5.4427));
	seed_var = seed_var + (dot(seed_var.yx, seed_var.xy + vec2<f32>(21.5351, 14.3137)));
	return fract(seed_var.x * seed_var.y * 95.4337);
} 

let PI: f32 = 3.1415927;
fn noiseStack(pos_in: vec3<f32>, octaves: i32, falloff: f32) -> f32 {
	var pos = pos_in;
	var noise: f32 = snoise(vec3<f32>(pos));
	var off: f32 = 1.;
	if (octaves > 1) {
		pos = pos * (2.);
		off = off * (falloff);
		noise = (1. - off) * noise + off * snoise(vec3<f32>(pos));
	}
	if (octaves > 2) {
		pos = pos * (2.);
		off = off * (falloff);
		noise = (1. - off) * noise + off * snoise(vec3<f32>(pos));
	}
	if (octaves > 3) {
		pos = pos * (2.);
		off = off * (falloff);
		noise = (1. - off) * noise + off * snoise(vec3<f32>(pos));
	}
	return (1. + noise) / 2.;
} 

fn noiseStackUV(pos: vec3<f32>, octaves: i32, falloff: f32, diff: f32) -> vec2<f32> {
	let displaceA: f32 = noiseStack(pos, octaves, falloff);
	let displaceB: f32 = noiseStack(pos + vec3<f32>(3984.293, 423.21, 5235.19), octaves, falloff);
	return vec2<f32>(displaceA, displaceB);
} 

fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
    let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
    let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
    let lower = sRGB / vec4<f32>(12.92);

    return mix(higher, lower, cutoff);
}

@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

	var fragColor: vec4<f32>;
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );
	let time: f32 = uni.iTime;
	let resolution: vec2<f32> = uni.iResolution.xy;
	let drag: vec2<f32> = uni.iMouse.xy;
	let offset: vec2<f32> = uni.iMouse.xy;

	let xpart: f32 = fragCoord.x / resolution.x;
	let ypart: f32 = fragCoord.y / resolution.y;

	let clip: f32 = 210.;
	let ypartClip: f32 = fragCoord.y / clip;
	let ypartClippedFalloff: f32 = clamp(2. - ypartClip, 0., 1.);
	let ypartClipped: f32 = min(ypartClip, 1.);
	let ypartClippedn: f32 = 1. - ypartClipped;

	let xfuel: f32 = 1. - abs(2. * xpart - 1.);

	let timeSpeed: f32 = 0.5;
	let realTime: f32 = timeSpeed * time;

	let coordScaled: vec2<f32> = 0.01 * fragCoord - 0.02 * vec2<f32>(offset.x, 0.);
	let position: vec3<f32> = vec3<f32>(coordScaled, 0.) + vec3<f32>(1223., 6434., 8425.);
	let flow: vec3<f32> = vec3<f32>(4.1 * (0.5 - xpart) * pow(ypartClippedn, 4.), -2. * xfuel * pow(ypartClippedn, 64.), 0.);
	let timing: vec3<f32> = realTime * vec3<f32>(0., -1.7, 1.1) + flow;

	let displacePos: vec3<f32> = vec3<f32>(1., 0.5, 1.) * 2.4 * position + realTime * vec3<f32>(0.01, -0.7, 1.3);
	let displace3: vec3<f32> = vec3<f32>(noiseStackUV(displacePos, 2, 0.4, 0.1), 0.);

	let noiseCoord: vec3<f32> = (vec3<f32>(2., 1., 1.) * position + timing + 0.4 * displace3) / 1.;
	let noise: f32 = noiseStack(noiseCoord, 3, 0.4);

	let flames: f32 = pow(ypartClipped, 0.3 * xfuel) * pow(noise, 0.3 * xfuel);

	let f: f32 = ypartClippedFalloff * pow(1. - flames * flames * flames, 8.);
	let fff: f32 = f * f * f;
	let fire: vec3<f32> = 1.5 * vec3<f32>(f, fff, fff * fff);

	// smoke
	let smokeNoise: f32 = 0.5 + snoise(0.4 * position + timing * vec3<f32>(1., 1., 0.2)) / 2.;
	let smoke: vec3<f32> = vec3<f32>(0.3 * pow(xfuel, 3.) * pow(ypart, 2.) * (smokeNoise + 0.4 * (1. - noise)));

	// sparks
	var sparkGridSize: f32 = 30.;
	var sparkCoord: vec2<f32> = fragCoord - vec2<f32>(2. * offset.x, 190. * realTime);
	sparkCoord = sparkCoord - (30. * noiseStackUV(0.01 * vec3<f32>(sparkCoord, 30. * time), 1, 0.4, 0.1));
	sparkCoord = sparkCoord + (100. * flow.xy);

	if (((sparkCoord.y / sparkGridSize) % 2.) < 1.) { sparkCoord.x = sparkCoord.x + (0.5 * sparkGridSize); }
	let sparkGridIndex: vec2<f32> = vec2<f32>(floor(sparkCoord / sparkGridSize));
	let sparkRandom: f32 = prng(sparkGridIndex);
	let sparkLife: f32 = min(10. * (1. - min((sparkGridIndex.y + 190. * realTime / sparkGridSize) / (24. - 20. * sparkRandom), 1.)), 1.);
	var sparks: vec3<f32> = vec3<f32>(0.);
	if (sparkLife > 0.) {
		let sparkSize: f32 = xfuel * xfuel * sparkRandom * 0.08;
		let sparkRadians: f32 = 999. * sparkRandom * 2. * PI + 2. * time;
		let sparkCircular: vec2<f32> = vec2<f32>(sin(sparkRadians), cos(sparkRadians));
		let sparkOffset: vec2<f32> = (0.5 - sparkSize) * sparkGridSize * sparkCircular;
		let sparkModulus: vec2<f32> = ((sparkCoord + sparkOffset) % sparkGridSize) - 0.5 * vec2<f32>(sparkGridSize);
		let sparkLength: f32 = length(sparkModulus);
		let sparksGray: f32 = max(0., 1. - sparkLength / (sparkSize * sparkGridSize));
		sparks = sparkLife * sparksGray * vec3<f32>(1., 0.3, 0.);
	}

	fragColor = vec4<f32>(max(fire, sparks) + smoke, 1.);
	textureStore(texture, y_inverted_location, toLinear(fragColor));
} 





================================================
FILE: assets/shaders/fluid/buffer_a.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;





// var<private> R: vec2<f32>;

fn lnln(p: vec2<f32>, a: vec2<f32>, b: vec2<f32>) -> f32 {
	return length(p - a - (b - a) * clamp(dot(p - a, b - a) / dot(b - a, b - a), 0., 1.));
} 

fn T(U: vec2<f32>) -> vec4<f32> {
	let f = vec2<i32>(floor(U));
	let c = vec2<i32>(ceil(U));
	let fr = fract(U);

	let upleft =    vec2<i32>( f.x,  c.y );
	let upright =   vec2<i32>( c.x , c.y );
	let downleft =  vec2<i32>( f.x,  f.y );
	let downright = vec2<i32>( c.x , f.y );


	let interpolated_2d = (
		 (1. - fr.x) * (1. - fr.y) 	* textureLoad(buffer_a, downleft)
		+ (1. - fr.x) * fr.y 		* textureLoad(buffer_a, upleft)
		+ fr.x * fr.y  				* textureLoad(buffer_a, upright)
		+  fr.x * (1. - fr.y) 		* textureLoad(buffer_a, downright)
	);

	return interpolated_2d;
} 

@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
	var Q: vec4<f32>;
	var U = vec2<f32>(f32(location.x), f32(location.y) );

	// let R = uni.iResolution.xy;
	let O: vec2<f32> = U;
	var A: vec2<f32> = U + vec2<f32>(1., 0.);
	var B: vec2<f32> = U + vec2<f32>(0., 1.);
	var C: vec2<f32> = U + vec2<f32>(-1., 0.);
	var D: vec2<f32> = U + vec2<f32>(0., -1.);
	var u: vec4<f32> = T(U);
	var a: vec4<f32> = T(A);
	var b: vec4<f32> = T(B);
	var c: vec4<f32> = T(C);
	var d: vec4<f32> = T(D);
	var p: vec4<f32> = vec4<f32>(0.);
	var g: vec2<f32> = vec2<f32>(0.);

	for (var i: i32 = 0; i < 2; i = i + 1) {
		U = U - (u.xy);
		A = A - (a.xy);
		B = B - (b.xy);
		C = C - (c.xy);
		D = D - (d.xy);

		p = p + (vec4<f32>(length(U - A), length(U - B), length(U - C), length(U - D)) - 1.);

		g = g + (vec2<f32>(a.z - c.z, b.z - d.z));
		u = T(U);
		a = T(A);
		b = T(B);
		c = T(C);
		d = T(D);
	}

	Q = u;
	let N: vec4<f32> = 0.25 * (a + b + c + d);
	Q = mix(Q, N, vec4<f32>(0., 0., 1., 0.));
	var Qxy = Q.xy;
	Qxy = Q.xy - (g / 10. / f32(2.));
	Q.x = Qxy.x;
	Q.y = Qxy.y;
	Q.z = Q.z + ((p.x + p.y + p.z + p.w) / 10.);
	Q.z = Q.z * (0.95);

	let mouse: vec4<f32> = textureLoad(buffer_d, vec2<i32>(vec2<f32>(0.5) * R));
	let q: f32 = lnln(U, mouse.xy, mouse.zw);
	let m: vec2<f32> = mouse.xy - mouse.zw;
	let l: f32 = length(m);

	if (mouse.z > 0. && l > 0.) {
		var Qxyw = Q.xyw;
        Qxyw = mix(Q.xyw, vec3<f32>(-normalize(m) * min(l, 20.) / 25., 1.), max(0., 5. - q) / 25.);
        Q.x = Qxyw.x;
        Q.y = Qxyw.y;
        Q.w = Qxyw.z;
	}
	// ifuni.iFrame < 1) { 
        
    #ifdef INIT
        Q = vec4<f32>(0.); 
    #endif
        
        
	if (uni.iFrame < 140. && length(U - 0.5 * R) < 20.) {
        var Qxyw = Q.xyw;
        Qxyw = vec3<f32>(0., 0.1, 1.);
        Q.x = Qxyw.x;
        Q.y = Qxyw.y;
        Q.w = Qxyw.z; 
    }
	if (U.x < 1. || U.y < 1. || R.x - U.x < 1. || R.y - U.y < 1.) { 
        var Qxyw = Q.xyw;
        Qxyw = Q.xyw * (0.);
        Q.x = Qxyw.x;
        Q.y = Qxyw.y;
        Q.w = Qxyw.z; 
    }

    textureStore(buffer_a, location, Q);
} 



================================================
FILE: assets/shaders/fluid/buffer_b.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;





@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    
} 



================================================
FILE: assets/shaders/fluid/buffer_c.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;





@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
   
} 



================================================
FILE: assets/shaders/fluid/buffer_d.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;





@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
	var fragColor: vec4<f32>;
	var fragCoord = vec2<f32>(f32(location.x), f32(location.y) );

	var p: vec4<f32> = textureLoad(buffer_d, vec2<i32>(fragCoord));
	if (uni.iMouse.z > 0.) {
		if (p.z > 0.) {		
            fragColor = vec4<f32>(uni.iMouse.xy, p.xy);
		} else { 		
            fragColor = vec4<f32>(uni.iMouse.xy, uni.iMouse.xy);
		}
	} else { 	
        fragColor = vec4<f32>(-uni.iResolution.xy, -uni.iResolution.xy);
	}

    textureStore(buffer_d, location, fragColor);
} 




================================================
FILE: assets/shaders/fluid/image.wgsl
================================================
struct CommonUniform {
    iResolution: vec2<f32>,
    changed_window_size: f32,
    padding0: f32,
    
    iTime: f32,
    iTimeDelta: f32,
    iFrame: f32,
    iSampleRate: f32,
    
    iMouse: vec4<f32>,
    

    iChannelTime: vec4<f32>,
    iChannelResolution: vec4<f32>,
    iDate: vec4<f32>,
};


@group(0) @binding(0)
var<uniform> uni: CommonUniform;

@group(0) @binding(1)
var buffer_a: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(2)
var buffer_b: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(3)
var buffer_c: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(4)
var buffer_d: texture_storage_2d<rgba32float, read_write>;



@group(0) @binding(5)
var texture: texture_storage_2d<rgba32float, read_write>;

// [[group(0), binding(6)]]
// var font_texture: texture_storage_2d<rgba32float, read_write>;

@group(0) @binding(6)
var font_texture: texture_2d<f32>;

@group(0) @binding(7)
var font_texture_sampler: sampler;

@group(0) @binding(8)
var rgba_noise_256_texture: texture_2d<f32>;

@group(0) @binding(9)
var rgba_noise_256_texture_sampler: sampler;






fn t(v: vec2<f32>) -> vec4<f32> {
	return textureLoad(buffer_a, vec2<i32>(v ));
} 

fn toLinear(sRGB: vec4<f32>) -> vec4<f32> {
    let cutoff = vec4<f32>(sRGB < vec4<f32>(0.04045));
    let higher = pow((sRGB + vec4<f32>(0.055)) / vec4<f32>(1.055), vec4<f32>(2.4));
    let lower = sRGB / vec4<f32>(12.92);

    return mix(higher, lower, cutoff);
}

@compute @workgroup_size(8, 8, 1)
fn update(@builtin(global_invocation_id) invocation_id: vec3<u32>) {
    let R: vec2<f32> = uni.iResolution.xy;
    let y_inverted_location = vec2<i32>(i32(invocation_id.x), i32(R.y) - i32(invocation_id.y));
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    
	var C: vec4<f32>;
	let U = vec2<f32>( f32(location.x), f32(location.y) );

	var me: vec4<f32> = t(U);
	me.z = me.z - (1.);
	C = 1. - 3. * me.wwww;

	let d: vec3<f32> = vec3<f32>(
        t(U + vec2<f32>(1., 0.)).w - t(U - vec2<f32>(1., 0.)).w, 
        t(U + vec2<f32>(0., 1.)).w - t(U - vec2<f32>(0., 1.)).w, 
        2.
    );

	var Cxyz = C.xyz;
	Cxyz = C.xyz - (
        max(
            vec3<f32>(0.), 
            sin(vec3<f32>(
                100. * length(me.xy), 
                -5. * me.z, 
                368. * d.y
            ) * me.w)
        ));

	C.x = Cxyz.x;
	C.y = Cxyz.y;
	C.z = Cxyz.z;
    C.a = 1.;

    // let col_debug_info = show_debug_info(location, C.xyz);

    // textureStore(texture, y_inverted_location, toLinear(col_debug_info));

    textureStore(texture, y_inverted_location, (C));
    // textureStore(texture, y_inverted_location, t(U));
}

================================================
FILE: assets/shaders/image_load.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: i32;
    iSampleRate: i32;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
    
    iResolution: vec2<f32>;
    iMouse: vec2<f32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(5)]]
var texture: texture_storage_2d<rgba8unorm, read_write>;

fn hash(value: u32) -> u32 {
    var state = value;
    state = state ^ 2747636419u;
    state = state * 2654435769u;
    state = state ^ state >> 16u;
    state = state * 2654435769u;
    state = state ^ state >> 16u;
    state = state * 2654435769u;
    return state;
}
fn randomFloat(value: u32) -> f32 {
    return f32(hash(value)) / 4294967295.0;
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let randomNumber = randomFloat(invocation_id.y * num_workgroups.x + invocation_id.x);
    let alive = randomNumber > 0.9;
    let color = vec4<f32>(f32(alive));

    textureStore(texture, location, color);
}


// fn get(location: vec2<i32>, offset_x: i32, offset_y: i32) -> i32 {
//     let value: vec4<f32> = textureLoad(texture, location + vec2<i32>(offset_x, offset_y));
//     return i32(value.x);
// }

// fn count_alive(location: vec2<i32>) -> i32 {
//     return get(location, -1, -1) +
//            get(location, -1,  0) +
//            get(location, -1,  1) +
//            get(location,  0, -1) +
//            get(location,  0,  1) +
//            get(location,  1, -1) +
//            get(location,  1,  0) +
//            get(location,  1,  1);
// }

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // let n_alive = count_alive(location);
    // let color = vec4<f32>(f32(n_alive) / 8.0);

    // var alive: bool;
    // if (n_alive == 3) {
    //     alive = true;
    // } else if (n_alive == 2) {
    //     let currently_alive = get(location, 0, 0);
    //     alive = bool(currently_alive);
    // } else {
    //     alive = false;
    // }

    var alive = true;

    // let value: vec4<f32> = textureLoad(buffer_a, vec2<i32>(0,1));
    // if (value.x > 0.51) {
    //     alive = false;
    // }

    // let value: vec4<f32> = textureLoad(buffer_b, vec2<i32>(0,1));
    // if (value.x > 0.74) {
    //     alive = false;
    // }

    // let value: vec4<f32> = textureLoad(buffer_c, vec2<i32>(0,1));
    // if (value.x > 0.61) {
    //     alive = false;
    // }

    let value: vec4<f32> = textureLoad(buffer_a, vec2<i32>(0,1));
    if (value.x > 0.79) {
        alive = false;
    }

    // if (ga > 2) {
    //     alive = true;
    // }

    // if (uni.iTime > 1.0) {
    //     alive = false;
    // }

    // alive = false;

    storageBarrier();

    textureStore(texture, location, vec4<f32>(f32(alive)));
}




================================================
FILE: assets/shaders/interactive_fluid_simulation/buffer_a.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    iMouse: vec4<f32>;
    iResolution: vec2<f32>;
    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};



[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let color = vec4<f32>(0.0);

    textureStore(buffer_a, location, color);
}


[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // textureStore(buffer_a, location, vec4<f32>(0.094));

    if (uni.iTime > 1.0) {
        textureStore(buffer_a, location, vec4<f32>(0.95));
    }
}

================================================
FILE: assets/shaders/interactive_fluid_simulation/buffer_b.wgsl
================================================

struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: i32;
    iSampleRate: i32;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
    
    iResolution: vec2<f32>;
    iMouse: vec2<f32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let color = vec4<f32>(0.0);

    textureStore(buffer_b, location, color);
}


[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // textureStore(buffer_b, location, vec4<f32>(0.85));


    // if (uni.iTime > 1.0) {
    //     textureStore(buffer_b, location, vec4<f32>(0.95));
    // }
}

================================================
FILE: assets/shaders/interactive_fluid_simulation/buffer_c.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    iMouse: vec4<f32>;
    iResolution: vec2<f32>;
    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba8unorm, read_write>;

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let color = vec4<f32>(0.0);

    textureStore(buffer_c, location, color);
}


[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // textureStore(buffer_c, location, vec4<f32>(0.95));

    // if (uni.iTime > 1.0) {
    //     textureStore(buffer_c, location, vec4<f32>(0.95));
    // }
}

================================================
FILE: assets/shaders/interactive_fluid_simulation/buffer_d.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    iMouse: vec4<f32>;
    iResolution: vec2<f32>;
    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};


[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba8unorm, read_write>;

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    let color = vec4<f32>(0.60);

    textureStore(buffer_d, location, color);
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // textureStore(buffer_d, location, vec4<f32>(0.7));

	// let p: vec4<f32> = texture(iChannel0, fragCoord/iResolution.xy);
	// if (uni.iMouse.z>0.) {
	// 	if (p.z>0.) {		fragColor = vec4<f32>(uni.iMouse.xy, p.xy);
	// 	} else {		fragColor = vec4<f32>(uni.iMouse.xy, uni.iMouse.xy);
	// 	}
	
	// } else {	fragColor = vec4<f32>(-uni.iResolution.xy, -uni.iResolution.xy);
	// }


    if (uni.iTime > 1.0) {
        storageBarrier();
        textureStore(buffer_d, location, vec4<f32>(0.95));
    }

    // storageBarrier();
}

// fn mainImage( fragColor: vec4<f32>,  fragCoord: vec2<f32>) -> () {
// 	let p: vec4<f32> = texture(iChannel0, fragCoord/iResolution.xy);
// 	if (iMouse.z>0.) {
// 		if (p.z>0.) {		fragColor = vec4<f32>(iMouse.xy, p.xy);
// 		} else {		fragColor = vec4<f32>(iMouse.xy, iMouse.xy);
// 		}
	
// 	} else {	fragColor = vec4<f32>(-iResolution.xy, -iResolution.xy);
// 	}

// }

================================================
FILE: assets/shaders/interactive_fluid_simulation/image.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    iMouse: vec4<f32>;
    iResolution: vec2<f32>;
    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};


[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;


[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(5)]]
var texture: texture_storage_2d<rgba8unorm, read_write>;

fn hash(value: u32) -> u32 {
    var state = value;
    state = state ^ 2747636419u;
    state = state * 2654435769u;
    state = state ^ state >> 16u;
    state = state * 2654435769u;
    state = state ^ state >> 16u;
    state = state * 2654435769u;
    return state;
}
fn randomFloat(value: u32) -> f32 {
    return f32(hash(value)) / 4294967295.0;
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let randomNumber = randomFloat(invocation_id.y * num_workgroups.x + invocation_id.x);
    let alive = randomNumber > 0.9;
    let color = vec4<f32>(f32(alive));

    textureStore(texture, location, color);
}

fn t(v: vec2<i32>) -> vec4<f32> {
	return textureLoad(buffer_a, v );
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));


    var me: vec4<f32> = t(location) ;
    let U = location;

	me.z = me.z - (1.);
	var C = 1. - 3.*me.www;
	let d: vec3<f32> = vec3<f32>(t(U+vec2<i32>(1, 0)).w-t(U-vec2<i32>(1, 0)).w, t(U+vec2<i32>(0, 1)).w-t(U-vec2<i32>(0, 1)).w, 2.);
	C = C - (max(vec3<f32>(0.), sin(vec3<f32>(100.*length(me.xy), -5.*me.z, 368.*d.y)*me.w)));


    storageBarrier();

    textureStore(texture, location, vec4<f32>(C.x, C.y, C.z, me.w));
}



// fn mainImage( C: vec4<f32>,  U: vec2<f32>) -> () {
// 	let me: vec4<f32> = t(U);
// 	me.z = me.z - (1.);
// 	C = 1.-3.*me.wwww;
// 	let d: vec3<f32> = vec3<f32>(t(U+vec2<f32>(1, 0)).w-t(U-vec2<f32>(1, 0)).w, t(U+vec2<f32>(0, 1)).w-t(U-vec2<f32>(0, 1)).w, 2.);
// 	C.xyz = C.xyz - (max(vec3<f32>(0), sin(vec3<f32>(100.*length(me.xy), -5.*me.z, 368.*d.y)*me.w)));

// }



================================================
FILE: assets/shaders/liquid/buffer_a.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    iMouse: vec4<f32>;
    iResolution: vec2<f32>;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

struct Particle {
    position: vec2<f32>;
    velocity: vec2<f32>;
    mass: vec2<f32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

let fluid_rho: f32 = 0.5;
let dt: f32 = 1.5;
let border_h = 5.0;
let h: f32 = 1.;

fn Pf(rho: vec2<f32>) -> f32
{
    //return 0.2*rho.x; //gas
    let GF: f32 = 1.;//smoothstep(0.49, 0.5, 1. - rho.y);
    return mix(0.5*rho.x, 0.04*rho.x*(rho.x/fluid_rho - 1.), GF); //water pressure
}

fn Rot(ang: f32) -> mat2x2<f32>
{
    return mat2x2<f32>(cos(ang), -sin(ang), sin(ang), cos(ang)); 
}

fn Dir(ang: f32) -> vec2<f32>
{
    return vec2<f32>(cos(ang), sin(ang));
}

fn sdBox(p: vec2<f32>, b: vec2<f32>) -> f32 {
  let d = (abs(p) - b) ;
  return length(max(d, vec2<f32>(0.))) + min(max(d.x, d.y), 0.);
}

fn border(p: vec2<f32>, uni: CommonUniform) -> f32
{
    let R: vec2<f32> = uni.iResolution;
    
    let bound: f32 = -sdBox(p - R*0.5, R*vec2<f32>(0.5, 0.5)); 
    let box: f32 = sdBox(Rot(0.*uni.iTime)*(p - R*vec2<f32>(0.5, 0.6)) , R*vec2<f32>(0.05, 0.01));
    let drain: f32 = -sdBox(p - R*vec2<f32>(0.5, 0.7), R*vec2<f32>(1.5, 0.5));
    return max(drain,min(bound, box));
}


fn bN( p: vec2<f32>, uni: CommonUniform ) -> vec3<f32>
{
    let dx: vec3<f32> = vec3<f32>(-h, 0.0 , h);

    let idx: vec4<f32> = vec4<f32>(-1./h, 0., 1./h, 0.25);
    let r: vec3<f32> = idx.zyw*border(p + dx.zy, uni)
           + idx.xyw*border(p + dx.xy, uni)
           + idx.yzw*border(p + dx.yz, uni)
           + idx.yxw*border(p + dx.yx, uni);

    return vec3<f32>(normalize(r.xy), r.z + 1e-4);

}


fn pack(x: vec2<f32>) -> u32 
{
    var q: vec2<f32>;
    q.x = 65534.0*clamp(0.5*x.x+0.5, 0., 1.);
    q.y = 65534.0*clamp(0.5*x.y+0.5, 0., 1.);
    return u32(round(q.x)) + 65535u*u32(round(q.y));
}

fn unpack(a: u32) -> vec2<f32>
{
    let q = vec2<u32>(a % 65535u, a / 65535u);
    let p = vec2<f32>(
        clamp(f32(q.x) / 65534.0, 0.,1.)*2.0 - 1.0,
        clamp(f32(q.y) / 65534.0, 0.,1.)*2.0 - 1.0
    );
    return p;
}

fn decode(x: f32) -> vec2<f32>
{
    let X: u32 = bitcast<u32>(x);
    return unpack(X); 
}

fn encode(x: vec2<f32>) -> f32
{
    let X: u32 = pack(x);
    let casted: f32 = bitcast<f32>(X);
    return casted;
}

fn getParticle(data: vec4<f32>, pos: vec2<f32>) -> Particle
{
    var P: Particle;
    P.position = decode(data.x) + pos;
    P.velocity = decode(data.y);
    P.mass = data.zw;
    return P;
}


fn saveParticle(in_p: Particle, pos: vec2<f32>) -> vec4<f32>
{
    var P: Particle = in_p;
    // P.position = clamp(P.position - pos, vec2<f32>(-0.5), vec2<f32>(0.5));
    P.position.x = clamp(P.position.x - pos.x, -0.5, 0.5);
    P.position.y = clamp(P.position.y - pos.y, -0.5, 0.5);
    return vec4<f32>(encode(P.position), encode(P.velocity), P.mass.x, P.mass.y);
}

fn hash32(p: vec2<f32>) -> vec3<f32>
{
	var p3: vec3<f32> = fract(vec3<f32>(p.xyx) * vec3<f32>(.1031, .1030, .0973));
    p3 = p3 + dot(p3, p3.yxz+33.33);
    return fract((p3.xxy+p3.yzz)*p3.zyx);
}

fn G(x: vec2<f32>) -> f32
{
    return exp(-dot(x,x));
}

fn G0(x: vec2<f32>) -> f32
{
    return exp(-length(x));
}

fn distribution(x: vec2<f32>,  p: vec2<f32>, K: f32) -> vec3<f32>
{
    let omin: vec2<f32> = clamp(x - K*0.5, p - 0.5, p + 0.5);
    let omax: vec2<f32> = clamp(x + K*0.5, p - 0.5, p + 0.5); 
    return vec3<f32>(0.5*(omin + omax), (omax.x - omin.x)*(omax.y - omin.y)/(K*K));
}


//diffusion and advection basically
fn Reintegration(buffer: texture_storage_2d<rgba8unorm, read_write>, P: Particle, pos: vec2<f32>) -> Particle
{
    var particle: Particle = P;


    
    //basically integral over all updated neighbor distributions
    //that fall inside of this pixel
    //this makes the tracking conservative
    var i: i32 = -2;
    loop  {
        if (i > 2) { break; }

        var j: i32 = -2;
        loop {
            if (j > 2) { break; }

            let tpos: vec2<f32> = pos + vec2<f32>(f32(i),f32(j));

            let data: vec4<f32> = textureLoad(buffer, vec2<i32>(tpos));
        
            var P0: Particle = getParticle(data, tpos);
        
            P0.position = P0.position + P0.velocity*dt; //integrate position

            let difR: f32 = 0.9 + 0.21*smoothStep(fluid_rho*0., fluid_rho*0.333, P0.mass.x);
            let D: vec3<f32> = distribution(P0.position, pos, difR);
            //the deposited mass into this cell
            let m: f32 = P0.mass.x*D.z;
            
            //add weighted by mass
            particle.position = particle.position + D.xy*m;
            particle.velocity =  particle.velocity + P0.velocity*m;
            particle.mass.y = particle.mass.y  +  P0.mass.y*m;
            
            //add mass
            particle.mass.x = particle.mass.x + m;

        }
    }
    // range(i, -2, 2) range(j, -2, 2)

    //normalization
    if(particle.mass.x != 0.)
    {
        particle.position = particle.position / particle.mass.x;
        particle.velocity= particle.velocity / particle.mass.x;
        particle.mass.y = particle.mass.y / particle.mass.x;
    }

    return particle;
}

//force calculation and integration
fn Simulation(
    buffer: texture_storage_2d<rgba8unorm, read_write>,   
    P: Particle,  
    pos: vec2<f32>, 
    Mouse: vec4<f32>,
    uni: CommonUniform
    ) -> Particle
{
    var particle: Particle = P;
    
    
    //Compute the SPH force
    var F: vec2<f32> = vec2<f32>(0.);
    var  avgV: vec3<f32> = vec3<f32>(0.);

    var i: i32 = -2;
    loop  {
        if (i > 2) { break; }

        var j: i32 = -2;
        loop {
            if (j > 2) { break; }

            let tpos: vec2<f32> = pos + vec2<f32>(f32(i), f32(j));
            // let  data: vec4<f32> = texel(ch, tpos);
            let data: vec4<f32> = textureLoad(buffer, vec2<i32>(tpos));

            let  P0: Particle = getParticle(data, tpos);
            let  dx: vec2<f32> = P0.position - particle.position;
            let  avgP: f32 = 0.5*P0.mass.x*(Pf(particle.mass) + Pf(P0.mass)); 
            F = F - 0.5*G(1.*dx)*avgP*dx;
            avgV = avgV + P0.mass.x*G(1.*dx)*vec3<f32>(P0.velocity,1.);
        }
    }

    avgV.x = avgV.x / avgV.z;
    avgV.y = avgV.y / avgV.z;

    //viscosity
    F = F + 0.*particle.mass.x*(avgV.xy - particle.velocity);
    
    //gravity
    F = F + particle.mass.x*vec2<f32>(0., -0.0004);

    if(Mouse.z > 0.)
    {
        let dm: vec2<f32> =(Mouse.xy - Mouse.zw)/10.; 
        let d: f32 = distance(Mouse.xy, particle.position)/20.;
        F = F + 0.001*dm*exp(-d*d);
       // particle.mass.y += 0.1*exp(-40.*d*d);
    }
    
    //integrate
    particle.velocity = particle.velocity + F*dt/particle.mass.x;

    //border 
    let N: vec3<f32> = bN(particle.position, uni);
    let vdotN : f32 = step(N.z, border_h) * dot(-N.xy, particle.velocity);
    particle.velocity = particle.velocity + 0.5*(N.xy*vdotN + N.xy*abs(vdotN));
    particle.velocity = particle.velocity + 0.*particle.mass.x*N.xy*step(abs(N.z), border_h)*exp(-N.z);
    
    if (N.z < 0.) { particle.velocity = vec2<f32>(0.); }
    
    
    //velocity limit
    let v: f32 = length(particle.velocity);
    if (v > 1.0) { 
        particle.velocity = particle.velocity / v; 
    } 

    // particle.velocity = particle.velocity / (v > 1.) ? v : 1.;

    return particle;
}


// // /*
// // vec3 distribution(vec2 x, vec2 p, float K)
// // {
// //     vec4 aabb0 = vec4(p - 0.5, p + 0.5);
// //     vec4 aabb1 = vec4(x - K*0.5, x + K*0.5);
// //     vec4 aabbX = vec4(max(aabb0.xy, aabb1.xy), min(aabb0.zw, aabb1.zw));
// //     vec2 center = 0.5*(aabbX.xy + aabbX.zw); //center of mass
// //     vec2 size = max(aabbX.zw - aabbX.xy, 0.); //only positive
// //     float m = size.x*size.y/(K*K); //relative amount
// //     //if any of the dimensions are 0 then the mass is 0
// //     return vec3(center, m);
// // }*/

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let color = vec4<f32>(0.0);

    textureStore(buffer_a, location, color);
}


[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // textureStore(buffer_a, location, vec4<f32>(0.094));

    if (uni.iTime > 1.0) {
        textureStore(buffer_a, location, vec4<f32>(0.95));
    }
}



================================================
FILE: assets/shaders/liquid/buffer_b.wgsl
================================================

struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: i32;
    iSampleRate: i32;

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
    
    iResolution: vec2<f32>;
    iMouse: vec2<f32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let color = vec4<f32>(0.0);

    textureStore(buffer_b, location, color);
}


[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // textureStore(buffer_b, location, vec4<f32>(0.85));


    // if (uni.iTime > 1.0) {
    //     textureStore(buffer_b, location, vec4<f32>(0.95));
    // }
}

================================================
FILE: assets/shaders/liquid/buffer_c.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    iMouse: vec4<f32>;
    iResolution: vec2<f32>;
    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};

[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba8unorm, read_write>;

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let color = vec4<f32>(0.0);

    textureStore(buffer_c, location, color);
}


[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // textureStore(buffer_c, location, vec4<f32>(0.95));

    // if (uni.iTime > 1.0) {
    //     textureStore(buffer_c, location, vec4<f32>(0.95));
    // }
}

================================================
FILE: assets/shaders/liquid/buffer_d.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    iMouse: vec4<f32>;
    iResolution: vec2<f32>;
    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};


[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba8unorm, read_write>;

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    let color = vec4<f32>(0.60);

    textureStore(buffer_d, location, color);
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // textureStore(buffer_d, location, vec4<f32>(0.7));

    if (uni.iTime > 1.0) {
        storageBarrier();
        textureStore(buffer_d, location, vec4<f32>(0.95));
    }

    // storageBarrier();
}

================================================
FILE: assets/shaders/liquid/image.wgsl
================================================
struct CommonUniform {
    iTime: f32;
    iTimeDelta: f32;
    iFrame: f32;
    iSampleRate: f32;

    iMouse: vec4<f32>;
    iResolution: vec2<f32>;
    

    iChannelTime: vec4<f32>;
    iChannelResolution: vec4<f32>;
    iDate: vec4<i32>;
};


[[group(0), binding(0)]]
var<uniform> uni: CommonUniform;

[[group(0), binding(1)]]
var buffer_a: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(2)]]
var buffer_b: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(3)]]
var buffer_c: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(4)]]
var buffer_d: texture_storage_2d<rgba8unorm, read_write>;

[[group(0), binding(5)]]
var texture: texture_storage_2d<rgba8unorm, read_write>;

fn hash(value: u32) -> u32 {
    var state = value;
    state = state ^ 2747636419u;
    state = state * 2654435769u;
    state = state ^ state >> 16u;
    state = state * 2654435769u;
    state = state ^ state >> 16u;
    state = state * 2654435769u;
    return state;
}
fn randomFloat(value: u32) -> f32 {
    return f32(hash(value)) / 4294967295.0;
}

[[stage(compute), workgroup_size(8, 8, 1)]]
fn init([[builtin(global_invocation_id)]] invocation_id: vec3<u32>, [[builtin(num_workgroups)]] num_workgroups: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));
    let location_f32 = vec2<f32>(f32(invocation_id.x), f32(invocation_id.y));

    let randomNumber = randomFloat(invocation_id.y * num_workgroups.x + invocation_id.x);
    let alive = randomNumber > 0.9;
    let color = vec4<f32>(f32(alive));

    textureStore(texture, location, color);
}


// fn get(location: vec2<i32>, offset_x: i32, offset_y: i32) -> i32 {
//     let value: vec4<f32> = textureLoad(texture, location + vec2<i32>(offset_x, offset_y));
//     return i32(value.x);
// }

// fn count_alive(location: vec2<i32>) -> i32 {
//     return get(location, -1, -1) +
//            get(location, -1,  0) +
//            get(location, -1,  1) +
//            get(location,  0, -1) +
//            get(location,  0,  1) +
//            get(location,  1, -1) +
//            get(location,  1,  0) +
//            get(location,  1,  1);
// }

[[stage(compute), workgroup_size(8, 8, 1)]]
fn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {
    let location = vec2<i32>(i32(invocation_id.x), i32(invocation_id.y));

    // let n_alive = count_alive(location);
    // let color = vec4<f32>(f32(n_alive) / 8.0);

    // var alive: bool;
    // if (n_alive == 3) {
    //     alive = true;
    // } else if (n_alive == 2) {
    //     let currently_alive = get(location, 0, 0);
    //     alive = bool(currently_alive);
    // } else {
    //     alive = false;
    // }

    var alive = true;

    // let value: vec4<f32> = textureLoad(buffer_a, vec2<i32>(0,1));
    // if (value.x > 0.51) {
    //     alive = false;
    // }

    // let value: vec4<f32> = textureLoad(buffer_b, vec2<i32>(0,1));
    // if (value.x > 0.74) {
    //     alive = false;
    // }

    // let value: vec4<f32> = textureLoad(buffer_c, vec2<i32>(0,1));
    // if (value.x > 0.61) {
    //     alive = false;
    // }

    let value: vec4<f32> = textureLoad(buffer_a, vec2<i32>(0,1));
    if (value.x > 0.79) {
        alive = false
Download .txt
gitextract_8_6g6_1p/

├── .gitignore
├── Cargo.toml
├── LICENSES
├── README.md
├── assets/
│   └── shaders/
│       ├── clouds/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── dancing_tree/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── debugger/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── dry_ice/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── fire/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── fire2/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── fluid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── image_load.wgsl
│       ├── interactive_fluid_simulation/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── liquid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── liquid_toy/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── love_and_domination/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── minimal/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── mip_fluid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── mixing_liquid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── molecular_dynamics/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── paint/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   ├── common.wgsl
│       │   └── image.wgsl
│       ├── paint2/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   ├── common.wgsl
│       │   ├── image.wgsl
│       │   └── image2.wgsl
│       ├── paint_streams/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── paint_streams2/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── preludes/
│       │   └── image_prelude
│       ├── protean_clouds/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── seascape/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── simpler_particles/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── simplest_detailed_fluid/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       ├── soul/
│       │   ├── buffer_a.wgsl
│       │   ├── buffer_b.wgsl
│       │   ├── buffer_c.wgsl
│       │   ├── buffer_d.wgsl
│       │   └── image.wgsl
│       └── sunset/
│           ├── buffer_a.wgsl
│           ├── buffer_b.wgsl
│           ├── buffer_c.wgsl
│           ├── buffer_d.wgsl
│           └── image.wgsl
├── bin/
│   ├── assets/
│   │   └── shaders/
│   │       ├── image_load.wgsl
│   │       ├── interactive_fluid_simulation/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── liquid/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── minimal/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── mixing_liquid/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── paint/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   ├── common.wgsl
│   │       │   └── image.wgsl
│   │       ├── paint2/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   ├── common.wgsl
│   │       │   ├── image.wgsl
│   │       │   └── image2.wgsl
│   │       ├── paint_streams/
│   │       │   ├── buffer_a.wgsl
│   │       │   ├── buffer_b.wgsl
│   │       │   ├── buffer_c.wgsl
│   │       │   ├── buffer_d.wgsl
│   │       │   └── image.wgsl
│   │       ├── preludes/
│   │       │   └── image_prelude
│   │       └── simplest_detailed_fluid/
│   │           ├── buffer_a.wgsl
│   │           ├── buffer_b.wgsl
│   │           ├── buffer_c.wgsl
│   │           ├── buffer_d.wgsl
│   │           └── image.wgsl
│   ├── examples/
│   │   ├── minimal/
│   │   │   ├── buffer_a.wgsl
│   │   │   ├── buffer_b.wgsl
│   │   │   ├── buffer_c.wgsl
│   │   │   ├── buffer_d.wgsl
│   │   │   ├── common.wgsl
│   │   │   └── image.wgsl
│   │   ├── mixing_liquid/
│   │   │   ├── buffer_a.wgsl
│   │   │   ├── buffer_b.wgsl
│   │   │   ├── buffer_c.wgsl
│   │   │   ├── buffer_d.wgsl
│   │   │   ├── common.wgsl
│   │   │   └── image.wgsl
│   │   ├── paint/
│   │   │   ├── buffer_a.wgsl
│   │   │   ├── buffer_b.wgsl
│   │   │   ├── buffer_c.wgsl
│   │   │   ├── buffer_d.wgsl
│   │   │   ├── common.wgsl
│   │   │   └── image.wgsl
│   │   └── paint_streams/
│   │       ├── buffer_a.wgsl
│   │       ├── buffer_b.wgsl
│   │       ├── buffer_c.wgsl
│   │       ├── buffer_d.wgsl
│   │       ├── common.wgsl
│   │       └── image.wgsl
│   ├── main.rs
│   ├── templates/
│   │   ├── buffer_a_template.wgsl
│   │   ├── buffer_b_template.wgsl
│   │   ├── buffer_c_template.wgsl
│   │   ├── buffer_d_template.wgsl
│   │   ├── common.wgsl
│   │   ├── common_prelude.wgsl
│   │   ├── image.wgsl
│   │   └── image_template.wgsl
│   ├── test_renderdoc
│   ├── test_renderdoc.d
│   ├── texture_a.rs
│   ├── texture_b.rs
│   ├── texture_c.rs
│   └── texture_d.rs
├── examples/
│   ├── debugger/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   └── image.wgsl
│   ├── dry_ice/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── dry_ice.rs
│   │   └── image.wgsl
│   ├── fire/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   └── image.wgsl
│   ├── fire2/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── fire2.rs
│   │   └── image.wgsl
│   ├── fluid/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── fluid.rs
│   │   └── image.wgsl
│   ├── liquid_toy/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── liquid_toy.rs
│   ├── minimal/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── minimal.rs
│   ├── paint/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── paint.rs
│   ├── paint_streams/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── paint_streams.rs
│   ├── protean_clouds/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── protean_clouds.rs
│   ├── seascape/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── seascape.rs
│   ├── simpler_particles/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── fps.rs
│   │   ├── image.wgsl
│   │   └── simpler_particles.rs
│   ├── soul/
│   │   ├── buffer_a.wgsl
│   │   ├── buffer_b.wgsl
│   │   ├── buffer_c.wgsl
│   │   ├── buffer_d.wgsl
│   │   ├── common.wgsl
│   │   ├── image.wgsl
│   │   └── soul.rs
│   └── sunset/
│       ├── buffer_a.wgsl
│       ├── buffer_b.wgsl
│       ├── buffer_c.wgsl
│       ├── buffer_d.wgsl
│       ├── common.wgsl
│       ├── image.wgsl
│       └── sunset.rs
└── src/
    ├── lib.rs
    ├── templates/
    │   ├── buffer_a_template.wgsl
    │   ├── buffer_b_template.wgsl
    │   ├── buffer_c_template.wgsl
    │   ├── buffer_d_template.wgsl
    │   ├── common.wgsl
    │   ├── common_prelude.wgsl
    │   ├── debugger.wgsl
    │   ├── image.wgsl
    │   └── image_template.wgsl
    ├── texture_a.rs
    ├── texture_b.rs
    ├── texture_c.rs
    └── texture_d.rs
Download .txt
SYMBOL INDEX (169 symbols across 23 files)

FILE: bin/main.rs
  constant SIZE (line 33) | pub const SIZE: (u32, u32) = (1280, 720);
  constant WORKGROUP_SIZE (line 34) | pub const WORKGROUP_SIZE: u32 = 8;
  constant NUM_PARTICLES (line 35) | pub const NUM_PARTICLES: u32 = 256;
  function main (line 74) | fn main() {
  function setup (line 99) | fn setup(
  function make_and_load_shaders (line 292) | pub fn make_and_load_shaders(example: &str, asset_server: &Res<AssetServ...
  function make_and_load_shaders2 (line 308) | pub fn make_and_load_shaders2(example: &str, asset_server: &Res<AssetSer...
  function format_and_save_shader (line 335) | fn format_and_save_shader(example: &str, buffer_type: &str) {
  type CommonUniform (line 395) | pub struct CommonUniform {
  type CommonUniformMeta (line 409) | pub struct CommonUniformMeta {
  function update_common_uniform (line 414) | fn update_common_uniform(
  type ShadertoyPlugin (line 457) | pub struct ShadertoyPlugin;
  type ShaderHandles (line 460) | pub struct ShaderHandles {
  method build (line 469) | fn build(&self, app: &mut App) {
  type MainImagePipeline (line 535) | pub struct MainImagePipeline {
  method from_world (line 540) | fn from_world(world: &mut World) -> Self {
  type MainImage (line 619) | struct MainImage(Handle<Image>);
  type MainImageBindGroup (line 621) | struct MainImageBindGroup {
  function prepare_common_uniform (line 628) | pub fn prepare_common_uniform(
  function extract_main_image (line 644) | fn extract_main_image(
  function queue_bind_group (line 658) | fn queue_bind_group(
  type ShadertoyState (line 733) | pub enum ShadertoyState {
  type MainNode (line 739) | pub struct MainNode {
    method update (line 752) | fn update(&mut self, world: &mut World) {
    method run (line 779) | fn run(
  method default (line 744) | fn default() -> Self {

FILE: bin/texture_a.rs
  type TextureABindGroup (line 20) | struct TextureABindGroup {
  type TextureA (line 35) | pub struct TextureA(pub Handle<Image>);
  type TextureAPipeline (line 37) | pub struct TextureAPipeline {
  method from_world (line 42) | fn from_world(world: &mut World) -> Self {
  function extract_texture_a (line 109) | pub fn extract_texture_a(mut commands: Commands, image: Res<TextureA>) {
  function queue_bind_group_a (line 113) | pub fn queue_bind_group_a(
  type TextureANode (line 183) | pub struct TextureANode {
    method update (line 196) | fn update(&mut self, world: &mut World) {
    method run (line 223) | fn run(
  method default (line 188) | fn default() -> Self {

FILE: bin/texture_b.rs
  type TextureBBindGroup (line 20) | struct TextureBBindGroup {
  type TextureB (line 27) | pub struct TextureB(pub Handle<Image>);
  type TextureBPipeline (line 29) | pub struct TextureBPipeline {
  method from_world (line 34) | fn from_world(world: &mut World) -> Self {
  function extract_texture_b (line 81) | pub fn extract_texture_b(mut commands: Commands, image: Res<TextureB>) {
  function queue_bind_group_b (line 85) | pub fn queue_bind_group_b(
  type TextureBNode (line 141) | pub struct TextureBNode {
    method update (line 154) | fn update(&mut self, world: &mut World) {
    method run (line 181) | fn run(
  method default (line 146) | fn default() -> Self {

FILE: bin/texture_c.rs
  type TextureCBindGroup (line 19) | struct TextureCBindGroup {
  type TextureC (line 26) | pub struct TextureC(pub Handle<Image>);
  type TextureCPipeline (line 28) | pub struct TextureCPipeline {
  method from_world (line 33) | fn from_world(world: &mut World) -> Self {
  function extract_texture_c (line 94) | pub fn extract_texture_c(mut commands: Commands, image: Res<TextureC>) {
  function queue_bind_group_c (line 98) | pub fn queue_bind_group_c(
  type TextureCNode (line 160) | pub struct TextureCNode {
    method update (line 173) | fn update(&mut self, world: &mut World) {
    method run (line 200) | fn run(
  method default (line 165) | fn default() -> Self {

FILE: bin/texture_d.rs
  type TextureDPipeline (line 21) | pub struct TextureDPipeline {
  method from_world (line 26) | fn from_world(world: &mut World) -> Self {
  type TextureD (line 95) | pub struct TextureD(pub Handle<Image>);
  type TextureDBindGroup (line 97) | struct TextureDBindGroup {
  function extract_texture_d (line 103) | pub fn extract_texture_d(mut commands: Commands, image: Res<TextureD>) {
  function queue_bind_group_d (line 107) | pub fn queue_bind_group_d(
  type MainUpdatePipelineKey (line 178) | pub struct MainUpdatePipelineKey {
  method default (line 183) | fn default() -> Self {
  type TextureDNode (line 190) | pub struct TextureDNode {
    method update (line 203) | fn update(&mut self, world: &mut World) {
    method run (line 230) | fn run(
  method default (line 195) | fn default() -> Self {

FILE: examples/dry_ice/dry_ice.rs
  function main (line 12) | fn main() {
  function setup (line 38) | fn setup(

FILE: examples/fire2/fire2.rs
  function main (line 12) | fn main() {
  function setup (line 37) | fn setup(

FILE: examples/fluid/fluid.rs
  function main (line 13) | fn main() {
  function setup (line 39) | fn setup(

FILE: examples/liquid_toy/liquid_toy.rs
  function main (line 13) | fn main() {
  function setup (line 38) | fn setup(

FILE: examples/minimal/minimal.rs
  function main (line 8) | fn main() {
  function setup (line 33) | fn setup(

FILE: examples/paint/paint.rs
  function main (line 9) | fn main() {
  function setup (line 34) | fn setup(

FILE: examples/paint_streams/paint_streams.rs
  function main (line 15) | fn main() {
  function setup (line 45) | fn setup(
  function match_window_size (line 59) | fn match_window_size(windows: Res<Windows>, mut canvas: ResMut<Shadertoy...
  function limit_fps (line 67) | fn limit_fps() {

FILE: examples/protean_clouds/protean_clouds.rs
  function main (line 12) | fn main() {
  function setup (line 37) | fn setup(

FILE: examples/seascape/seascape.rs
  function main (line 12) | fn main() {
  function setup (line 37) | fn setup(

FILE: examples/simpler_particles/fps.rs
  constant TIMESTEP_4_PER_SECOND (line 7) | const TIMESTEP_4_PER_SECOND: f64 = 20.0 / 60.0;
  type FPSPlugin (line 9) | pub struct FPSPlugin;
  method build (line 12) | fn build(&self, app: &mut App) {
  type FpsText (line 39) | struct FpsText;
  type ColorText (line 43) | struct ColorText;
  function setup (line 45) | fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
  function text_color_system (line 77) | fn text_color_system(time: Res<Time>, mut query: Query<&mut Text, With<C...
  function text_update_system (line 91) | fn text_update_system(diagnostics: Res<Diagnostics>, mut query: Query<&m...

FILE: examples/simpler_particles/simpler_particles.rs
  function main (line 14) | fn main() {
  function setup (line 44) | fn setup(

FILE: examples/soul/soul.rs
  function main (line 13) | fn main() {
  function setup (line 38) | fn setup(

FILE: examples/sunset/sunset.rs
  function main (line 11) | fn main() {
  function setup (line 37) | fn setup(

FILE: src/lib.rs
  constant WORKGROUP_SIZE (line 55) | pub const WORKGROUP_SIZE: u32 = 8;
  constant NUM_PARTICLES (line 56) | pub const NUM_PARTICLES: u32 = 256;
  type ShadertoyCanvas (line 60) | pub struct ShadertoyCanvas {
  type ShadertoyTextures (line 68) | pub struct ShadertoyTextures {
  type ShadertoyResources (line 75) | pub struct ShadertoyResources {
  function setup (line 81) | fn setup(
  function make_and_load_shaders (line 259) | pub fn make_and_load_shaders(example: &str, asset_server: &Res<AssetServ...
  function make_and_load_shaders2 (line 275) | pub fn make_and_load_shaders2(
  function format_and_save_shader (line 306) | fn format_and_save_shader(example: &str, buffer_type: &str, include_debu...
  type CommonUniform (line 376) | pub struct CommonUniform {
    method new (line 394) | pub fn new() -> Self {
    method into_crevice (line 413) | pub fn into_crevice(&self) -> CommonUniformCrevice {
  type CommonUniformCrevice (line 458) | pub struct CommonUniformCrevice {
  type ExtractedUniform (line 476) | pub struct ExtractedUniform(pub CommonUniformCrevice);
  type Source (line 479) | type Source = CommonUniform;
  method extract_resource (line 481) | fn extract_resource(common_uniform: &Self::Source) -> Self {
  type CommonUniformMeta (line 517) | pub struct CommonUniformMeta {
  function make_new_texture (line 521) | fn make_new_texture(
  function update_common_uniform (line 542) | fn update_common_uniform(
  type ShadertoyPlugin (line 629) | pub struct ShadertoyPlugin;
  type ShaderHandles (line 632) | pub struct ShaderHandles {
  method build (line 641) | fn build(&self, app: &mut App) {
  type ShadertoyPipelines (line 730) | pub struct ShadertoyPipelines {
    method make_texture_layout (line 736) | pub fn make_texture_layout(binding: u32) -> BindGroupLayoutEntry {
    method new (line 749) | pub fn new(render_device: &RenderDevice) -> Self {
  method from_world (line 854) | fn from_world(world: &mut World) -> Self {
  type MainImage (line 982) | struct MainImage(Handle<Image>);
  type MainImageBindGroup (line 986) | struct MainImageBindGroup {
  function prepare_common_uniform (line 993) | pub fn prepare_common_uniform(
  type ChangedWindowSize (line 1029) | pub struct ChangedWindowSize(pub bool);
  function extract_stuff_here (line 1031) | fn extract_stuff_here(
  function queue_bind_group (line 1082) | fn queue_bind_group(
  type ShadertoyState (line 1221) | pub enum ShadertoyState {
  type MainNode (line 1227) | pub struct MainNode {
    method update (line 1240) | fn update(&mut self, world: &mut World) {
    method run (line 1267) | fn run(
  method default (line 1232) | fn default() -> Self {

FILE: src/texture_a.rs
  type TextureABindGroup (line 22) | struct TextureABindGroup {
  type TextureA (line 37) | pub struct TextureA(pub Handle<Image>);
  function queue_bind_group_a (line 115) | pub fn queue_bind_group_a(
  type TextureANode (line 186) | pub struct TextureANode {
    method update (line 199) | fn update(&mut self, world: &mut World) {
    method run (line 226) | fn run(
  method default (line 191) | fn default() -> Self {

FILE: src/texture_b.rs
  type TextureBBindGroup (line 24) | struct TextureBBindGroup {
  type TextureB (line 31) | pub struct TextureB(pub Handle<Image>);
  function queue_bind_group_b (line 109) | pub fn queue_bind_group_b(
  type TextureBNode (line 177) | pub struct TextureBNode {
    method update (line 190) | fn update(&mut self, world: &mut World) {
    method run (line 217) | fn run(
  method default (line 182) | fn default() -> Self {

FILE: src/texture_c.rs
  type TextureCBindGroup (line 22) | struct TextureCBindGroup {
  type TextureC (line 29) | pub struct TextureC(pub Handle<Image>);
  function queue_bind_group_c (line 111) | pub fn queue_bind_group_c(
  type TextureCNode (line 179) | pub struct TextureCNode {
    method update (line 192) | fn update(&mut self, world: &mut World) {
    method run (line 219) | fn run(
  method default (line 184) | fn default() -> Self {

FILE: src/texture_d.rs
  type TextureD (line 97) | pub struct TextureD(pub Handle<Image>);
  type TextureDBindGroup (line 99) | struct TextureDBindGroup {
  function queue_bind_group_d (line 109) | pub fn queue_bind_group_d(
  type MainUpdatePipelineKey (line 180) | pub struct MainUpdatePipelineKey {
  method default (line 185) | fn default() -> Self {
  type TextureDNode (line 192) | pub struct TextureDNode {
    method update (line 205) | fn update(&mut self, world: &mut World) {
    method run (line 232) | fn run(
  method default (line 197) | fn default() -> Self {
Condensed preview — 329 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,203K chars).
[
  {
    "path": ".gitignore",
    "chars": 340,
    "preview": "\n# Generated by Cargo\n# will have compiled files and executables\n/target/\n\n# Remove Cargo.lock from gitignore if creatin"
  },
  {
    "path": "Cargo.toml",
    "chars": 1469,
    "preview": "[package]\nname = \"bevy_shadertoy_wgsl\"\nversion = \"0.1.0\"\nedition = \"2021\"\nauthors = [\"Eliot Bolduc\"]\n\n[dependencies]\nbyt"
  },
  {
    "path": "LICENSES",
    "chars": 2514,
    "preview": "bevy_shadertoy_wgsl is dual-licensed under either\n\n* MIT License (docs/LICENSE-MIT or <http://opensource.org/licenses/MI"
  },
  {
    "path": "README.md",
    "chars": 487,
    "preview": "# bevy_shadertoy_wgsl\n\nA Shadertoy clone for the Bevy game engine, where the glsl language is replaced by wgsl.\n\n\nClone "
  },
  {
    "path": "assets/shaders/clouds/buffer_a.wgsl",
    "chars": 919,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/clouds/buffer_b.wgsl",
    "chars": 767,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/clouds/buffer_c.wgsl",
    "chars": 767,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/clouds/buffer_d.wgsl",
    "chars": 768,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/clouds/image.wgsl",
    "chars": 10502,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/dancing_tree/buffer_a.wgsl",
    "chars": 924,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/dancing_tree/buffer_b.wgsl",
    "chars": 772,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/dancing_tree/buffer_c.wgsl",
    "chars": 772,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/dancing_tree/buffer_d.wgsl",
    "chars": 773,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/dancing_tree/image.wgsl",
    "chars": 20032,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/debugger/buffer_a.wgsl",
    "chars": 1247,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/debugger/buffer_b.wgsl",
    "chars": 1095,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/debugger/buffer_c.wgsl",
    "chars": 1095,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/debugger/buffer_d.wgsl",
    "chars": 1096,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/debugger/image.wgsl",
    "chars": 32457,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/dry_ice/buffer_a.wgsl",
    "chars": 10840,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/dry_ice/buffer_b.wgsl",
    "chars": 5653,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/dry_ice/buffer_c.wgsl",
    "chars": 13728,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/dry_ice/buffer_d.wgsl",
    "chars": 8141,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/dry_ice/image.wgsl",
    "chars": 18610,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fire/buffer_a.wgsl",
    "chars": 919,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/fire/buffer_b.wgsl",
    "chars": 767,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/fire/buffer_c.wgsl",
    "chars": 767,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/fire/buffer_d.wgsl",
    "chars": 768,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/fire/image.wgsl",
    "chars": 4231,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/fire2/buffer_a.wgsl",
    "chars": 951,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fire2/buffer_b.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fire2/buffer_c.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fire2/buffer_d.wgsl",
    "chars": 800,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fire2/image.wgsl",
    "chars": 8813,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fluid/buffer_a.wgsl",
    "chars": 3799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fluid/buffer_b.wgsl",
    "chars": 806,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fluid/buffer_c.wgsl",
    "chars": 805,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fluid/buffer_d.wgsl",
    "chars": 1499,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/fluid/image.wgsl",
    "chars": 2675,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/image_load.wgsl",
    "chars": 3493,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: i32;\n    iSampleRate: i32;\n\n    iChannelTime: ve"
  },
  {
    "path": "assets/shaders/interactive_fluid_simulation/buffer_a.wgsl",
    "chars": 1140,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/interactive_fluid_simulation/buffer_b.wgsl",
    "chars": 1231,
    "preview": "\nstruct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: i32;\n    iSampleRate: i32;\n\n    iChannelTime: v"
  },
  {
    "path": "assets/shaders/interactive_fluid_simulation/buffer_c.wgsl",
    "chars": 1314,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/interactive_fluid_simulation/buffer_d.wgsl",
    "chars": 2060,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/interactive_fluid_simulation/image.wgsl",
    "chars": 2680,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/liquid/buffer_a.wgsl",
    "chars": 8856,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/liquid/buffer_b.wgsl",
    "chars": 1231,
    "preview": "\nstruct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: i32;\n    iSampleRate: i32;\n\n    iChannelTime: v"
  },
  {
    "path": "assets/shaders/liquid/buffer_c.wgsl",
    "chars": 1314,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/liquid/buffer_d.wgsl",
    "chars": 1363,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/liquid/image.wgsl",
    "chars": 3495,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/liquid_toy/buffer_a.wgsl",
    "chars": 5325,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/liquid_toy/buffer_b.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/liquid_toy/buffer_c.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/liquid_toy/buffer_d.wgsl",
    "chars": 800,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/liquid_toy/image.wgsl",
    "chars": 4694,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/love_and_domination/buffer_a.wgsl",
    "chars": 3190,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/love_and_domination/buffer_b.wgsl",
    "chars": 1743,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/love_and_domination/buffer_c.wgsl",
    "chars": 1854,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/love_and_domination/buffer_d.wgsl",
    "chars": 2173,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/love_and_domination/image.wgsl",
    "chars": 2329,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/minimal/buffer_a.wgsl",
    "chars": 949,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/minimal/buffer_b.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/minimal/buffer_c.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/minimal/buffer_d.wgsl",
    "chars": 800,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/minimal/image.wgsl",
    "chars": 1626,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/mip_fluid/buffer_a.wgsl",
    "chars": 14844,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mip_fluid/buffer_b.wgsl",
    "chars": 7604,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mip_fluid/buffer_c.wgsl",
    "chars": 6975,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mip_fluid/buffer_d.wgsl",
    "chars": 4339,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mip_fluid/image.wgsl",
    "chars": 20311,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mixing_liquid/buffer_a.wgsl",
    "chars": 7046,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mixing_liquid/buffer_b.wgsl",
    "chars": 7284,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mixing_liquid/buffer_c.wgsl",
    "chars": 5518,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mixing_liquid/buffer_d.wgsl",
    "chars": 4477,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/mixing_liquid/image.wgsl",
    "chars": 22301,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/molecular_dynamics/buffer_a.wgsl",
    "chars": 4478,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/molecular_dynamics/buffer_b.wgsl",
    "chars": 5576,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/molecular_dynamics/buffer_c.wgsl",
    "chars": 2653,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/molecular_dynamics/buffer_d.wgsl",
    "chars": 2654,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/molecular_dynamics/image.wgsl",
    "chars": 6344,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/paint/buffer_a.wgsl",
    "chars": 6097,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint/buffer_b.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint/buffer_c.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint/buffer_d.wgsl",
    "chars": 800,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint/common.wgsl",
    "chars": 322,
    "preview": "// unused\n\n#define_import_path bevy_shadertoy_wgsl::assets::shaders::common\n\nstruct CommonUniform {\n    iTime: f32;\n    "
  },
  {
    "path": "assets/shaders/paint/image.wgsl",
    "chars": 1926,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint2/buffer_a.wgsl",
    "chars": 5678,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/paint2/buffer_b.wgsl",
    "chars": 594,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/paint2/buffer_c.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "assets/shaders/paint2/buffer_d.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "assets/shaders/paint2/common.wgsl",
    "chars": 322,
    "preview": "// unused\n\n#define_import_path bevy_shadertoy_wgsl::assets::shaders::common\n\nstruct CommonUniform {\n    iTime: f32;\n    "
  },
  {
    "path": "assets/shaders/paint2/image.wgsl",
    "chars": 1464,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/paint2/image2.wgsl",
    "chars": 1940,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: i32;\n    iSampleRate: i32;\n\n    iChannelTime: ve"
  },
  {
    "path": "assets/shaders/paint_streams/buffer_a.wgsl",
    "chars": 8907,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint_streams/buffer_b.wgsl",
    "chars": 10963,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint_streams/buffer_c.wgsl",
    "chars": 7951,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint_streams/buffer_d.wgsl",
    "chars": 6871,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint_streams/image.wgsl",
    "chars": 26516,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/paint_streams2/buffer_a.wgsl",
    "chars": 8912,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/paint_streams2/buffer_b.wgsl",
    "chars": 10967,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/paint_streams2/buffer_c.wgsl",
    "chars": 7956,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/paint_streams2/buffer_d.wgsl",
    "chars": 6875,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/paint_streams2/image.wgsl",
    "chars": 27172,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n    \n    iMouse: vec4"
  },
  {
    "path": "assets/shaders/preludes/image_prelude",
    "chars": 773,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iResolution: vec"
  },
  {
    "path": "assets/shaders/protean_clouds/buffer_a.wgsl",
    "chars": 873,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/protean_clouds/buffer_b.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/protean_clouds/buffer_c.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/protean_clouds/buffer_d.wgsl",
    "chars": 800,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/protean_clouds/image.wgsl",
    "chars": 6760,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/seascape/buffer_a.wgsl",
    "chars": 950,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/seascape/buffer_b.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/seascape/buffer_c.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/seascape/buffer_d.wgsl",
    "chars": 800,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/seascape/image.wgsl",
    "chars": 8173,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/simpler_particles/buffer_a.wgsl",
    "chars": 8480,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/simpler_particles/buffer_b.wgsl",
    "chars": 7144,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/simpler_particles/buffer_c.wgsl",
    "chars": 7144,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/simpler_particles/buffer_d.wgsl",
    "chars": 7146,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/simpler_particles/image.wgsl",
    "chars": 9864,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/simplest_detailed_fluid/buffer_a.wgsl",
    "chars": 2077,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/simplest_detailed_fluid/buffer_b.wgsl",
    "chars": 1232,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/simplest_detailed_fluid/buffer_c.wgsl",
    "chars": 1315,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/simplest_detailed_fluid/buffer_d.wgsl",
    "chars": 1363,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/simplest_detailed_fluid/image.wgsl",
    "chars": 2160,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "assets/shaders/soul/buffer_a.wgsl",
    "chars": 949,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/soul/buffer_b.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/soul/buffer_c.wgsl",
    "chars": 799,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/soul/buffer_d.wgsl",
    "chars": 800,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/soul/image.wgsl",
    "chars": 12049,
    "preview": "struct CommonUniform {\n    iResolution: vec2<f32>,\n    changed_window_size: f32,\n    padding0: f32,\n    \n    iTime: f32,"
  },
  {
    "path": "assets/shaders/sunset/buffer_a.wgsl",
    "chars": 924,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/sunset/buffer_b.wgsl",
    "chars": 772,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/sunset/buffer_c.wgsl",
    "chars": 772,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/sunset/buffer_d.wgsl",
    "chars": 773,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "assets/shaders/sunset/image.wgsl",
    "chars": 24599,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    \n    iMouse: vec"
  },
  {
    "path": "bin/assets/shaders/image_load.wgsl",
    "chars": 3493,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: i32;\n    iSampleRate: i32;\n\n    iChannelTime: ve"
  },
  {
    "path": "bin/assets/shaders/interactive_fluid_simulation/buffer_a.wgsl",
    "chars": 1140,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/interactive_fluid_simulation/buffer_b.wgsl",
    "chars": 1231,
    "preview": "\nstruct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: i32;\n    iSampleRate: i32;\n\n    iChannelTime: v"
  },
  {
    "path": "bin/assets/shaders/interactive_fluid_simulation/buffer_c.wgsl",
    "chars": 1314,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/interactive_fluid_simulation/buffer_d.wgsl",
    "chars": 2060,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/interactive_fluid_simulation/image.wgsl",
    "chars": 2680,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/liquid/buffer_a.wgsl",
    "chars": 8856,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/liquid/buffer_b.wgsl",
    "chars": 1231,
    "preview": "\nstruct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: i32;\n    iSampleRate: i32;\n\n    iChannelTime: v"
  },
  {
    "path": "bin/assets/shaders/liquid/buffer_c.wgsl",
    "chars": 1314,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/liquid/buffer_d.wgsl",
    "chars": 1363,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/liquid/image.wgsl",
    "chars": 3495,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/minimal/buffer_a.wgsl",
    "chars": 746,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/minimal/buffer_b.wgsl",
    "chars": 594,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/minimal/buffer_c.wgsl",
    "chars": 1315,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/minimal/buffer_d.wgsl",
    "chars": 1363,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/minimal/image.wgsl",
    "chars": 1535,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/mixing_liquid/buffer_a.wgsl",
    "chars": 8639,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/mixing_liquid/buffer_b.wgsl",
    "chars": 8636,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/mixing_liquid/buffer_c.wgsl",
    "chars": 8645,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/mixing_liquid/buffer_d.wgsl",
    "chars": 7689,
    "preview": "\nstruct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f3"
  },
  {
    "path": "bin/assets/shaders/mixing_liquid/image.wgsl",
    "chars": 11125,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint/buffer_a.wgsl",
    "chars": 5930,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint/buffer_b.wgsl",
    "chars": 762,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint/buffer_c.wgsl",
    "chars": 1314,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint/buffer_d.wgsl",
    "chars": 1362,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint/common.wgsl",
    "chars": 322,
    "preview": "// unused\n\n#define_import_path bevy_shadertoy_wgsl::assets::shaders::common\n\nstruct CommonUniform {\n    iTime: f32;\n    "
  },
  {
    "path": "bin/assets/shaders/paint/image.wgsl",
    "chars": 1464,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint2/buffer_a.wgsl",
    "chars": 5678,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint2/buffer_b.wgsl",
    "chars": 594,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint2/buffer_c.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/assets/shaders/paint2/buffer_d.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/assets/shaders/paint2/common.wgsl",
    "chars": 322,
    "preview": "// unused\n\n#define_import_path bevy_shadertoy_wgsl::assets::shaders::common\n\nstruct CommonUniform {\n    iTime: f32;\n    "
  },
  {
    "path": "bin/assets/shaders/paint2/image.wgsl",
    "chars": 1464,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint2/image2.wgsl",
    "chars": 1940,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: i32;\n    iSampleRate: i32;\n\n    iChannelTime: ve"
  },
  {
    "path": "bin/assets/shaders/paint_streams/buffer_a.wgsl",
    "chars": 5973,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint_streams/buffer_b.wgsl",
    "chars": 7380,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint_streams/buffer_c.wgsl",
    "chars": 4809,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/paint_streams/buffer_d.wgsl",
    "chars": 3771,
    "preview": "\nstruct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f3"
  },
  {
    "path": "bin/assets/shaders/paint_streams/image.wgsl",
    "chars": 7870,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/preludes/image_prelude",
    "chars": 773,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iResolution: vec"
  },
  {
    "path": "bin/assets/shaders/simplest_detailed_fluid/buffer_a.wgsl",
    "chars": 2077,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/simplest_detailed_fluid/buffer_b.wgsl",
    "chars": 1232,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/simplest_detailed_fluid/buffer_c.wgsl",
    "chars": 1315,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/simplest_detailed_fluid/buffer_d.wgsl",
    "chars": 1363,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/assets/shaders/simplest_detailed_fluid/image.wgsl",
    "chars": 2160,
    "preview": "struct CommonUniform {\n    iTime: f32;\n    iTimeDelta: f32;\n    iFrame: f32;\n    iSampleRate: f32;\n\n    iMouse: vec4<f32"
  },
  {
    "path": "bin/examples/minimal/buffer_a.wgsl",
    "chars": 270,
    "preview": "\n\n[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n  "
  },
  {
    "path": "bin/examples/minimal/buffer_b.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/examples/minimal/buffer_c.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/examples/minimal/buffer_d.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/examples/minimal/common.wgsl",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "bin/examples/minimal/image.wgsl",
    "chars": 384,
    "preview": "// displays a gray screen by setting the color in buffer_a.wglsl and loading buffer_a\n// here\n\n[[stage(compute), workgro"
  },
  {
    "path": "bin/examples/mixing_liquid/buffer_a.wgsl",
    "chars": 1106,
    "preview": "\n\n[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n  "
  },
  {
    "path": "bin/examples/mixing_liquid/buffer_b.wgsl",
    "chars": 1067,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n// "
  },
  {
    "path": "bin/examples/mixing_liquid/buffer_c.wgsl",
    "chars": 1076,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n// "
  },
  {
    "path": "bin/examples/mixing_liquid/buffer_d.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/examples/mixing_liquid/common.wgsl",
    "chars": 6925,
    "preview": "\n\n\n// struct Particle {\n//      a: vec4<f32>;\n//      b: vec4<f32>;\n// };\n\n\n// fn dum(x: Particle) {\n//     let x2 = Par"
  },
  {
    "path": "bin/examples/mixing_liquid/image.wgsl",
    "chars": 3047,
    "preview": "// displays a gray screen by setting the color in buffer_a.wglsl and loading buffer_a\n// here\n\n// fn even(uv: f32) -> f3"
  },
  {
    "path": "bin/examples/paint/buffer_a.wgsl",
    "chars": 5286,
    "preview": "\ntype float2 = vec2<f32>;\ntype float4 = vec4<f32>;\n\nfn hue(v: f32) -> vec4<f32> { \n    return (vec4<f32>(.6) + vec4<f32>"
  },
  {
    "path": "bin/examples/paint/buffer_b.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/examples/paint/buffer_c.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/examples/paint/buffer_d.wgsl",
    "chars": 118,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n}"
  },
  {
    "path": "bin/examples/paint/common.wgsl",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "bin/examples/paint/image.wgsl",
    "chars": 313,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n    "
  },
  {
    "path": "bin/examples/paint_streams/buffer_a.wgsl",
    "chars": 2322,
    "preview": "\n// don't forget to use a return value when using Reintegration\nfn Reintegration(ch: texture_storage_2d<rgba8unorm, read"
  },
  {
    "path": "bin/examples/paint_streams/buffer_b.wgsl",
    "chars": 3729,
    "preview": "fn border(p: vec2<f32>, R2: vec2<f32>, time: f32) -> f32 {\n\tlet bound: f32 = -sdBox(p - R2 * 0.5, R2 * vec2<f32>(0.5, 0."
  },
  {
    "path": "bin/examples/paint_streams/buffer_c.wgsl",
    "chars": 1158,
    "preview": "[[stage(compute), workgroup_size(8, 8, 1)]]\nfn update([[builtin(global_invocation_id)]] invocation_id: vec3<u32>) {\n\n// "
  }
]

// ... and 129 more files (download for full content)

About this extraction

This page contains the full source code of the eliotbo/bevy_shadertoy_wgsl GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 329 files (32.9 MB), approximately 409.7k tokens, and a symbol index with 169 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!