diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1de2eda --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +rust-gpu/target +rust-gpu/spirt-passes +bevy-app/target +bevy-app/crates/viewer/entry_points.json +bevy-app/crates/viewer/assets/rust-gpu/shader.rust-gpu.msgpack + +*.dot +*.svg + +Dockerfile +run-docker.sh +entrypoint.sh +rust-gpu/entrypoint.sh diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 3485899..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "rust-gpu/crates/rust-gpu-builder"] - path = rust-gpu/crates/rust-gpu-builder - url = https://github.com/Shfty/rust-gpu-builder diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..467a964 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM debian + +RUN apt-get update -y && apt-get install -y build-essential wget curl pkg-config g++ pkg-config libx11-dev libasound2-dev \ + libudev-dev libwayland-dev libxkbcommon-dev mesa-vulkan-drivers wget curl pkg-config \ + && wget https://sh.rustup.rs -O /tmp/rustup.sh && chmod +x /tmp/rustup.sh \ + && sh /tmp/rustup.sh -y --default-toolchain none --no-update-default-toolchain + +RUN /root/.cargo/bin/rustup install nightly-2023-05-27 +RUN /root/.cargo/bin/rustup override set nightly-2023-05-27-x86_64-unknown-linux-gnu +RUN /root/.cargo/bin/rustup component add rust-src rustc-dev llvm-tools-preview + +RUN mkdir /docker-cargo-target +ENV CARGO_TARGET_DIR=/docker-cargo-target +ENV PATH="$PATH:/root/.cargo/bin" +WORKDIR /init-build +ADD . . +RUN bash -c "cd rust-gpu && cargo run --release -- crates/shader ../bevy-app/crates/viewer/assets/rust-gpu/shader.rust-gpu.msgpack" + +WORKDIR /root/mnt/ \ No newline at end of file diff --git a/bevy-app/Cargo.lock b/bevy-app/Cargo.lock index 38f7319..ff498e9 100644 --- a/bevy-app/Cargo.lock +++ b/bevy-app/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.21" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5110f1c78cf582855d895ecd0746b653db010cec6d9f5575293f27934d980a39" +checksum = "80179d7dd5d7e8c285d67c4a1e652972a92de7475beddfb92028c76463b13225" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -20,24 +20,24 @@ checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" [[package]] name = "accesskit" -version = "0.10.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704d532b1cd3d912bb37499c55a81ac748cc1afa737eedd100ba441acdd47d38" +checksum = "76eb1adf08c5bcaa8490b9851fd53cca27fa9880076f178ea9d29f05196728a8" [[package]] name = "accesskit_consumer" -version = "0.14.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba8b23cfca3944012ee2e5c71c02077a400e034c720eed6bd927cb6b4d1fd9" +checksum = "04bb4d9e4772fe0d47df57d0d5dbe5d85dd05e2f37ae1ddb6b105e76be58fb00" dependencies = [ "accesskit", ] [[package]] name = "accesskit_macos" -version = "0.6.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d062544d6cc36f4213323b7cb3a0d74ddff4b0d2311ab5e7596f4278bb2cc9" +checksum = "134d0acf6acb667c89d3332999b1a5df4edbc8d6113910f392ebb73f2b03bb56" dependencies = [ "accesskit", "accesskit_consumer", @@ -47,23 +47,23 @@ dependencies = [ [[package]] name = "accesskit_windows" -version = "0.13.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf5b3c3828397ee832ba4a72fb1a4ace10f781e31885f774cbd531014059115" +checksum = "9eac0a7f2d7cd7a93b938af401d3d8e8b7094217989a7c25c55a953023436e31" dependencies = [ "accesskit", "accesskit_consumer", "arrayvec", "once_cell", "paste", - "windows 0.44.0", + "windows 0.48.0", ] [[package]] name = "accesskit_winit" -version = "0.12.4" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcb615217efc79c4bed3094c4ca76c4bc554751d1da16f3ed4ba0459b1e8f31" +checksum = "825d23acee1bd6d25cbaa3ca6ed6e73faf24122a774ec33d52c5c86c6ab423c0" dependencies = [ "accesskit", "accesskit_macos", @@ -73,9 +73,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -88,32 +88,40 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.6" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ + "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.0.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "alsa" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8512c9117059663fb5606788fbca3619e2a91dac0e3fe516242eab1fa6be5e44" +checksum = "e2562ad8dcf0f789f65c6fdaad8a8a9708ed6b488e649da28c01656ad66b8b47" dependencies = [ "alsa-sys", - "bitflags", + "bitflags 1.3.2", "libc", "nix 0.24.3", ] @@ -130,12 +138,12 @@ dependencies = [ [[package]] name = "android-activity" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c77a0045eda8b888c76ea473c2b0515ba6f471d318f8927c5c72240937035a6" +checksum = "64529721f27c2314ced0890ce45e469574a73e5e6fdd6e9da1860eb29285f5e0" dependencies = [ "android-properties", - "bitflags", + "bitflags 1.3.2", "cc", "jni-sys", "libc", @@ -143,7 +151,7 @@ dependencies = [ "ndk", "ndk-context", "ndk-sys", - "num_enum", + "num_enum 0.6.1", ] [[package]] @@ -154,9 +162,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "android_log-sys" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" +checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" [[package]] name = "android_system_properties" @@ -169,9 +177,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "approx" @@ -184,24 +192,24 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "ash" -version = "0.37.2+1.3.238" +version = "0.37.3+1.3.251" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28bf19c1f0a470be5fbf7522a308a05df06610252c5bcf5143e1b23f629a9a03" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" dependencies = [ - "libloading", + "libloading 0.7.4", ] [[package]] name = "async-channel" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", @@ -210,32 +218,32 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" dependencies = [ "async-lock", "async-task", "concurrent-queue", - "fastrand", + "fastrand 2.0.1", "futures-lite", "slab", ] [[package]] name = "async-lock" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ "event-listener", ] [[package]] name = "async-task" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" [[package]] name = "autocfg" @@ -245,15 +253,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.6.2", + "miniz_oxide", "object", "rustc-demangle", ] @@ -264,10 +272,17 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" + [[package]] name = "bevy" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c6d3ec4f89e85294dc97334c5b271ddc301fdf67ac9bb994fe44d9273e6ed7" dependencies = [ "bevy_internal", ] @@ -275,7 +290,6 @@ dependencies = [ [[package]] name = "bevy-rust-gpu" version = "0.5.0" -source = "git+https://github.com/bevy-rust-gpu/bevy-rust-gpu?tag=v0.5.0#d3cabc453298647dc2f73008618ca57747f9ef9c" dependencies = [ "bevy", "bevy_common_assets", @@ -287,8 +301,9 @@ dependencies = [ [[package]] name = "bevy_a11y" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "132c9e35a77c5395951f6d25fa2c52ee92296353426df4f961e60f3ff47e2e42" dependencies = [ "accesskit", "bevy_app", @@ -298,8 +313,9 @@ dependencies = [ [[package]] name = "bevy_animation" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f44eae3f1c35a87e38ad146f72317f19ce7616dad8bbdfb88ee752c1282d28c5" dependencies = [ "bevy_app", "bevy_asset", @@ -308,6 +324,7 @@ dependencies = [ "bevy_hierarchy", "bevy_math", "bevy_reflect", + "bevy_render", "bevy_time", "bevy_transform", "bevy_utils", @@ -315,12 +332,14 @@ dependencies = [ [[package]] name = "bevy_app" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f557a7d59e1e16892d7544fc37316506ee598cb5310ef0365125a30783c11531" dependencies = [ "bevy_derive", "bevy_ecs", "bevy_reflect", + "bevy_tasks", "bevy_utils", "downcast-rs", "wasm-bindgen", @@ -329,10 +348,12 @@ dependencies = [ [[package]] name = "bevy_asset" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9714af523da4cdf58c42a317e5ed40349708ad954a18533991fd64c8ae0a6f68" dependencies = [ "anyhow", + "async-channel", "bevy_app", "bevy_diagnostic", "bevy_ecs", @@ -343,7 +364,7 @@ dependencies = [ "bevy_winit", "crossbeam-channel", "downcast-rs", - "fastrand", + "fastrand 1.9.0", "js-sys", "notify", "parking_lot", @@ -356,12 +377,14 @@ dependencies = [ [[package]] name = "bevy_audio" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de308bd63a2f7a0b77ffeb7cf00cc185ec01393c5db2091fe03964f97152749" dependencies = [ "anyhow", "bevy_app", "bevy_asset", + "bevy_derive", "bevy_ecs", "bevy_math", "bevy_reflect", @@ -374,20 +397,22 @@ dependencies = [ [[package]] name = "bevy_common_assets" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291aeda7599bf12869ff225c3702a8b8810c7e5d40655271d0b38442253ca03d" +checksum = "a0e5659f20aeaa1703e76d87c62d66f92aaa56e431fbed71bb38345b576aa6f0" dependencies = [ "anyhow", "bevy", "rmp-serde", "serde", + "serde_json", ] [[package]] name = "bevy_core" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d5272321be5fcf5ce2fb16023bc825bb10dfcb71611117296537181ce950f48" dependencies = [ "bevy_app", "bevy_ecs", @@ -400,11 +425,13 @@ dependencies = [ [[package]] name = "bevy_core_pipeline" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67382fa9c96ce4f4e5833ed7cedd9886844a8f3284b4a717bd4ac738dcdea0c3" dependencies = [ "bevy_app", "bevy_asset", + "bevy_core", "bevy_derive", "bevy_ecs", "bevy_math", @@ -412,25 +439,27 @@ dependencies = [ "bevy_render", "bevy_transform", "bevy_utils", - "bitflags", + "bitflags 2.4.1", "radsort", "serde", ] [[package]] name = "bevy_derive" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44e4e2784a81430199e4157e02903a987a32127c773985506f020e7d501b62e" dependencies = [ "bevy_macro_utils", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "bevy_diagnostic" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6babb230dc383c98fdfc9603e3a7a2a49e1e2879dbe8291059ef37dca897932e" dependencies = [ "bevy_app", "bevy_core", @@ -443,8 +472,9 @@ dependencies = [ [[package]] name = "bevy_ecs" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266144b36df7e834d5198049e037ecdf2a2310a76ce39ed937d1b0a6a2c4e8c6" dependencies = [ "async-channel", "bevy_ecs_macros", @@ -457,24 +487,27 @@ dependencies = [ "fixedbitset", "rustc-hash", "serde", + "thiserror", "thread_local", ] [[package]] name = "bevy_ecs_macros" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7157a9c3be038d5008ee3f114feb6cf6b39c1d3d32ee21a7cacb8f81fccdfa80" dependencies = [ "bevy_macro_utils", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "bevy_encase_derive" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0ac0f55ad6bca1be7b0f35bbd5fc95ed3d31e4e9db158fee8e5327f59006001" dependencies = [ "bevy_macro_utils", "encase_derive_impl", @@ -482,23 +515,48 @@ dependencies = [ [[package]] name = "bevy_gilrs" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65f4d79c55829f8016014593a42453f61a564ffb06ef79460d25696ccdfac67b" dependencies = [ "bevy_app", "bevy_ecs", "bevy_input", + "bevy_log", + "bevy_time", "bevy_utils", "gilrs", + "thiserror", +] + +[[package]] +name = "bevy_gizmos" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e286a3e7276431963f4aa29165ea5429fa7dbbc6d5c5ba0c531e7dd44ecc88a2" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_core", + "bevy_core_pipeline", + "bevy_ecs", + "bevy_math", + "bevy_pbr", + "bevy_reflect", + "bevy_render", + "bevy_sprite", + "bevy_transform", + "bevy_utils", ] [[package]] name = "bevy_gltf" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07494a733dca032e71a20f4b1f423de765da49cbff34406ae6cd813f9b50c41" dependencies = [ "anyhow", - "base64", + "base64 0.13.1", "bevy_animation", "bevy_app", "bevy_asset", @@ -517,13 +575,16 @@ dependencies = [ "bevy_utils", "gltf", "percent-encoding", + "serde", + "serde_json", "thiserror", ] [[package]] name = "bevy_hierarchy" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "103f8f58416ac6799b8c7f0b418f1fac9eba44fa924df3b0e16b09256b897e3d" dependencies = [ "bevy_app", "bevy_core", @@ -536,8 +597,9 @@ dependencies = [ [[package]] name = "bevy_input" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbd935401101ac8003f3c3aea70788c65ad03f7a32716a10608bedda7a648bc" dependencies = [ "bevy_app", "bevy_ecs", @@ -549,8 +611,9 @@ dependencies = [ [[package]] name = "bevy_internal" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0e35a9b2bd29aa784b3cc416bcbf2a298f69f00ca51fd042ea39d9af7fad37e" dependencies = [ "bevy_a11y", "bevy_animation", @@ -563,6 +626,7 @@ dependencies = [ "bevy_diagnostic", "bevy_ecs", "bevy_gilrs", + "bevy_gizmos", "bevy_gltf", "bevy_hierarchy", "bevy_input", @@ -586,8 +650,9 @@ dependencies = [ [[package]] name = "bevy_log" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07dcc615ff4f617b06c3f9522fca3c55d56f9644db293318f8ab68fcdea5d4fe" dependencies = [ "android_log-sys", "bevy_app", @@ -601,35 +666,40 @@ dependencies = [ [[package]] name = "bevy_macro_utils" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ddc18d489b4e57832d4958cde7cd2f349f0ad91e5892ac9e2f2ee16546b981" dependencies = [ "quote", - "syn 1.0.109", + "rustc-hash", + "syn 2.0.38", "toml_edit", ] [[package]] name = "bevy_math" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78286a81fead796dc4b45ab14f4f02fe29a94423d3587bcfef872b2a8e0a474b" dependencies = [ - "glam", + "glam 0.24.2", "serde", ] [[package]] name = "bevy_mikktspace" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cfc2a21ea47970a9b1f0f4735af3256a8f204815bd756110051d10f9d909497" dependencies = [ - "glam", + "glam 0.24.2", ] [[package]] name = "bevy_pbr" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63ca796a619e61cd43a0a3b11fde54644f7f0732a1fba1eef5d406248c6eba85" dependencies = [ "bevy_app", "bevy_asset", @@ -642,20 +712,23 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags", + "bitflags 2.4.1", "bytemuck", + "naga_oil", "radsort", ] [[package]] name = "bevy_ptr" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c7586401a46f7d8e436028225c1df5288f2e0082d066b247a82466fea155c6" [[package]] name = "bevy_reflect" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0778197a1eb3e095a71417c74b7152ede02975cdc95b5ea4ddc5251ed00a2eb5" dependencies = [ "bevy_math", "bevy_ptr", @@ -663,31 +736,34 @@ dependencies = [ "bevy_utils", "downcast-rs", "erased-serde", - "glam", + "glam 0.24.2", "once_cell", "parking_lot", "serde", "smallvec", + "smol_str", "thiserror", ] [[package]] name = "bevy_reflect_derive" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342a4b2d09db22c48607d23ad59a056aff1ee004549050a51d490d375ba29528" dependencies = [ "bevy_macro_utils", "bit-set", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", "uuid", ] [[package]] name = "bevy_render" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39df4824b760928c27afc7b00fb649c7a63c9d76661ab014ff5c86537ee906cb" dependencies = [ "anyhow", "async-channel", @@ -708,16 +784,18 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags", + "bitflags 2.4.1", + "bytemuck", "codespan-reporting", "downcast-rs", "encase", "futures-lite", "hexasphere", "image", + "js-sys", "ktx2", "naga", - "once_cell", + "naga_oil", "parking_lot", "regex", "ruzstd", @@ -725,25 +803,29 @@ dependencies = [ "smallvec", "thiserror", "thread_local", + "wasm-bindgen", + "web-sys", "wgpu", "wgpu-hal", ] [[package]] name = "bevy_render_macros" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd08c740aac73363e32fb45af869b10cec65bcb76fe3e6cd0f8f7eebf4c36c9" dependencies = [ "bevy_macro_utils", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "bevy_scene" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd47e1263506153bef3a8be97fe2d856f206d315668c4f97510ca6cc181d9681" dependencies = [ "anyhow", "bevy_app", @@ -763,8 +845,9 @@ dependencies = [ [[package]] name = "bevy_sprite" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a8ca824fad75c6ef74cfbbba0a4ce3ccc435fa23d6bf3f003f260548813397" dependencies = [ "bevy_app", "bevy_asset", @@ -777,7 +860,7 @@ dependencies = [ "bevy_render", "bevy_transform", "bevy_utils", - "bitflags", + "bitflags 2.4.1", "bytemuck", "fixedbitset", "guillotiere", @@ -787,22 +870,23 @@ dependencies = [ [[package]] name = "bevy_tasks" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c73bbb847c83990d3927005090df52f8ac49332e1643d2ad9aac3cd2974e66bf" dependencies = [ "async-channel", "async-executor", "async-task", "concurrent-queue", "futures-lite", - "once_cell", "wasm-bindgen-futures", ] [[package]] name = "bevy_text" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692288ab7b0a9f8b38058964c52789fc6bcb63703b23de51cce90ec41bfca355" dependencies = [ "ab_glyph", "anyhow", @@ -823,8 +907,9 @@ dependencies = [ [[package]] name = "bevy_time" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d58d6dbae9c8225d8c0e0f04d2c5dbb71d22adc01ecd5ab3cebc364139e4a6d" dependencies = [ "bevy_app", "bevy_ecs", @@ -836,8 +921,9 @@ dependencies = [ [[package]] name = "bevy_transform" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b0ac0149a57cd846cb357a35fc99286f9848e53d4481954608ac9552ed2d4" dependencies = [ "bevy_app", "bevy_ecs", @@ -848,8 +934,9 @@ dependencies = [ [[package]] name = "bevy_ui" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b6d295a755e5b79e869a09e087029d72974562a521ec7ccfba7141fa948a32" dependencies = [ "bevy_a11y", "bevy_app", @@ -877,13 +964,14 @@ dependencies = [ [[package]] name = "bevy_utils" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d9484e32434ea84dc548cff246ce0c6f756c1336f5ea03f24ac120a48595c7" dependencies = [ "ahash", "bevy_utils_proc_macros", "getrandom", - "hashbrown", + "hashbrown 0.14.2", "instant", "petgraph", "thiserror", @@ -893,18 +981,20 @@ dependencies = [ [[package]] name = "bevy_utils_proc_macros" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5391b242c36f556db01d5891444730c83aa9dd648b6a8fd2b755d22cb3bddb57" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "bevy_window" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd584c0da7c4ada6557b09f57f30fb7cff21ccedc641473fc391574b4c9b7944" dependencies = [ "bevy_app", "bevy_ecs", @@ -917,8 +1007,9 @@ dependencies = [ [[package]] name = "bevy_winit" -version = "0.10.0" -source = "git+https://github.com/bevy-rust-gpu/bevy?branch=bevy-rust-gpu-dev#788c90070d7c3ba0901c96cb3a73f4c43b2422ef" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdc044abdb95790c20053e6326760f0a2985f0dcd78613d397bf35f16039d53" dependencies = [ "accesskit_winit", "approx", @@ -929,10 +1020,10 @@ dependencies = [ "bevy_hierarchy", "bevy_input", "bevy_math", + "bevy_tasks", "bevy_utils", "bevy_window", "crossbeam-channel", - "once_cell", "raw-window-handle", "wasm-bindgen", "web-sys", @@ -941,11 +1032,11 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.64.0" +version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" dependencies = [ - "bitflags", + "bitflags 2.4.1", "cexpr", "clang-sys", "lazy_static", @@ -956,7 +1047,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -980,6 +1071,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +dependencies = [ + "serde", +] + [[package]] name = "block" version = "0.1.6" @@ -1007,49 +1107,50 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.38", ] [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -1087,7 +1188,7 @@ checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" dependencies = [ "glob", "libc", - "libloading", + "libloading 0.7.4", ] [[package]] @@ -1124,9 +1225,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] @@ -1143,9 +1244,24 @@ dependencies = [ [[package]] name = "const_panic" -version = "0.2.7" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b" + +[[package]] +name = "const_soft_float" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58baae561b85ca19b3122a9ddd35c8ec40c3bcd14fe89921824eae73f7baffbf" +checksum = "87ca1caa64ef4ed453e68bb3db612e51cf1b2f5b871337f0fcab1c8f87cc3dff" + +[[package]] +name = "constgebra" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd23e864550e6dafc1e41ac78ce4f1ccddc8672b40c403524a04ff3f0518420" +dependencies = [ + "const_soft_float", +] [[package]] name = "convert_case" @@ -1162,16 +1278,10 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ - "core-foundation-sys 0.8.4", + "core-foundation-sys", "libc", ] -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" - [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -1184,7 +1294,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-graphics-types", "foreign-types", @@ -1193,32 +1303,31 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", - "foreign-types", "libc", ] [[package]] name = "coreaudio-rs" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb17e2d1795b1996419648915df94bc7103c28f7b48062d7acf4652fc371b2ff" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" dependencies = [ - "bitflags", - "core-foundation-sys 0.6.2", + "bitflags 1.3.2", + "core-foundation-sys", "coreaudio-sys", ] [[package]] name = "coreaudio-sys" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f034b2258e6c4ade2f73bf87b21047567fb913ee9550837c2316d139b0262b24" +checksum = "d8478e5bdad14dce236b9898ea002eabfa87cbe14f0aa538dbe3b6a4bec4332d" dependencies = [ "bindgen", ] @@ -1230,7 +1339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d959d90e938c5493000514b446987c07aed46c668faaa7d34d6c7a67b1a578c" dependencies = [ "alsa", - "core-foundation-sys 0.8.4", + "core-foundation-sys", "coreaudio-rs", "dasp_sample", "jni 0.19.0", @@ -1269,9 +1378,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] @@ -1282,8 +1391,8 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8f0de2f5a8e7bd4a9eec0e3c781992a4ce1724f68aec7d7a3715344de8b39da" dependencies = [ - "bitflags", - "libloading", + "bitflags 1.3.2", + "libloading 0.7.4", "winapi", ] @@ -1293,6 +1402,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + [[package]] name = "dispatch" version = "0.2.0" @@ -1307,41 +1422,47 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "encase" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6591f13a63571c4821802eb5b10fd1155b1290bce87086440003841c8c3909b" +checksum = "8fce2eeef77fd4a293a54b62aa00ac9daebfbcda4bf8998c5a815635b004aa1c" dependencies = [ "const_panic", "encase_derive", - "glam", + "glam 0.24.2", "thiserror", ] [[package]] name = "encase_derive" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1da6deed1f8b6f5909616ffa695f63a5de54d6a0f084fa715c70c8ed3abac9" +checksum = "0e520cde08cbf4f7cc097f61573ec06ce467019803de8ae82fb2823fa1554a0e" dependencies = [ "encase_derive_impl", ] [[package]] name = "encase_derive_impl" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae489d58959f3c4cdd1250866a05acfb341469affe4fced71aff3ba228be1693" +checksum = "3fe2568f851fd6144a45fa91cfed8fe5ca8fc0b56ba6797bfc1ed2771b90e37c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "erased-serde" -version = "0.3.25" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" dependencies = [ "serde", ] @@ -1370,24 +1491,30 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" dependencies = [ "simd-adler32", ] [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "windows-sys 0.48.0", ] @@ -1399,12 +1526,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -1439,15 +1566,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -1455,7 +1582,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -1464,20 +1591,11 @@ dependencies = [ "waker-fn", ] -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", @@ -1501,9 +1619,9 @@ dependencies = [ [[package]] name = "gilrs-core" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd745b0cb1a207756e8fabacf5623066ad6aa543ea0be4bab34e897e6bbe24f9" +checksum = "5ccc99e9b8d63ffcaa334c4babfa31f46e156618a11f63efb6e8e6bcb37b830d" dependencies = [ "core-foundation", "io-kit-sys", @@ -1511,25 +1629,40 @@ dependencies = [ "libc", "libudev-sys", "log", - "nix 0.26.2", + "nix 0.26.4", "uuid", "vec_map", "wasm-bindgen", "web-sys", - "windows 0.48.0", + "windows 0.51.1", ] [[package]] name = "gimli" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "glam" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774" +dependencies = [ + "num-traits", +] [[package]] name = "glam" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" + +[[package]] +name = "glam" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" dependencies = [ "bytemuck", "serde", @@ -1543,9 +1676,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "glow" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e007a07a24de5ecae94160f141029e9a347282cfe25d1d58d85d845cf3130f1" +checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728" dependencies = [ "js-sys", "slotmap", @@ -1555,33 +1688,32 @@ dependencies = [ [[package]] name = "gltf" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd7703af6975def3b32573c60aaa5ebfebfab5d879da1e1315d87155ba57bcd" +checksum = "ad2dcfb6dd7a66f9eb3d181a29dcfb22d146b0bcdc2e1ed1713cbf03939a88ea" dependencies = [ "byteorder", "gltf-json", "lazy_static", - "urlencoding", ] [[package]] name = "gltf-derive" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b33dbe598480111e3b2e5a1e9a7e52ad5df0f836e04b8c80fc96f52a9c9f2e" +checksum = "f2cbcea5dd47e7ad4e9ee6f040384fcd7204bbf671aa4f9e7ca7dfc9bfa1de20" dependencies = [ "inflections", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "gltf-json" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5511a759d99beeeef064bd6f81e207c77e3a3431c7499d7590929e35de371f31" +checksum = "7d5b810806b78dde4b71a95cc0e6fdcab34c4c617da3574df166f9987be97d03" dependencies = [ "gltf-derive", "serde", @@ -1602,11 +1734,11 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" +checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gpu-alloc-types", ] @@ -1616,7 +1748,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1634,24 +1766,30 @@ dependencies = [ [[package]] name = "gpu-descriptor" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" +checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" dependencies = [ - "bitflags", + "bitflags 2.4.1", "gpu-descriptor-types", - "hashbrown", + "hashbrown 0.14.2", ] [[package]] name = "gpu-descriptor-types" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" +checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" dependencies = [ - "bitflags", + "bitflags 2.4.1", ] +[[package]] +name = "grid" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c" + [[package]] name = "guillotiere" version = "0.6.2" @@ -1667,21 +1805,28 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" dependencies = [ "ahash", + "allocator-api2", "serde", ] [[package]] name = "hassle-rs" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90601c6189668c7345fc53842cb3f3a3d872203d523be1b3cb44a36a3e62fb85" +checksum = "1397650ee315e8891a0df210707f0fc61771b0cc518c3023896064c5407cb3b0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "com-rs", "libc", - "libloading", + "libloading 0.7.4", "thiserror", "widestring", "winapi", @@ -1689,12 +1834,12 @@ dependencies = [ [[package]] name = "hexasphere" -version = "8.1.0" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd41d443f978bfa380a6dad58b62a08c43bcb960631f13e9d015b911eaf73588" +checksum = "7cb3df16a7bcb1b5bc092abd55e14f77ca70aea14445026e264586fc62889a10" dependencies = [ - "glam", - "once_cell", + "constgebra", + "glam 0.24.2", ] [[package]] @@ -1705,9 +1850,9 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "image" -version = "0.24.6" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" dependencies = [ "bytemuck", "byteorder", @@ -1724,7 +1869,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.2", ] [[package]] @@ -1739,7 +1894,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" dependencies = [ - "bitflags", + "bitflags 1.3.2", "inotify-sys", "libc", ] @@ -1771,15 +1926,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2d4429acc1deff0fbdece0325b4997bdb02b2c245ab7023fd5deca0f6348de" dependencies = [ - "core-foundation-sys 0.8.4", + "core-foundation-sys", "mach2", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jni" @@ -1817,18 +1972,18 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -1840,15 +1995,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", - "libloading", + "libloading 0.7.4", "pkg-config", ] [[package]] name = "kqueue" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" dependencies = [ "kqueue-sys", "libc", @@ -1856,11 +2011,11 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", ] @@ -1870,7 +2025,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87d65e08a9ec02e409d27a0139eaa6b9756b4d81fe7cde71f6941a83730ce838" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1898,9 +2053,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.142" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libloading" @@ -1912,6 +2067,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall 0.4.1", +] + [[package]] name = "libudev-sys" version = "0.1.4" @@ -1924,9 +2106,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1934,12 +2116,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "mach2" @@ -1965,14 +2144,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "metal" @@ -1980,7 +2159,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "core-graphics-types", "foreign-types", @@ -1994,15 +2173,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -2015,26 +2185,27 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "naga" -version = "0.11.0" -source = "git+https://github.com/bevy-rust-gpu/naga?branch=spv-in-break-if-v0.11.0#6aea73fa48853fd25eb07405dedd00b81709f376" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbcc2e0513220fd2b598e6068608d4462db20322c0e77e47f6f488dfcfc279cb" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "codespan-reporting", "hexf-parse", - "indexmap", + "indexmap 1.9.3", "log", "num-traits", "petgraph", @@ -2046,16 +2217,36 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "naga_oil" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be942a5c21c58b9b0bf4d9b99db3634ddb7a916f8e1d1d0b71820cc4150e56b" +dependencies = [ + "bit-set", + "codespan-reporting", + "data-encoding", + "indexmap 1.9.3", + "naga", + "once_cell", + "regex", + "regex-syntax 0.6.29", + "rustc-hash", + "thiserror", + "tracing", + "unicode-ident", +] + [[package]] name = "ndk" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "jni-sys", "ndk-sys", - "num_enum", + "num_enum 0.5.11", "raw-window-handle", "thiserror", ] @@ -2081,21 +2272,20 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", ] [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", - "static_assertions", ] [[package]] @@ -2110,20 +2300,21 @@ dependencies = [ [[package]] name = "notify" -version = "5.1.0" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags", + "bitflags 2.4.1", "crossbeam-channel", "filetime", "fsevent-sys", "inotify", "kqueue", "libc", + "log", "mio", "walkdir", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -2179,11 +2370,12 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2192,7 +2384,16 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", ] [[package]] @@ -2207,6 +2408,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "objc" version = "0.2.7" @@ -2254,9 +2467,9 @@ dependencies = [ [[package]] name = "object" -version = "0.30.3" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -2295,17 +2508,17 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "orbclient" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "221d488cd70617f1bd599ed8ceb659df2147d9393717954d82a0f5e8032a6ab1" +checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "redox_syscall 0.3.5", + "libredox", ] [[package]] @@ -2316,18 +2529,18 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owned_ttf_parser" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4" +checksum = "d4586edfe4c648c71797a74c84bacb32b52b212eff5dfe2bb9f2c599844023e7" dependencies = [ "ttf-parser", ] [[package]] name = "parking" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -2341,22 +2554,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.4.1", "smallvec", - "windows-sys 0.45.0", + "windows-targets 0.48.5", ] [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "peeking_take_while" @@ -2366,43 +2579,43 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 2.1.0", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "png" -version = "0.17.8" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -2426,24 +2639,24 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" +checksum = "f89dff0959d98c9758c88826cc002e2c3d0b9dfac4139711d1f30de442f1139b" [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2474,31 +2687,32 @@ checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.8.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.1", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -2510,6 +2724,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -2518,21 +2743,21 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "renderdoc-sys" -version = "0.7.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" +checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" [[package]] name = "rmp" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" dependencies = [ "byteorder", "num-traits", @@ -2541,9 +2766,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b13be192e0220b8afb7222aa5813cb62cc269ebb5cac346ca6487681d2913e" +checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" dependencies = [ "byteorder", "rmp", @@ -2552,9 +2777,9 @@ dependencies = [ [[package]] name = "rodio" -version = "0.17.1" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf1d4dea18dff2e9eb6dca123724f8b60ef44ad74a9ad283cdfe025df7e73fa" +checksum = "3b1bb7b48ee48471f55da122c0044fcc7600cfcc85db88240b89cb832935e611" dependencies = [ "cpal", "lewton", @@ -2562,13 +2787,14 @@ dependencies = [ [[package]] name = "ron" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ - "base64", - "bitflags", + "base64 0.21.5", + "bitflags 2.4.1", "serde", + "serde_derive", ] [[package]] @@ -2576,8 +2802,9 @@ name = "rust-gpu-bridge" version = "0.5.0" source = "git+https://github.com/bevy-rust-gpu/rust-gpu-bridge?tag=v0.5.0#da8b209ed46f87b1e56ec3fd2b8b02d49b0de0ce" dependencies = [ - "glam", + "glam 0.23.0", "rust-gpu-bridge-macros", + "spirv-std", ] [[package]] @@ -2587,22 +2814,21 @@ source = "git+https://github.com/bevy-rust-gpu/rust-gpu-bridge-macros?tag=v0.2.0 dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.38", ] [[package]] name = "rust-gpu-builder-shared" version = "0.2.0" -source = "git+https://github.com/bevy-rust-gpu/rust-gpu-builder-shared?tag=v0.2.0#0994e71ae2dc7b595833343ca3751b5175111fe4" dependencies = [ "bevy", + "bevy_reflect", "serde", ] [[package]] name = "rust-gpu-sdf" version = "0.1.0" -source = "git+https://github.com/bevy-rust-gpu/rust-gpu-sdf#8a7a38584f4caef54a4cdd8cfb1a7164f8b5e32e" dependencies = [ "bevy", "rust-gpu-bridge", @@ -2623,19 +2849,20 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "ruzstd" -version = "0.2.4" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cada0ef59efa6a5f4dc5e491f93d9f31e3fc7758df421ff1de8a706338e1100" +checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" dependencies = [ "byteorder", + "thiserror-core", "twox-hash", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -2648,35 +2875,35 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.38", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -2685,30 +2912,30 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "shlex" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "simd-adler32" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -2724,9 +2951,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +dependencies = [ + "serde", +] + +[[package]] +name = "smol_str" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" dependencies = [ "serde", ] @@ -2737,10 +2973,41 @@ version = "0.2.0+1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" dependencies = [ - "bitflags", + "bitflags 1.3.2", + "num-traits", +] + +[[package]] +name = "spirv-std" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3197bd4c021c2dfc0f9dfb356312c8f7842d972d5545c308ad86422c2e2d3e66" +dependencies = [ + "bitflags 1.3.2", + "glam 0.22.0", "num-traits", + "spirv-std-macros", + "spirv-std-types", ] +[[package]] +name = "spirv-std-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaffad626ab9d3ac61c4b74b5d51cb52f1939a8041d7ac09ec828eb4ad44d72" +dependencies = [ + "proc-macro2", + "quote", + "spirv-std-types", + "syn 1.0.109", +] + +[[package]] +name = "spirv-std-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab83875e851bc803c687024d2d950730f350c0073714b95b3a6b1d22e9eac42a" + [[package]] name = "static_assertions" version = "1.1.0" @@ -2766,9 +3033,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -2777,12 +3044,12 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.28.4" +version = "0.29.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2f3ca6693feb29a89724516f016488e9aafc7f37264f898593ee4b942f31b" +checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5" dependencies = [ "cfg-if", - "core-foundation-sys 0.8.4", + "core-foundation-sys", "libc", "ntapi", "once_cell", @@ -2791,42 +3058,63 @@ dependencies = [ [[package]] name = "taffy" -version = "0.3.12" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3540ec65df399929a04a485feb50144475735920cc47eaf8eba09c70b1df4055" +checksum = "3c2287b6d7f721ada4cddf61ade5e760b2c6207df041cac9bfaa192897362fd3" dependencies = [ "arrayvec", + "grid", "num-traits", "slotmap", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] +[[package]] +name = "thiserror-core" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" +dependencies = [ + "thiserror-core-impl", +] + +[[package]] +name = "thiserror-core-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.38", ] [[package]] @@ -2856,28 +3144,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.1.0", "toml_datetime", "winnow", ] [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2885,20 +3172,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.38", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -2906,12 +3193,12 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -2946,9 +3233,9 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" [[package]] name = "twox-hash" @@ -2976,14 +3263,14 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.38", ] [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" @@ -2993,9 +3280,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -3003,17 +3290,11 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "urlencoding" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" - [[package]] name = "uuid" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "getrandom", "serde", @@ -3043,21 +3324,22 @@ version = "0.1.0" dependencies = [ "bevy", "bevy-rust-gpu", + "rmp-serde", "rust-gpu-bridge", "rust-gpu-sdf", ] [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -3071,9 +3353,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3081,24 +3363,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -3108,9 +3390,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3118,22 +3400,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "wayland-scanner" @@ -3148,9 +3430,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -3158,9 +3440,9 @@ dependencies = [ [[package]] name = "wgpu" -version = "0.15.1" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d745a1b6d91d85c33defbb29f0eee0450e1d2614d987e14bf6baf26009d132d7" +checksum = "480c965c9306872eb6255fa55e4b4953be55a8b64d57e61d7ff840d3dcc051cd" dependencies = [ "arrayvec", "cfg-if", @@ -3182,20 +3464,20 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.15.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7131408d940e335792645a98f03639573b0480e9e2e7cddbbab74f7c6d9f3fff" +checksum = "8f478237b4bf0d5b70a39898a66fa67ca3a007d79f2520485b8b0c3dfc46f8c2" dependencies = [ "arrayvec", "bit-vec", - "bitflags", + "bitflags 2.4.1", "codespan-reporting", - "fxhash", "log", "naga", "parking_lot", "profiling", "raw-window-handle", + "rustc-hash", "smallvec", "thiserror", "web-sys", @@ -3205,20 +3487,19 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "0.15.4" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdcf61a283adc744bb5453dd88ea91f3f86d5ca6b027661c6c73c7734ae0288b" +checksum = "1ecb3258078e936deee14fd4e0febe1cfe9bbb5ffef165cb60218d2ee5eb4448" dependencies = [ "android_system_properties", "arrayvec", "ash", "bit-set", - "bitflags", + "bitflags 2.4.1", "block", "core-graphics-types", "d3d12", "foreign-types", - "fxhash", "glow", "gpu-alloc", "gpu-allocator", @@ -3227,7 +3508,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading", + "libloading 0.8.1", "log", "metal", "naga", @@ -3237,6 +3518,7 @@ dependencies = [ "range-alloc", "raw-window-handle", "renderdoc-sys", + "rustc-hash", "smallvec", "thiserror", "wasm-bindgen", @@ -3247,20 +3529,20 @@ dependencies = [ [[package]] name = "wgpu-types" -version = "0.15.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32444e121b0bd00cb02c0de32fde457a9491bd44e03e7a5db6df9b1da2f6f110" +checksum = "d0c153280bb108c2979eb5c7391cb18c56642dd3c072e55f52065e13e2a1252a" dependencies = [ - "bitflags", + "bitflags 2.4.1", "js-sys", "web-sys", ] [[package]] name = "widestring" -version = "0.5.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "winapi" @@ -3280,9 +3562,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -3299,8 +3581,6 @@ version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" dependencies = [ - "windows-implement", - "windows-interface", "windows-targets 0.42.2", ] @@ -3319,25 +3599,35 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", + "windows-implement", + "windows-interface", + "windows-targets 0.48.5", ] [[package]] -name = "windows-implement" -version = "0.44.0" +name = "windows" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce87ca8e3417b02dc2a8a22769306658670ec92d78f1bd420d6310a67c245c6" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "windows-core", + "windows-targets 0.48.5", ] [[package]] -name = "windows-interface" -version = "0.44.0" +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-implement" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "853f69a591ecd4f810d29f17e902d40e349fb05b0b11fff63b08b826bfe39c7f" +checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c" dependencies = [ "proc-macro2", "quote", @@ -3345,18 +3635,14 @@ dependencies = [ ] [[package]] -name = "windows-sys" -version = "0.42.0" +name = "windows-interface" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -3374,7 +3660,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.5", ] [[package]] @@ -3394,17 +3680,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -3415,9 +3701,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -3427,9 +3713,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -3439,9 +3725,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -3451,9 +3737,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -3463,9 +3749,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -3475,9 +3761,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -3487,18 +3773,18 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winit" -version = "0.28.3" +version = "0.28.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f504e8c117b9015f618774f8d58cd4781f5a479bc41079c064f974cbb253874" +checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94" dependencies = [ "android-activity", - "bitflags", + "bitflags 1.3.2", "cfg_aliases", "core-foundation", "core-graphics", @@ -3523,9 +3809,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.4.4" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5617da7e1f97bf363947d767b91aaf3c2bbc19db7fda9c65af1278713d58e0a2" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -3549,6 +3835,31 @@ checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" [[package]] name = "xml-rs" -version = "0.8.4" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" + +[[package]] +name = "zerocopy" +version = "0.7.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[patch.unused]] +name = "naga" +version = "0.11.0" +source = "git+https://github.com/bevy-rust-gpu/naga?branch=spv-in-break-if-v0.11.0#001a42b96d800897b70bba9bb5e9691d6c7058b6" diff --git a/bevy-app/Cargo.toml b/bevy-app/Cargo.toml index a0431b8..f5acafd 100644 --- a/bevy-app/Cargo.toml +++ b/bevy-app/Cargo.toml @@ -9,7 +9,7 @@ default-members = ["crates/viewer"] naga = { git = "https://github.com/bevy-rust-gpu/naga", branch = "spv-in-break-if-v0.11.0" } #bevy = { path = "../../../bevy" } -bevy = { git = "https://github.com/bevy-rust-gpu/bevy", branch = "bevy-rust-gpu-dev" } +# bevy = { version="0.11.3" } #[patch."https://github.com/bevy-rust-gpu/bevy-rust-gpu"] #bevy-rust-gpu = { path = "../../crates/bevy-rust-gpu" } diff --git a/bevy-app/crates/bevy_rust_gpu b/bevy-app/crates/bevy_rust_gpu new file mode 160000 index 0000000..0423a2b --- /dev/null +++ b/bevy-app/crates/bevy_rust_gpu @@ -0,0 +1 @@ +Subproject commit 0423a2bb16e61459f35014cb202e78b530f17e93 diff --git a/bevy-app/crates/rust-gpu-sdf/.github/workflows/publish-rust-docs.yml b/bevy-app/crates/rust-gpu-sdf/.github/workflows/publish-rust-docs.yml new file mode 100644 index 0000000..df0d494 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/.github/workflows/publish-rust-docs.yml @@ -0,0 +1,11 @@ +name: Publish Rust Docs +run-name: ${{ github.actor }} is publishing documentation 🚀 +on: + push: + +permissions: + contents: write + +jobs: + publish-cargo-doc: + uses: Shfty/github-actions/.github/workflows/publish-rust-docs.yml@master diff --git a/bevy-app/crates/rust-gpu-sdf/.github/workflows/rust.yml b/bevy-app/crates/rust-gpu-sdf/.github/workflows/rust.yml new file mode 100644 index 0000000..4e57226 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/.github/workflows/rust.yml @@ -0,0 +1,24 @@ +name: Rust + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + # - name: Install dependencies + # run: sudo apt install librust-alsa-sys-dev libudev-dev + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/bevy-app/crates/rust-gpu-sdf/.gitignore b/bevy-app/crates/rust-gpu-sdf/.gitignore new file mode 100644 index 0000000..c184a93 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/.gitignore @@ -0,0 +1,3 @@ +.cargo +target +Cargo.lock diff --git a/bevy-app/crates/rust-gpu-sdf/Cargo.toml b/bevy-app/crates/rust-gpu-sdf/Cargo.toml new file mode 100644 index 0000000..9c9eee7 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "rust-gpu-sdf" +version = "0.1.0" +edition = "2021" + +[features] +default = [] +glam = ["rust-gpu-bridge/glam"] +spirv-std = ["rust-gpu-bridge/spirv-std"] +bevy = ["dep:bevy"] + + +[dependencies] +rust-gpu-bridge = { git = "https://github.com/bevy-rust-gpu/rust-gpu-bridge", tag = "v0.5.0" } +type-fields = { git = "https://github.com/bevy-rust-gpu/type-fields", tag = "prerelease" } + +bevy = { version = "0.11.*", optional = true } diff --git a/bevy-app/crates/rust-gpu-sdf/LICENSE-APACHE b/bevy-app/crates/rust-gpu-sdf/LICENSE-APACHE new file mode 100644 index 0000000..d9a10c0 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/bevy-app/crates/rust-gpu-sdf/LICENSE-MIT b/bevy-app/crates/rust-gpu-sdf/LICENSE-MIT new file mode 100644 index 0000000..9cf1062 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/LICENSE-MIT @@ -0,0 +1,19 @@ +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. diff --git a/bevy-app/crates/rust-gpu-sdf/README.md b/bevy-app/crates/rust-gpu-sdf/README.md new file mode 100644 index 0000000..40a8a86 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/README.md @@ -0,0 +1,9 @@ +
+ +# rust-gpu-sdf + +[![Documentation](https://img.shields.io/badge/docs-API-blue)](https://bevy-rust-gpu.github.io/rust-gpu-sdf/rust_gpu_sdf/) + +A no-std signed distance field library. +Usable on the CPU in regular Rust, or on the GPU by way of `rust-gpu`. +
diff --git a/bevy-app/crates/rust-gpu-sdf/rust-toolchain.toml b/bevy-app/crates/rust-gpu-sdf/rust-toolchain.toml new file mode 100644 index 0000000..cb3562f --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/rust-toolchain.toml @@ -0,0 +1,7 @@ +[toolchain] +channel = "nightly-2023-03-04" +components = ["rust-src", "rustc-dev", "llvm-tools-preview"] +# commit_hash = 44cfafe2fafe816395d3acc434663a45d5178c41 + +# Whenever changing the nightly channel, update the commit hash above, and make +# sure to change REQUIRED_TOOLCHAIN in crates/rustc_codegen_spirv/src/build.rs also. diff --git a/bevy-app/crates/rust-gpu-sdf/src/attribute/bound_error.rs b/bevy-app/crates/rust-gpu-sdf/src/attribute/bound_error.rs new file mode 100644 index 0000000..1936dc8 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/attribute/bound_error.rs @@ -0,0 +1,96 @@ +//! Error term quantifying the bound-ness of a distance function. +//! +//! A distance function can be considered a correct distance field +//! if its derivative is uniformly 1. +//! If this does not hold, it is instead considered a distance bound. +//! +//! In practical terms, this equates to any stretching, squashing, +//! incorrectly-sharp edges, or other discontinuities in an evaluated field. +//! +//! This can only be tested for, but the accuracy of the test is determined +//! by the accuracy of the field's derivative function. +//! +//! This creates issues when testing fields whose derivatives +//! are calculated using local differencing, as the process +//! innately smooths off discontinuities relative to its epsilon factor. +//! +//! To avoid this, we combine the gradient at a given point in the field +//! with a distance evaluation to produce a support vector; +//! i.e. the vector from the evaluated position +//! to the nearest point on the implicit surface. +//! +//! In a correct distance field, summing the evaluated position +//! and support vector will result in a new position whose +//! evaluated distance is almost zero w.r.t. floating-point precision. +//! +//! This is still subject to its own error term relative to the accuracy of the +//! gradient function, but is more robust than the derivative approach, +//! and able to catch more common bound cases. + +use core::{ + marker::PhantomData, + ops::{Add, Mul}, +}; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrSupport, AttrTangent, + AttrUv, Attribute, Distance, Field, FieldOperator, Operator, Support, SupportFunction, + }, +}; + +/// Bound error term +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd)] +#[repr(C)] +pub struct ErrorTerm { + pub support: Support, + pub error: Distance, +} + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AttrBoundError { + _phantom: PhantomData, +} + +impl Attribute for AttrBoundError +where + Dim: Default, +{ + type Input = Position; + type Output = ErrorTerm; +} + +/// Bound error wrapper operator +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(C)] +pub struct BoundErrorOp; + +impl FieldOperator> for BoundErrorOp +where + Sdf: Field> + Field>, + Input: Default + Clone + Add + Mul, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as Attribute>::Output { + let mut out = ErrorTerm::default(); + + let support = Field::>::field(sdf, p); + let sv = support.support_vector(); + out.support = support; + out.error = Field::>::field(sdf, &((*p).clone() + sv)); + out + } +} + +impl_passthrough_op_1!(BoundErrorOp, AttrDistance, Dim); +impl_passthrough_op_1!(BoundErrorOp, AttrNormal, Dim); +impl_passthrough_op_1!(BoundErrorOp, AttrTangent, Dim); +impl_passthrough_op_1!(BoundErrorOp, AttrUv, Dim); +impl_passthrough_op_1!(BoundErrorOp, AttrColor, Dim); + +/// Bound error wrapper +pub type BoundError = Operator>; diff --git a/bevy-app/crates/rust-gpu-sdf/src/attribute/color.rs b/bevy-app/crates/rust-gpu-sdf/src/attribute/color.rs new file mode 100644 index 0000000..4810754 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/attribute/color.rs @@ -0,0 +1,49 @@ +use core::marker::PhantomData; + +use rust_gpu_bridge::glam::Vec4; + +use crate::{ + impl_newtype, + prelude::{items::position::Position, Field}, +}; + +use super::Attribute; + +#[repr(C)] +pub struct AttrColor { + _phantom: PhantomData, +} + +impl Default for AttrColor { + fn default() -> Self { + AttrColor { + _phantom: Default::default(), + } + } +} + +impl Clone for AttrColor { + fn clone(&self) -> Self { + AttrColor { + _phantom: self._phantom.clone(), + } + } +} + +impl Copy for AttrColor {} + +impl Attribute for AttrColor { + type Input = Position; + type Output = Color; +} + +impl Field> for Vec4 { + fn field(&self, _: &Position) -> Color { + Color(*self) + } +} + +impl_newtype!( + #[derive(Default, Copy, Clone, PartialEq)] + pub struct Color(Vec4); +); diff --git a/bevy-app/crates/rust-gpu-sdf/src/attribute/distance.rs b/bevy-app/crates/rust-gpu-sdf/src/attribute/distance.rs new file mode 100644 index 0000000..a5fc054 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/attribute/distance.rs @@ -0,0 +1,47 @@ +use core::marker::PhantomData; + +use crate::{ + impl_newtype, + prelude::{items::position::Position, Field}, +}; + +use super::Attribute; + +#[repr(C)] +pub struct AttrDistance { + _phantom: PhantomData, +} + +impl Default for AttrDistance { + fn default() -> Self { + AttrDistance { + _phantom: Default::default(), + } + } +} + +impl Clone for AttrDistance { + fn clone(&self) -> Self { + AttrDistance { + _phantom: self._phantom.clone(), + } + } +} + +impl Copy for AttrDistance {} + +impl Attribute for AttrDistance { + type Input = Position; + type Output = Distance; +} + +impl Field> for f32 { + fn field(&self, _: &Position) -> Distance { + Distance(*self) + } +} + +impl_newtype!( + #[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd)] + pub struct Distance(f32); +); diff --git a/bevy-app/crates/rust-gpu-sdf/src/attribute/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/attribute/mod.rs new file mode 100644 index 0000000..52e0ccb --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/attribute/mod.rs @@ -0,0 +1,91 @@ +//! Attributes whose corresponding data type can be evaluated via field function + +use type_fields::t_funk::{hlist::ToTList, tlist::ToHList}; + +pub trait Attribute { + type Input; + type Output; +} + +/// An attribute whose input satisfies a given lifetime. +pub trait AttributeRef<'a>: Attribute { + type InputRef: 'a; +} + +impl<'a, T> AttributeRef<'a> for T +where + T: Attribute, + T::Input: 'a, +{ + type InputRef = T::Input; +} + +/// A list of `Attribute`s +/// +/// Extension trait of Attribute; +/// applied over `(LHS, RHS)` and `(LHS, ())` to recurse +/// through arbitrarly-long cons list impls. +pub trait Attributes { + type Input; + type Output; +} + +impl Attributes for (LHS, RHS) +where + LHS: Attribute, + RHS: Attributes, +{ + type Input = LHS::Input; + type Output = (LHS::Output, RHS::Output); +} + +impl Attributes for (LHS, ()) +where + LHS: Attribute, +{ + type Input = LHS::Input; + type Output = (LHS::Output, ()); +} + +/// A list of `Attribute`s whose input satisfies a given lifetime. +pub trait AttributesRef<'a>: Attributes { + type InputRef: 'a; +} + +impl<'a, T> AttributesRef<'a> for T +where + T: Attributes, + T::Input: 'a, +{ + type InputRef = T::Input; +} + +/// A cons list of `Attribute`s +pub trait ConsAttributes<'a>: ToHList { + type ConsAttr: Attributes; + type AttrInput: 'a; + type AttrOutput: ToTList; + type UnconsOutput; +} + +impl<'a, T> ConsAttributes<'a> for T +where + T: ToHList, + T::HList: AttributesRef<'a>, + ::Output: ToTList, +{ + type ConsAttr = T::HList; + type AttrInput = >::InputRef; + type AttrOutput = ::Output; + type UnconsOutput = <::Output as ToTList>::TList; +} + +pub mod color; +pub mod distance; +pub mod normal; +pub mod tangent; +pub mod uv; + +pub mod support_function; + +pub mod bound_error; diff --git a/bevy-app/crates/rust-gpu-sdf/src/attribute/normal.rs b/bevy-app/crates/rust-gpu-sdf/src/attribute/normal.rs new file mode 100644 index 0000000..7e15d3e --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/attribute/normal.rs @@ -0,0 +1,55 @@ +use core::marker::PhantomData; + +use rust_gpu_bridge::glam::{Vec2, Vec3}; + +use crate::{ + default, impl_newtype, + prelude::{items::position::Position, Field}, +}; + +use super::Attribute; + +#[repr(C)] +pub struct AttrNormal(PhantomData); + +impl Default for AttrNormal { + fn default() -> Self { + AttrNormal(default()) + } +} + +impl Clone for AttrNormal { + fn clone(&self) -> Self { + AttrNormal(self.0.clone()) + } +} + +impl Copy for AttrNormal {} + +impl Attribute for AttrNormal { + type Input = Position; + type Output = Normal; +} + +impl Field> for f32 { + fn field(&self, _: &Position) -> Normal { + Normal(*self) + } +} + +impl Field> for Vec2 { + fn field(&self, _: &Position) -> Normal { + Normal(*self) + } +} + +impl Field> for Vec3 { + fn field(&self, _: &Position) -> Normal { + Normal(*self) + } +} + +impl_newtype!( + #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct Normal(Dim); +); diff --git a/bevy-app/crates/rust-gpu-sdf/src/attribute/support_function.rs b/bevy-app/crates/rust-gpu-sdf/src/attribute/support_function.rs new file mode 100644 index 0000000..eb95dc5 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/attribute/support_function.rs @@ -0,0 +1,85 @@ +//! Vector to nearest surface + +use core::{marker::PhantomData, ops::Mul}; + +use rust_gpu_bridge::IsNormalized; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, + Attribute, Distance, Field, FieldOperator, Operator, + }, +}; + +/// Support function attribute marker +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd)] +#[repr(C)] +pub struct Support { + pub normal: Dim, + pub distance: Distance, +} + +impl Support { + pub fn support_vector(&self) -> Dim + where + Dim: Clone + Mul, + { + self.normal.clone() * -*self.distance + } +} + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AttrSupport { + _phantom: PhantomData, +} + +impl Attribute for AttrSupport +where + Dim: Default, +{ + type Input = Position; + type Output = Support; +} + +/// Support function wrapper operator +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(C)] +pub struct SupportFunctionOp; + +impl FieldOperator> for SupportFunctionOp +where + Sdf: Field> + Field>, + Dim: Default + Clone + Mul + IsNormalized, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> as Attribute>::Output { + let mut out = Support::default(); + + // Calculate normal + let n = (*Field::>::field(sdf, p)).clone(); + + // Skip samples where normal is not valid + // (ex. the center of a sphere) + if !n.clone().is_normalized() { + return out; + } + + // Calculate distance + let d = Field::>::field(sdf, p); + + // Write into output + out.normal = n; + out.distance = d; + + out + } +} + +impl_passthrough_op_1!(SupportFunctionOp, AttrDistance, Dim); +impl_passthrough_op_1!(SupportFunctionOp, AttrNormal, Dim); +impl_passthrough_op_1!(SupportFunctionOp, AttrTangent, Dim); +impl_passthrough_op_1!(SupportFunctionOp, AttrUv, Dim); +impl_passthrough_op_1!(SupportFunctionOp, AttrColor, Dim); + +/// Support function wrapper +pub type SupportFunction = Operator; diff --git a/bevy-app/crates/rust-gpu-sdf/src/attribute/tangent.rs b/bevy-app/crates/rust-gpu-sdf/src/attribute/tangent.rs new file mode 100644 index 0000000..1ad6279 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/attribute/tangent.rs @@ -0,0 +1,55 @@ +use core::marker::PhantomData; + +use rust_gpu_bridge::glam::{Vec2, Vec3}; + +use crate::{ + default, impl_newtype, + prelude::{items::position::Position, Field}, +}; + +use super::Attribute; + +#[repr(C)] +pub struct AttrTangent(PhantomData); + +impl Default for AttrTangent { + fn default() -> Self { + AttrTangent(default()) + } +} + +impl Clone for AttrTangent { + fn clone(&self) -> Self { + AttrTangent(self.0.clone()) + } +} + +impl Copy for AttrTangent {} + +impl Attribute for AttrTangent { + type Input = Position; + type Output = Tangent; +} + +impl Field> for f32 { + fn field(&self, _: &Position) -> Tangent { + Tangent(*self) + } +} + +impl Field> for Vec2 { + fn field(&self, _: &Position) -> Tangent { + Tangent(*self) + } +} + +impl Field> for Vec3 { + fn field(&self, _: &Position) -> Tangent { + Tangent(*self) + } +} + +impl_newtype!( + #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct Tangent(Dim); +); diff --git a/bevy-app/crates/rust-gpu-sdf/src/attribute/uv.rs b/bevy-app/crates/rust-gpu-sdf/src/attribute/uv.rs new file mode 100644 index 0000000..9863983 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/attribute/uv.rs @@ -0,0 +1,49 @@ +use core::marker::PhantomData; + +use rust_gpu_bridge::glam::Vec2; + +use crate::{ + impl_newtype, + prelude::{items::position::Position, Field}, +}; + +use super::Attribute; + +#[repr(C)] +pub struct AttrUv { + _phantom: PhantomData, +} + +impl Default for AttrUv { + fn default() -> Self { + AttrUv { + _phantom: Default::default(), + } + } +} + +impl Clone for AttrUv { + fn clone(&self) -> Self { + AttrUv { + _phantom: self._phantom.clone(), + } + } +} + +impl Copy for AttrUv {} + +impl Attribute for AttrUv { + type Input = Position; + type Output = Uv; +} + +impl Field> for Vec2 { + fn field(&self, _: &Position) -> Uv { + Uv(*self) + } +} + +impl_newtype!( + #[derive(Default, Copy, Clone, PartialEq)] + pub struct Uv(Vec2); +); diff --git a/bevy-app/crates/rust-gpu-sdf/src/bound_tester.rs b/bevy-app/crates/rust-gpu-sdf/src/bound_tester.rs new file mode 100644 index 0000000..3503bae --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/bound_tester.rs @@ -0,0 +1,135 @@ +//! Utility type for testing the bound error term of a distance function + +use core::ops::RangeInclusive; + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Abs, +}; + +use crate::prelude::{ + default, AttrBoundError, AttrDistance, AttrNormal, BoundError, Field, + FieldAttribute, SupportFunction, +}; + +/// Asserts that the provided distance function is a field rather than a bound +#[derive(Debug, Clone, PartialEq)] +#[repr(C)] +pub struct BoundTester { + pub sdf: Sdf, + pub samples: RangeInclusive, + pub step: f32, + pub epsilon: f32, +} + +impl Default for BoundTester +where + Sdf: Default, +{ + fn default() -> Self { + BoundTester { + sdf: default(), + samples: -20..=20, + step: 10.0 / 20.0, + epsilon: 0.00001, + } + } +} + +impl BoundTester +where + Sdf: Field> + Field> + Default + Clone + 'static, +{ + pub fn is_field_2d(self) -> bool { + !self.is_bound_2d() + } + + pub fn is_bound_2d(self) -> bool { + // Iterate over a regular grid + for x in self.samples.clone() { + for y in self.samples.clone() { + // Compose sample coordinate + let pos = Vec2::new(x as f32, y as f32) * self.step; + + // Calculate error term + let error_term = BoundError { + target: SupportFunction { + target: self.sdf.clone(), + ..default() + }, + ..Default::default() + } + .field_attribute::>(&pos.into()); + + // Skip samples with no valid support function + if error_term.support.normal == Vec2::ZERO { + continue; + } + + assert!( + error_term.error.abs() <= self.epsilon, + "Encountered error {:?} at point {:}, {:} with {:?} and normal {:}, {}", + error_term.error, + pos.x, + pos.y, + error_term.support.distance, + error_term.support.normal.x, + error_term.support.normal.y + ); + } + } + + false + } +} + +impl BoundTester +where + Sdf: Field> + Field> + Default + Clone + 'static, +{ + pub fn is_field_3d(self) -> bool { + !self.is_bound_3d() + } + + pub fn is_bound_3d(self) -> bool { + // Iterate over a regular grid + for x in self.samples.clone() { + for y in self.samples.clone() { + for z in self.samples.clone() { + // Compose sample coordinate + let pos = Vec3::new(x as f32, y as f32, z as f32) * self.step; + + // Calculate error term + let error_term = BoundError { + target: SupportFunction { + target: self.sdf.clone(), + ..default() + }, + ..Default::default() + } + .field_attribute::>(&pos.into()); + + // Skip samples with no valid support function + if error_term.support.normal == Vec3::ZERO { + continue; + } + + assert!( + error_term.error.abs() <= self.epsilon, + "Encountered error {:?} at point {:}, {:}, {:} with {:?} and normal {:}, {:}, {:}", + error_term.error, + pos.x, + pos.y, + pos.z, + error_term.support.distance, + error_term.support.normal.x, + error_term.support.normal.y, + error_term.support.normal.z + ); + } + } + } + + false + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/items/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/context/items/mod.rs new file mode 100644 index 0000000..082bd2d --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/items/mod.rs @@ -0,0 +1,2 @@ +pub mod position; + diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/items/position.rs b/bevy-app/crates/rust-gpu-sdf/src/context/items/position.rs new file mode 100644 index 0000000..0694e00 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/items/position.rs @@ -0,0 +1,6 @@ +use crate::impl_newtype; + +impl_newtype!( + #[derive(Debug, Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)] + pub struct Position(Dim); +); diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/context/mod.rs new file mode 100644 index 0000000..7d48d80 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/mod.rs @@ -0,0 +1,13 @@ +//! Type-level data access + +pub mod traits; +pub mod items; + +/// Marker denoting the left side of a cons cell +pub enum Car {} + +/// Marker denoting the right side of a cons cell +pub enum Cdr {} + +/// Marker denoting self +pub enum This {} diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/traits/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/context/traits/mod.rs new file mode 100644 index 0000000..18e315b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/traits/mod.rs @@ -0,0 +1,6 @@ +pub mod register; +pub mod register_item; +pub mod register_items; +pub mod register_items_uncons; +pub mod registers; +pub mod registers_uncons; diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/traits/register.rs b/bevy-app/crates/rust-gpu-sdf/src/context/traits/register.rs new file mode 100644 index 0000000..51150cc --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/traits/register.rs @@ -0,0 +1,50 @@ +use crate::prelude::{Car, Cdr, This}; + +/// Fetch `T` by type from a cons list. +pub trait Register: Sized { + fn register(self) -> T; +} + +impl Register<(Cdr, Inner), T> for (LHS, RHS) +where + RHS: Register, +{ + fn register(self) -> T { + self.1.register() + } +} + +impl Register<(Car, ()), LHS> for (LHS, RHS) { + fn register(self) -> LHS { + self.0 + } +} + +impl<'a, T> Register for T +where + T: 'a, +{ + fn register(self) -> T { + self + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use type_fields::t_funk::tlist::ToHList; + + use crate::prelude::Register; + + #[test] + pub fn test_context() { + let context = (1, 2.0, "three").to_hlist(); + + let _int = 0usize.register(); + let _float = 0.0.register(); + let _string = "hello".register(); + + let _int = Register::<_, usize>::register(context); + let _float = Register::<_, f32>::register(context); + let _string = Register::<_, &str>::register(context); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_item.rs b/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_item.rs new file mode 100644 index 0000000..983d345 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_item.rs @@ -0,0 +1,39 @@ +use crate::prelude::Register; + +/// Fetch `T` by type from a cons list. +/// +/// Moves `T` into the function position. +pub trait RegisterItem: Sized { + fn item(self) -> Item + where + Self: Register; +} + +impl RegisterItem for T { + fn item(self) -> Item + where + T: Register, + { + self.register() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use type_fields::t_funk::tlist::ToHList; + + use crate::prelude::RegisterItem; + + #[test] + pub fn test_context_item() { + let context = (1, 2.0, "three").to_hlist(); + + let _int = 0usize.item::(); + let _float = 0.0.item::(); + let _string = "hello".item::<&str>(); + + let _int = context.item::(); + let _float = context.item::(); + let _string = context.item::<&str>(); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_items.rs b/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_items.rs new file mode 100644 index 0000000..e643cda --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_items.rs @@ -0,0 +1,44 @@ +use type_fields::t_funk::{hlist::ToTList, tlist::ToHList}; + +use crate::prelude::Registers; + +/// Fetch multiple items by type from a cons list. +/// +/// Moves `Items` into the function position. +pub trait RegisterItems: Sized { + fn context_items(self) -> >::Type + where + Items: ToHList, + Self: Registers, + >::Type: ToTList; +} + +impl RegisterItems for T { + fn context_items(self) -> >::Type + where + Items: ToHList, + Self: Registers, + { + self.registers() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use type_fields::t_funk::tlist::ToHList; + + use crate::prelude::RegisterItems; + + #[test] + pub fn test_context_items() { + let context = (1, 2.0, "three").to_hlist(); + + let (_int, ()) = 0usize.context_items::<(usize,)>(); + let (_float, ()) = 0.0.context_items::<(f32,)>(); + let (_string, ()) = "hello".context_items::<(&str,)>(); + + let (_string, ()) = context.context_items::<(&str,)>(); + let (_string, (_float, ())) = context.context_items::<(&str, f32)>(); + let (_string, (_float, (_int, ()))) = context.context_items::<(&str, f32, usize)>(); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_items_uncons.rs b/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_items_uncons.rs new file mode 100644 index 0000000..bb38ea8 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/traits/register_items_uncons.rs @@ -0,0 +1,51 @@ +use type_fields::t_funk::{hlist::ToTList, tlist::ToHList}; + +use crate::prelude::Registers; + +use super::registers_uncons::RegistersUncons; + +/// Fetch multiple items by type from a cons list and uncons them before return. +/// +/// Moves `Items` into the function position. +pub trait RegisterItemsUncons: Sized { + fn context_items_uncons( + self, + ) -> <>::Type as ToTList>::TList + where + Self: Registers, + Items: ToHList, + Self::Type: ToTList; +} + +impl RegisterItemsUncons for T { + fn context_items_uncons( + self, + ) -> <>::Type as ToTList>::TList + where + Self: Registers, + Items: ToHList, + >::Type: ToTList, + { + RegistersUncons::::registers_uncons(self) + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use type_fields::t_funk::tlist::ToHList; + + use crate::prelude::RegisterItemsUncons; + + #[test] + pub fn test_context_items() { + let context = (1, 2.0, "three").to_hlist(); + + let (_int,) = 0usize.context_items_uncons::<(usize,)>(); + let (_float,) = 0.0.context_items_uncons::<(f32,)>(); + let (_string,) = "hello".context_items_uncons::<(&str,)>(); + + let (_string,) = context.context_items_uncons::<(&str,)>(); + let (_string, _float) = context.context_items_uncons::<(&str, f32)>(); + let (_string, _float, _int) = context.context_items_uncons::<(&str, f32, usize)>(); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/traits/registers.rs b/bevy-app/crates/rust-gpu-sdf/src/context/traits/registers.rs new file mode 100644 index 0000000..d3cc24c --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/traits/registers.rs @@ -0,0 +1,60 @@ +use crate::prelude::{Register, This}; + +/// Fetch multiple items by type from a cons list. +pub trait Registers { + type Type; + + fn registers(self) -> Self::Type; +} + +impl Registers<(LState, RState), (LHS, RHS)> for T +where + T: Clone + Register + Registers, +{ + type Type = (LHS, >::Type); + + fn registers(self) -> Self::Type { + (self.clone().register(), self.registers()) + } +} + +impl Registers for T { + type Type = T; + + fn registers(self) -> Self::Type { + self + } +} + +impl Registers<(), ()> for T { + type Type = (); + + fn registers(self) -> Self::Type { + () + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use type_fields::t_funk::tlist::ToHList; + + use crate::prelude::Registers; + + #[test] + pub fn test_contexts() { + let context = (1, 2.0, "three").to_hlist(); + + /* + let _int = 0usize.contexts(); + let _float = 0.0.contexts(); + let _string = "hello".contexts(); + */ + + let _int = Registers::<_, (usize, ())>::registers(0usize); + let _float = Registers::<_, (f32, ())>::registers(0.0); + let _string = Registers::<_, (&str, ())>::registers("hello"); + + let (_string, (_float, (_int, ()))) = + Registers::<_, (&str, (f32, (usize, ())))>::registers(context); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/context/traits/registers_uncons.rs b/bevy-app/crates/rust-gpu-sdf/src/context/traits/registers_uncons.rs new file mode 100644 index 0000000..62e9123 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/context/traits/registers_uncons.rs @@ -0,0 +1,42 @@ +use type_fields::t_funk::{hlist::ToTList, tlist::ToHList}; + +use crate::prelude::Registers; + +/// Fetch multiple items by type from a cons list and uncons them before return. +pub trait RegistersUncons: Registers +where + Items: ToHList, +{ + fn registers_uncons(self) -> ::TList; +} + +impl RegistersUncons for T +where + Self: Registers, + Items: ToHList, +{ + fn registers_uncons(self) -> ::TList { + self.registers().to_tlist() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use type_fields::t_funk::tlist::ToHList; + + use crate::prelude::RegistersUncons; + + #[test] + pub fn test_contexts_uncons() { + let context = (1, 2.0, "three").to_hlist(); + + let (_int,) = RegistersUncons::<_, (usize,)>::registers_uncons(0usize); + let (_float,) = RegistersUncons::<_, (f32,)>::registers_uncons(0.0); + let (_string,) = RegistersUncons::<_, (&str,)>::registers_uncons("hello"); + + let (_string,) = RegistersUncons::<_, (&str,)>::registers_uncons(context); + let (_string, _float) = RegistersUncons::<_, (&str, f32)>::registers_uncons(context); + let (_string, _float, _int) = + RegistersUncons::<_, (&str, f32, usize)>::registers_uncons(context); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/extrude.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/extrude.rs new file mode 100644 index 0000000..924788c --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/extrude.rs @@ -0,0 +1,155 @@ +//! Extrude a 2D distance field into 3D. + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3, Vec3Swizzles}, + Abs, Sign, +}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrUv, Field, FieldOperator, Normal, + Operator, +}; + +/// Extrude a 2D distance field into 3D. +#[derive(Default, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ExtrudeOp { + pub axis: Vec3, + pub depth: f32, +} + +impl FieldOperator> for ExtrudeOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + input: &Position, + ) -> as crate::prelude::Attribute>::Output { + let d = *sdf.field(&input.x.into()); + let w = Vec2::new(d, input.y.abs() - self.depth); + (w.x.max(w.y).min(0.0) + w.max(Vec2::ZERO).length()).into() + } +} + +impl FieldOperator> for ExtrudeOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + input: &Position, + ) -> as crate::prelude::Attribute>::Output { + let d = *sdf.field(&input.truncate().into()); + let w = Vec2::new(d, input.z.abs() - self.depth); + (w.x.max(w.y).min(0.0) + w.max(Vec2::ZERO).length()).into() + } +} + +impl FieldOperator> for ExtrudeOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Normal { + let d = *sdf.field(&p.x.into()); + let w = Vec2::new(d, p.y.abs() - self.depth); + let s = p.y.sign(); + + let g = w.x.max(w.y); + let q = w.max(Vec2::ZERO); + let l = q.length(); + + let m = s + * (if g > 0.0 { + q / l + } else { + if w.x > w.y { + Vec2::X + } else { + Vec2::Y + } + }); + + m.into() + } +} + +impl FieldOperator> for ExtrudeOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Normal { + let d = sdf.field(&p.xy().into()); + if p.z.abs() > p.xy().length() * 0.5 { + Vec3::new(0.0, 0.0, p.z.sign()) + } else { + d.extend(0.0) + } + .normalize() + .into() + } +} + +impl FieldOperator> for ExtrudeOp +where + Sdf: crate::prelude::Field>, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + (*sdf.field(&p.x.into()) + Vec2::new(0.0, p.y.abs())).into() + } +} + +impl FieldOperator> for ExtrudeOp +where + Sdf: crate::prelude::Field>, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + (*sdf.field(&p.truncate().into()) + Vec2::new(0.0, p.z.abs())).into() + } +} + +/// Extrude a 2D distance field into 3D. +pub type Extrude = Operator; + +impl Extrude { + pub fn axis(&mut self) -> &mut Vec3 { + self.op().axis() + } + + pub fn depth(&mut self) -> &mut f32 { + self.op().depth() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{ + prelude::{BoundTester, Circle, Extrude, Point, Sphere}, + test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_extrude_2d() { + assert!(BoundTester::>::default().is_field_2d()); + } + + #[test] + fn test_extrude_3d() { + assert!(BoundTester::>::default().is_field_3d()); + } + + test_op_attrs_2d!(Extrude::); + test_op_attrs_3d!(Extrude::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/extrude_interior.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/extrude_interior.rs new file mode 100644 index 0000000..b2c8e54 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/extrude_interior.rs @@ -0,0 +1,108 @@ +//! Extrude a 2D distance field into 3D, using its interior distance to determine depth. + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Abs, +}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, Field, FieldOperator, AttrNormal, Operator, AttrUv, +}; + +/// Extrude a 2D distance field into 3D, using its interior distance to determine depth. +/// NOTE: The present implementation is a bound, not a field +/// TODO: Refactor to use a 1D FieldFunction to describe Z curvature +#[derive(Default, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ExtrudeInteriorOp { + pub depth: f32, +} + +impl FieldOperator> for ExtrudeInteriorOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + let d = *sdf.field(&p.x.into()); + let w = Vec2::new(d, p.y.abs() + d.min(0.0) * self.depth); + let exterior = w.max(Vec2::ZERO).length(); + let interior = w.x.max(w.y).min(0.0); + (interior + exterior).into() + } +} + +impl FieldOperator> for ExtrudeInteriorOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + let d = *sdf.field(&p.truncate().into()); + let w = Vec2::new(d, p.z.abs() + d.min(0.0) * self.depth); + let exterior = w.max(Vec2::ZERO).length(); + let interior = w.x.max(w.y).min(0.0); + (interior + exterior).into() + } +} + +impl FieldOperator> for ExtrudeInteriorOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> as crate::prelude::Attribute>::Output { + let d = *sdf.field(&p.x.into()); + Vec2::new(d, 1.0).normalize().into() + } +} + +impl FieldOperator> for ExtrudeInteriorOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> as crate::prelude::Attribute>::Output { + let d = *sdf.field(&p.truncate().into()); + d.extend(1.0).normalize().into() + } +} + +impl FieldOperator> for ExtrudeInteriorOp +where + Sdf: crate::prelude::Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> as crate::prelude::Attribute>::Output { + sdf.field(&p.truncate().into()) + } +} + +/// Uniformly scale a distance field. +pub type ExtrudeInterior = Operator; + +impl ExtrudeInterior { + pub fn depth(&mut self) -> &mut f32 { + self.op().depth() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{ + prelude::{BoundTester, Circle, ExtrudeInterior, Point}, + test_op_attrs_3d, + }; + + #[test] + fn test_extrude_interior() { + assert!(BoundTester::>::default().is_field_3d()); + } + + test_op_attrs_3d!(ExtrudeInterior::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/mod.rs new file mode 100644 index 0000000..6db79e0 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/mod.rs @@ -0,0 +1,5 @@ +pub mod slice; +pub mod extrude; +pub mod extrude_interior; +pub mod sweep; + diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/slice.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/slice.rs new file mode 100644 index 0000000..5a9e363 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/slice.rs @@ -0,0 +1,91 @@ +//! Take a 2D slice of a 3D field + +use rust_gpu_bridge::glam::{Vec2, Vec3}; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, + Distance, Field, FieldOperator, Normal, Operator, Tangent, Uv, + }, +}; + +/// Take a 2D slice of a 3D field +#[derive(Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SliceOp { + pub u: Vec3, + pub v: Vec3, +} + +impl Default for SliceOp { + fn default() -> Self { + SliceOp { + u: Vec3::X, + v: Vec3::Y, + } + } +} + +impl FieldOperator> for SliceOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Distance { + let u = self.u * p.x; + let v = self.v * p.y; + sdf.field(&(u + v).into()).into() + } +} + +impl FieldOperator> for SliceOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Normal { + let u = self.u * p.x; + let v = self.v * p.y; + let n = sdf.field(&(u + v).into()); + Vec2::new(n.dot(self.u), n.dot(self.v)).normalize().into() + } +} + +impl FieldOperator> for SliceOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Tangent { + let u = self.u * p.x; + let v = self.v * p.y; + let n = sdf.field(&(u + v).into()); + Vec2::new(n.dot(self.u), n.dot(self.v)).normalize().into() + } +} + +impl FieldOperator> for SliceOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Uv { + let u = self.u * p.x; + let v = self.v * p.y; + sdf.field(&(u + v).into()) + } +} + +impl_passthrough_op_1!(SliceOp, AttrColor, Dim); + +/// Take a 2D slice of a 3D field +pub type Slice = Operator; + +impl Slice { + pub fn u(&mut self) -> &mut Vec3 { + &mut self.op().u + } + + pub fn v(&mut self) -> &mut Vec3 { + &mut self.op().v + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/sweep.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/sweep.rs new file mode 100644 index 0000000..f8f8aa5 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/arity/sweep.rs @@ -0,0 +1,99 @@ +//! Create a 3D distance field by sweeping a 2D distance field +//! around the perimiter of another 2D distance field + +use rust_gpu_bridge::glam::{Vec2, Vec3, Vec3Swizzles}; +use type_fields::macros::Field; + +use crate::prelude::{AttrDistance, Field, FieldOperator, AttrNormal, Operator, AttrUv, items::position::Position, Normal, Uv}; + +/// Create a 3D distance field by sweeping a 2D distance field +/// around the perimiter of another 2D distance field +#[derive(Debug, Default, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SweepOp; + +impl FieldOperator<(Core, Shell), AttrDistance> for SweepOp +where + Core: Field>, + Shell: Field>, +{ + fn operator( + &self, + (core, shell): &(Core, Shell), + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + let q = *core.field(&p.x.into()); + shell.field(&q.into()) + } +} + +impl FieldOperator<(Core, Shell), AttrDistance> for SweepOp +where + Core: Field>, + Shell: Field>, +{ + fn operator( + &self, + (core, shell): &(Core, Shell), + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + let q = Vec2::new(*core.field(&p.truncate().into()), p.z); + shell.field(&q.into()) + } +} + +impl FieldOperator<(Core, Shell), AttrNormal> for SweepOp +where + Core: Field>, + Shell: Field>, +{ + fn operator(&self, (core, shell): &(Core, Shell), input: &Position) -> Normal { + let q = Vec2::new(*core.field(&input.truncate().into()), input.z); + let n = shell.field(&q.into()); + let w = input.xy().normalize() * n.x; + Vec3::new(w.x, w.y, n.y).into() + } +} + +impl FieldOperator<(Core, Shell), AttrUv> for SweepOp +where + Core: Field> + Field>, + Shell: Field>, +{ + fn operator(&self, (core, shell): &(Core, Shell), input: &Position) -> Uv { + let dist_core = *Field::>::field(core, &input.truncate().into()); + let uv_core = Field::>::field(core, &input.truncate().into()); + let q = Vec2::new(dist_core, input.z); + let uv_shell = shell.field(&q.into()); + Vec2::new(uv_core.x, uv_shell.x + uv_shell.y).into() + } +} + +/// Uniformly scale a distance field. +pub type Sweep = Operator; + +impl Sweep { + pub fn core(&mut self) -> &mut Core { + &mut self.target().0 + } + + pub fn shell(&mut self) -> &mut Shell { + &mut self.target().1 + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{ + prelude::{BoundTester, Circle, Point, Sweep}, + test_op_attrs_3d, + }; + + #[test] + fn test_sweep() { + assert!(BoundTester::>::default().is_field_3d()); + } + + test_op_attrs_3d!(Sweep::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/intersection.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/intersection.rs new file mode 100644 index 0000000..788487a --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/intersection.rs @@ -0,0 +1,91 @@ +//! Compute the boolean intersection of two distance fields. + +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, Field, FieldOperator, AttrNormal, Operator, AttrUv, Distance, Normal, Uv, +}; + +/// Compute the boolean intersection of two distance fields. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct IntersectionOp; + +impl FieldOperator<(SdfA, SdfB), AttrDistance> for IntersectionOp +where + SdfA: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Distance { + sdf_a.field(input).max(*sdf_b.field(input)).into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrNormal> for IntersectionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Normal { + let dist_a = Field::>::field(sdf_a, input); + let dist_b = Field::>::field(sdf_b, input); + + let n = if dist_a > dist_b { + Field::>::field(sdf_a, input) + } else { + Field::>::field(sdf_b, input) + }; + + n + } +} + +impl FieldOperator<(SdfA, SdfB), AttrUv> for IntersectionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Uv { + let dist_a = Field::>::field(sdf_a, input); + let dist_b = Field::>::field(sdf_b, input); + + if dist_a > dist_b { + Field::>::field(sdf_a, input) + } else { + Field::>::field(sdf_b, input) + } + } +} + +/// Compute the boolean intersection of two distance fields. +pub type Intersection = Operator; + +impl Intersection { + pub fn sdf_a(&mut self) -> &mut SdfA { + &mut self.target().0 + } + + pub fn sdf_b(&mut self) -> &mut SdfB { + &mut self.target().1 + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Cube, Intersection, Point, Sphere}, + test_op_attrs, + }; + + #[test] + fn test_intersection() { + Intersection::::default(); + } + + test_op_attrs!(Intersection::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/mod.rs new file mode 100644 index 0000000..2f32ef7 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/mod.rs @@ -0,0 +1,3 @@ +pub mod union; +pub mod subtraction; +pub mod intersection; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/subtraction.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/subtraction.rs new file mode 100644 index 0000000..16bc809 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/subtraction.rs @@ -0,0 +1,92 @@ +//! Compute the boolean subtraction of two distance fields. + +use core::ops::Neg; + +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrUv, Distance, Field, FieldOperator, + Normal, Operator, Uv, +}; + +/// Compute the boolean subtraction of two distance fields. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SubtractionOp; + +impl FieldOperator<(SdfA, SdfB), AttrDistance> for SubtractionOp +where + SdfA: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Distance { + sdf_a.field(p).neg().max(*sdf_b.field(p)).into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrNormal> for SubtractionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Normal { + let dist_a = *Field::>::field(sdf_a, input); + let dist_b = *Field::>::field(sdf_b, input); + + if -dist_a > dist_b { + Field::>::field(sdf_a, input) + } else { + Field::>::field(sdf_b, input) + } + } +} + +impl FieldOperator<(SdfA, SdfB), AttrUv> for SubtractionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Uv { + let dist_a = *Field::>::field(sdf_a, p); + let dist_b = *Field::>::field(sdf_b, p); + + if -dist_a > dist_b { + Field::>::field(sdf_a, p) + } else { + Field::>::field(sdf_b, p) + } + } +} + +/// Compute the boolean subtraction of two distance fields. +pub type Subtraction = Operator; + +impl Subtraction { + pub fn sdf_a(&mut self) -> &mut SdfA { + &mut self.target().0 + } + + pub fn sdf_b(&mut self) -> &mut SdfB { + &mut self.target().1 + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Cube, Point, Sphere, Subtraction}, + test_op_attrs, + }; + + #[test] + fn test_subtraction() { + Subtraction::::default(); + } + + test_op_attrs!(Subtraction::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/union.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/union.rs new file mode 100644 index 0000000..f25edf8 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/boolean/union.rs @@ -0,0 +1,90 @@ +//! Compute the boolean union of two distance fields. + +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrUv, Distance, Field, FieldOperator, + Normal, Operator, Uv, +}; + +/// Compute the boolean union of two distance fields. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct UnionOp; + +impl FieldOperator<(SdfA, SdfB), AttrDistance> for UnionOp +where + SdfA: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Distance { + sdf_a.field(p).min(*sdf_b.field(p)).into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrNormal> for UnionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Normal { + let dist_a = Field::>::field(sdf_a, input); + let dist_b = Field::>::field(sdf_b, input); + + if dist_a < dist_b { + Field::>::field(sdf_a, input) + } else { + Field::>::field(sdf_b, input) + } + } +} + +impl FieldOperator<(SdfA, SdfB), AttrUv> for UnionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Uv { + let dist_a = Field::>::field(sdf_a, input); + let dist_b = Field::>::field(sdf_b, input); + + if dist_a < dist_b { + Field::>::field(sdf_a, input) + } else { + Field::>::field(sdf_a, input) + } + } +} + +/// Compute the boolean union of two distance fields. +pub type Union = Operator; + +impl Union { + pub fn sdf_a(&mut self) -> &mut SdfA { + &mut self.target().0 + } + + pub fn sdf_b(&mut self) -> &mut SdfB { + &mut self.target().1 + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Cube, Point, Sphere, Union}, + test_op_attrs, + }; + + #[test] + fn test_union() { + Union::::default(); + } + + test_op_attrs!(Union::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/checker.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/checker.rs new file mode 100644 index 0000000..3342f06 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/checker.rs @@ -0,0 +1,32 @@ +use crate::{ + impl_passthrough_op_1, + prelude::{AttrColor, AttrDistance, Field, AttrNormal, Raycast, AttrTangent, AttrUv, items::position::Position}, +}; +use rust_gpu_bridge::{glam::Vec3, Mod}; + +use super::{FieldOperator, Operator}; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +pub struct CheckerOp; + +impl FieldOperator> for CheckerOp +where + Sdf: Field>, + Input: Mod, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> as crate::prelude::Attribute>::Output { + let uv = sdf.field(p); + let checker = uv.round(); + let checker = (checker.x + checker.y).modulo(2.0) / 2.0; + Vec3::splat(checker).extend(1.0).into() + } +} + +impl_passthrough_op_1!(CheckerOp, AttrDistance, Dim); +impl_passthrough_op_1!(CheckerOp, AttrNormal, Dim); +impl_passthrough_op_1!(CheckerOp, AttrTangent, Dim); +impl_passthrough_op_1!(CheckerOp, AttrUv, Dim); +impl_passthrough_op_1!(CheckerOp, Raycast,); + +pub type Checker = Operator; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_normal.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_normal.rs new file mode 100644 index 0000000..e359d33 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_normal.rs @@ -0,0 +1,39 @@ +use core::ops::{Add, Mul}; + +use rust_gpu_bridge::{glam::Vec4, Splat, ToVec}; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, Color, + Field, Raycast, + }, +}; + +use super::{FieldOperator, Operator}; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +pub struct ColorNormalOp; + +impl FieldOperator> for ColorNormalOp +where + Sdf: Field>, + Input: Clone + Add + Mul + Splat + ToVec, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Color { + let normal = (*sdf.field(p)).clone(); + let normal = normal * Input::splat(0.5) + Input::splat(0.5); + let mut color = normal.to_vec(); + color.w = 1.0; + color.into() + } +} + +impl_passthrough_op_1!(ColorNormalOp, AttrDistance, Dim); +impl_passthrough_op_1!(ColorNormalOp, AttrNormal, Dim); +impl_passthrough_op_1!(ColorNormalOp, AttrTangent, Dim); +impl_passthrough_op_1!(ColorNormalOp, AttrUv, Dim); +impl_passthrough_op_1!(ColorNormalOp, Raycast,); + +pub type ColorNormal = Operator; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_tangent.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_tangent.rs new file mode 100644 index 0000000..b46804b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_tangent.rs @@ -0,0 +1,37 @@ +use core::ops::{Add, Mul}; + +use rust_gpu_bridge::{glam::Vec4, Splat, ToVec}; + +use crate::{ + impl_passthrough_op_1, + prelude::{AttrColor, AttrDistance, Field, AttrNormal, Raycast, AttrTangent, AttrUv, items::position::Position, Color}, +}; + +use super::{FieldOperator, Operator}; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +pub struct ColorTangentOp; + +impl FieldOperator> for ColorTangentOp +where + Sdf: Field>, + Input: Clone + Add + Mul + Splat + ToVec, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Color { + let tangent = (*sdf.field(p)).clone(); + let tangent = tangent * Input::splat(0.5) + Input::splat(0.5); + let mut color = tangent.to_vec(); + color.w = 1.0; + color.into() + } +} + +impl_passthrough_op_1!(ColorTangentOp, AttrDistance, Dim); +impl_passthrough_op_1!(ColorTangentOp, AttrNormal, Dim); +impl_passthrough_op_1!(ColorTangentOp, AttrTangent, Dim); +impl_passthrough_op_1!(ColorTangentOp, AttrUv, Dim); +impl_passthrough_op_1!(ColorTangentOp, Raycast,); + +pub type ColorTangent = Operator; + diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_uv.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_uv.rs new file mode 100644 index 0000000..9a61f69 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/color_uv.rs @@ -0,0 +1,33 @@ +use core::ops::{Add, Mul}; + +use rust_gpu_bridge::{glam::Vec4, Splat, ToVec}; + +use crate::{ + impl_passthrough_op_1, + prelude::{AttrColor, AttrDistance, Field, AttrNormal, Raycast, AttrTangent, AttrUv, items::position::Position, Color}, +}; + +use super::{FieldOperator, Operator}; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +pub struct ColorUvOp; + +impl FieldOperator> for ColorUvOp +where + Sdf: Field>, + Input: Add + Mul + Splat + ToVec, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Color { + let uv = sdf.field(p); + uv.extend(0.0).extend(1.0).into() + } +} + +impl_passthrough_op_1!(ColorUvOp, AttrDistance, Dim); +impl_passthrough_op_1!(ColorUvOp, AttrNormal, Dim); +impl_passthrough_op_1!(ColorUvOp, AttrTangent, Dim); +impl_passthrough_op_1!(ColorUvOp, AttrUv, Dim); +impl_passthrough_op_1!(ColorUvOp, Raycast,); + +pub type ColorUv = Operator; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/composite.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/composite.rs new file mode 100644 index 0000000..ce99351 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/composite.rs @@ -0,0 +1,29 @@ +//! Operators composed from other operators. + +use crate::prelude::{Hollow, Isosurface}; + +/// Converts a solid shape into a hollow one with the given surface depth. +pub type Onion = Isosurface>; + +impl Onion { + pub fn radius(&mut self) -> &mut f32 { + self.op().delta() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use type_fields::field::Field; + + use crate::{ + prelude::{Circle, Onion}, + test_op_attrs, + }; + + #[test] + fn test_onion() { + Onion::::default().with(Onion::radius, f32::default()); + } + + test_op_attrs!(Onion::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/cartesian_to_spherical.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/cartesian_to_spherical.rs new file mode 100644 index 0000000..a20826d --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/cartesian_to_spherical.rs @@ -0,0 +1,68 @@ +use rust_gpu_bridge::{ + glam::{Vec2, Vec3, Vec3Swizzles}, + Acos, Atan2, Sign, +}; + +use crate::prelude::{Attribute, Field, FieldOperator, Operator, items::position::Position}; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct CartesianToPolarOp; + +impl FieldOperator for CartesianToPolarOp +where + Sdf: Field, + Attr: Attribute>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + let r = p.length(); + let a = p.x.atan2(p.y); + sdf.field(&Vec2::new(a, r).into()) + } +} + +pub type CartesianToPolar = Operator; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct CartesianToSphericalOp; + +impl FieldOperator for CartesianToSphericalOp +where + Sdf: Field, + Attr: Attribute>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + let r = p.length(); + let i = (p.z / r).acos(); + let a = p.y.sign() * (p.x / p.xy().length()).acos(); + sdf.field(&Vec3::new(i, r, a).into()) + } +} + +pub type CartesianToSpherical = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{CartesianToSpherical, Point}, + test_op_attrs_2d, test_op_attrs_3d, + }; + + use super::CartesianToPolar; + + #[test] + fn test_cartesian_to_polar() { + CartesianToPolar::::default(); + } + + #[test] + fn test_cartesian_to_spherical() { + CartesianToSpherical::::default(); + } + + test_op_attrs_2d!(CartesianToPolar::); + test_op_attrs_3d!(CartesianToSpherical::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/mod.rs new file mode 100644 index 0000000..2a5443f --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/mod.rs @@ -0,0 +1,2 @@ +pub mod cartesian_to_spherical; +pub mod spherical_to_cartesian; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/spherical_to_cartesian.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/spherical_to_cartesian.rs new file mode 100644 index 0000000..eef9614 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/coordinate_system/spherical_to_cartesian.rs @@ -0,0 +1,68 @@ +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Cos, Sin, +}; + +use crate::prelude::{Attribute, Field, FieldOperator, Operator, items::position::Position}; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct PolarToCartesianOp; + +impl FieldOperator for PolarToCartesianOp +where + Sdf: Field, + Attr: Attribute>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + let x = p.y * p.x.cos(); + let y = p.y * p.x.sin(); + sdf.field(&Vec2::new(y, x).into()) + } +} + +pub type PolarToCartesian = Operator; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SphericalToCartesianOp; + +impl FieldOperator for SphericalToCartesianOp +where + Sdf: Field, + Attr: Attribute>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + let x = p.y * p.x.sin() * p.z.cos(); + let y = p.y * p.x.sin() * p.z.sin(); + let z = p.y * p.x.cos(); + sdf.field(&Vec3::new(x, y, z).into()) + } +} + +pub type SphericalToCartesian = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Point, SphericalToCartesian}, + test_op_attrs_2d, test_op_attrs_3d, + }; + + use super::PolarToCartesian; + + #[test] + fn test_polar_to_cartesian() { + PolarToCartesian::::default(); + } + + #[test] + fn test_spherical_to_cartesian() { + SphericalToCartesian::::default(); + } + + test_op_attrs_2d!(PolarToCartesian::); + test_op_attrs_3d!(SphericalToCartesian::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/displace.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/displace.rs new file mode 100644 index 0000000..1fbc689 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/displace.rs @@ -0,0 +1,59 @@ +//! Displace the output of a distance field using the output of another distance field. + +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_2, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, + Distance, Field, FieldOperator, Operator, + }, +}; + +/// Displace the output of a distance field using the output of another distance field. +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct DisplaceOp { + pub delta: f32, +} + +impl FieldOperator> for DisplaceOp +where + SdfA: Field>, + Input: Clone, +{ + fn operator(&self, sdf_a: &SdfA, input: &Position) -> Distance { + sdf_a.field(input) + self.delta + } +} + +impl_passthrough_op_2!(DisplaceOp, AttrNormal, 0, SdfA, Dim); +impl_passthrough_op_2!(DisplaceOp, AttrTangent, 0, SdfA, Dim); +impl_passthrough_op_2!(DisplaceOp, AttrUv, 0, SdfA, Dim); +impl_passthrough_op_2!(DisplaceOp, AttrColor, 0, SdfA, Dim); + +/// Displace the output of a distance field using the output of another distance field. +pub type Displace = Operator; + +impl Displace { + pub fn delta(&mut self) -> &mut f32 { + self.op().delta() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{ + prelude::{Cube, DisplaceProxy, Point, Sphere}, + test_op_attrs, + }; + use type_fields::field::Field; + + #[test] + fn test_displace() { + DisplaceProxy::::default().with(DisplaceProxy::displace, Sphere::default()); + } + + test_op_attrs!(DisplaceProxy::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/displace_proxy.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/displace_proxy.rs new file mode 100644 index 0000000..5096c6b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/displace_proxy.rs @@ -0,0 +1,62 @@ +//! Displace the output of a distance field using the output of another distance field. + +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_2, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, + Distance, Field, FieldOperator, Operator, + }, +}; + +/// Displace the output of a distance field using the output of another distance field. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct DisplaceProxyOp; + +impl FieldOperator<(SdfA, SdfB), AttrDistance> for DisplaceProxyOp +where + SdfA: Field>, + SdfB: Field>, + Input: Clone, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Distance { + sdf_a.field(input) + *sdf_b.field(input) + } +} + +impl_passthrough_op_2!(DisplaceProxyOp, AttrNormal, 0, SdfA, Dim); +impl_passthrough_op_2!(DisplaceProxyOp, AttrTangent, 0, SdfA, Dim); +impl_passthrough_op_2!(DisplaceProxyOp, AttrUv, 0, SdfA, Dim); +impl_passthrough_op_2!(DisplaceProxyOp, AttrColor, 0, SdfA, Dim); + +/// Displace the output of a distance field using the output of another distance field. +pub type DisplaceProxy = Operator; + +impl DisplaceProxy { + pub fn sdf(&mut self) -> &mut SdfA { + &mut self.target.0 + } + + pub fn displace(&mut self) -> &mut SdfB { + &mut self.target.1 + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{ + prelude::{Cube, DisplaceProxy, Point, Sphere}, + test_op_attrs, + }; + use type_fields::field::Field; + + #[test] + fn test_displace() { + DisplaceProxy::::default().with(DisplaceProxy::displace, Sphere::default()); + } + + test_op_attrs!(DisplaceProxy::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/elongate.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/elongate.rs new file mode 100644 index 0000000..f18d0e4 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/elongate.rs @@ -0,0 +1,216 @@ +//! Extrude a shape along its axes, preserving exterior geometry. + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3, Vec3Swizzles}, + Abs, Sign, +}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrUv, Distance, Field, FieldOperator, + Normal, Operator, Uv, +}; + +/// Extrude a shape along its axes, preserving exterior geometry. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ElongateOp { + pub extent: Dim, +} + +#[cfg(feature = "bevy")] +impl bevy::reflect::TypeUuid for ElongateOp { + const TYPE_UUID: bevy::reflect::Uuid = bevy::reflect::Uuid::from_u128(196665527114209003); +} + +impl Default for ElongateOp { + fn default() -> Self { + ElongateOp { extent: 1.0 } + } +} + +impl Default for ElongateOp { + fn default() -> Self { + ElongateOp { extent: Vec2::ONE } + } +} + +impl Default for ElongateOp { + fn default() -> Self { + ElongateOp { extent: Vec3::ONE } + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Distance { + let q = input.abs() - self.extent; + sdf.field(&q.max(0.0).into()) + q.min(0.0) + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Distance { + let q = input.abs() - self.extent; + sdf.field(&q.max(Vec2::ZERO).into()) + q.x.max(q.y).min(0.0) + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Distance { + let q = input.abs() - self.extent; + sdf.field(&q.max(Vec3::ZERO).into()) + q.x.max(q.y.max(q.z)).min(0.0) + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, _sdf: &Sdf, input: &Position) -> Normal { + input.sign().into() + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, _sdf: &Sdf, input: &Position) -> Normal { + let w = input.abs() - self.extent; + let s = input.sign(); + + let g = w.x.max(w.y); + let q = w.max(Vec2::ZERO); + let l = q.length(); + + let m = s + * (if g > 0.0 { + q / l + } else { + if w.x > w.y { + Vec2::X + } else { + Vec2::Y + } + }); + + m.into() + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, _sdf: &Sdf, input: &Position) -> Normal { + let w = input.abs() - self.extent; + let s = input.sign(); + + let g = w.x.max(w.y).max(w.z); + let q = w.max(Vec3::ZERO); + let l = q.length(); + + let m = s + * (if g > 0.0 { + q / l + } else { + if w.x > w.y { + if w.x > w.z { + Vec3::X + } else { + Vec3::Z + } + } else { + if w.y > w.z { + Vec3::Y + } else { + Vec3::Z + } + } + }); + + m.into() + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, _sdf: &Sdf, input: &Position) -> Uv { + Vec2::new((**input + self.extent) * (0.5 / self.extent), 0.0).into() + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, _sdf: &Sdf, input: &Position) -> Uv { + ((**input + self.extent) * (0.5 / self.extent)).into() + } +} + +impl FieldOperator> for ElongateOp +where + Sdf: Field>, +{ + fn operator(&self, _sdf: &Sdf, input: &Position) -> Uv { + let w = input.abs(); + + let m = if w.x > w.y { + if w.x > w.z { + (input.zy() + self.extent.zy()) * (0.5 / self.extent.zy()) + } else { + (input.xy() + self.extent.xy()) * (0.5 / self.extent.xy()) + } + } else { + if w.y > w.z { + (input.xz() + self.extent.xz()) * (0.5 / self.extent.xz()) + } else { + (input.xy() + self.extent.xy()) * (0.5 / self.extent.xy()) + } + }; + + m.into() + } +} + +/// Extrude a shape along its axes, preserving exterior geometry. +pub type Elongate = Operator, Sdf>; + +impl Elongate { + pub fn extent(&mut self) -> &mut Dim { + &mut self.op.extent + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Elongate, Point}, + test_op_attrs_1d, test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_elongate() { + Elongate::::default().with(Elongate::extent, Vec3::default()); + } + + test_op_attrs_1d!(Elongate::); + test_op_attrs_2d!(Elongate::); + test_op_attrs_3d!(Elongate::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_central_diff.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_central_diff.rs new file mode 100644 index 0000000..6d91c1f --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_central_diff.rs @@ -0,0 +1,116 @@ +use rust_gpu_bridge::glam::{Vec2, Vec3}; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, Field, + FieldOperator, Normalize, Operator, Raycast, + }, +}; + +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct GradientCentralDiffOp { + pub epsilon: f32, +} + +impl Default for GradientCentralDiffOp { + fn default() -> Self { + GradientCentralDiffOp { epsilon: 0.001 } + } +} + +impl FieldOperator> for GradientCentralDiffOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + input: &Position, + ) -> as crate::prelude::Attribute>::Output { + (*sdf.field(&(**input + self.epsilon).into()) + - *sdf.field(&(**input - self.epsilon).into())) + .into() + } +} + +impl FieldOperator> for GradientCentralDiffOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + input: &Position, + ) -> as crate::prelude::Attribute>::Output { + Vec2::new( + *sdf.field(&Vec2::new(input.x + self.epsilon, input.y).into()) + - *sdf.field(&Vec2::new(input.x - self.epsilon, input.y).into()), + *sdf.field(&Vec2::new(input.x, input.y + self.epsilon).into()) + - *sdf.field(&Vec2::new(input.x, input.y - self.epsilon).into()), + ).into() + } +} + +impl FieldOperator> for GradientCentralDiffOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + Vec3::new( + *sdf.field(&Vec3::new(p.x + self.epsilon, p.y, p.z).into()) + - *sdf.field(&Vec3::new(p.x - self.epsilon, p.y, p.z).into()), + *sdf.field(&Vec3::new(p.x, p.y + self.epsilon, p.z).into()) + - *sdf.field(&Vec3::new(p.x, p.y - self.epsilon, p.z).into()), + *sdf.field(&Vec3::new(p.x, p.y, p.z + self.epsilon).into()) + - *sdf.field(&Vec3::new(p.x, p.y, p.z - self.epsilon).into()), + ).into() + } +} + +impl_passthrough_op_1!(GradientCentralDiffOp, AttrDistance::, Dim); +impl_passthrough_op_1!(GradientCentralDiffOp, AttrTangent, Dim); +impl_passthrough_op_1!(GradientCentralDiffOp, AttrUv, Dim); +impl_passthrough_op_1!(GradientCentralDiffOp, AttrColor, Dim); +impl_passthrough_op_1!(GradientCentralDiffOp, Raycast,); + +pub type GradientCentralDiff = Operator; + +impl GradientCentralDiff { + pub fn epsilon(&mut self) -> &mut f32 { + self.op().epsilon() + } +} + +pub type NormalCentralDiff = Normalize>; + +impl NormalCentralDiff { + pub fn sdf(&mut self) -> &mut Sdf { + self.target().target() + } + + pub fn epsilon(&mut self) -> &mut f32 { + self.target().epsilon() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{prelude::Point, test_op_attrs}; + + use super::GradientCentralDiff; + + #[test] + fn test_gradient_central_diff() { + GradientCentralDiff::::default(); + } + + test_op_attrs!(GradientCentralDiff::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_tetrahedron.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_tetrahedron.rs new file mode 100644 index 0000000..90be9ef --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_tetrahedron.rs @@ -0,0 +1,114 @@ +use rust_gpu_bridge::glam::{Vec2, Vec2Swizzles, Vec3}; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, Field, + FieldOperator, Normalize, Operator, Raycast, + }, +}; + +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct GradientTetrahedronOp { + pub epsilon: f32, +} + +impl Default for GradientTetrahedronOp { + fn default() -> Self { + GradientTetrahedronOp { epsilon: 0.001 } + } +} + +impl FieldOperator> for GradientTetrahedronOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + input: &Position, + ) -> as crate::prelude::Attribute>::Output { + (*sdf.field(&(**input + self.epsilon).into()) + - *sdf.field(&(**input - self.epsilon).into())) + .into() + } +} + +impl FieldOperator> for GradientTetrahedronOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + let k = Vec2::new(1.0, -1.0); + (k.xy() * *sdf.field(&(**p + k.xy() * self.epsilon).into()) + + k.yy() * *sdf.field(&(**p + k.yy() * self.epsilon).into()) + + k.yx() * *sdf.field(&(**p + k.yx() * self.epsilon).into()) + + k.xx() * *sdf.field(&(**p + k.xx() * self.epsilon).into())) + .into() + } +} + +impl FieldOperator> for GradientTetrahedronOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + let k = Vec2::new(1.0, -1.0); + (k.xyy() * *sdf.field(&(**p + k.xyy() * self.epsilon).into()) + + k.yyx() * *sdf.field(&(**p + k.yyx() * self.epsilon).into()) + + k.yxy() * *sdf.field(&(**p + k.yxy() * self.epsilon).into()) + + k.xxx() * *sdf.field(&(**p + k.xxx() * self.epsilon).into())) + .into() + } +} + +impl_passthrough_op_1!(GradientTetrahedronOp, AttrDistance, Dim); +impl_passthrough_op_1!(GradientTetrahedronOp, AttrTangent, Dim); +impl_passthrough_op_1!(GradientTetrahedronOp, AttrUv, Dim); +impl_passthrough_op_1!(GradientTetrahedronOp, AttrColor, Dim); +impl_passthrough_op_1!(GradientTetrahedronOp, Raycast,); + +pub type GradientTetrahedron = Operator; + +impl GradientTetrahedron { + pub fn epsilon(&mut self) -> &mut f32 { + self.op().epsilon() + } +} + +pub type NormalTetrahedron = Normalize>; + +impl NormalTetrahedron { + pub fn sdf(&mut self) -> &mut Sdf { + self.target().target() + } + + pub fn epsilon(&mut self) -> &mut f32 { + self.target().epsilon() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{prelude::Point, test_op_attrs}; + + use super::GradientTetrahedron; + + #[test] + fn test_gradient_tetrahedron() { + GradientTetrahedron::::default(); + } + + test_op_attrs!(GradientTetrahedron::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_uv.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_uv.rs new file mode 100644 index 0000000..663ad76 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/gradient_uv.rs @@ -0,0 +1,106 @@ +use rust_gpu_bridge::glam::{Vec2, Vec2Swizzles, Vec3}; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, Field, + FieldOperator, Normalize, Operator, Raycast, + }, +}; + +/// Calculate a 3D gradient given a 2D UV +#[derive(Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct UvGradientOp { + pub axis: Vec2, + pub epsilon: f32, +} + +impl Default for UvGradientOp { + fn default() -> Self { + UvGradientOp { + axis: Vec2::X, + epsilon: 0.00001, + } + } +} + +impl FieldOperator> for UvGradientOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + input: &Position, + ) -> as crate::prelude::Attribute>::Output { + let k = Vec2::new(1.0, -1.0); + (k.xyy() + * sdf + .field(&(**input + k.xyy() * self.epsilon).into()) + .dot(self.axis) + + k.yyx() + * sdf + .field(&(**input + k.yyx() * self.epsilon).into()) + .dot(self.axis) + + k.yxy() + * sdf + .field(&(**input + k.yxy() * self.epsilon).into()) + .dot(self.axis) + + k.xxx() + * sdf + .field(&(**input + k.xxx() * self.epsilon).into()) + .dot(self.axis)) + .into() + } +} + +impl_passthrough_op_1!(UvGradientOp, AttrDistance, Dim); +impl_passthrough_op_1!(UvGradientOp, AttrNormal, Dim); +impl_passthrough_op_1!(UvGradientOp, AttrUv, Dim); +impl_passthrough_op_1!(UvGradientOp, AttrColor, Dim); +impl_passthrough_op_1!(UvGradientOp, Raycast,); + +pub type UvGradient = Operator; + +impl UvGradient { + pub fn axis(&mut self) -> &mut Vec2 { + self.op().axis() + } + + pub fn epsilon(&mut self) -> &mut f32 { + self.op().epsilon() + } +} + +pub type UvTangent = Normalize>; + +impl UvTangent { + pub fn sdf(&mut self) -> &mut Sdf { + self.target().target() + } + + pub fn axis(&mut self) -> &mut Vec2 { + self.target().axis() + } + + pub fn epsilon(&mut self) -> &mut f32 { + self.target().epsilon() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{prelude::Point, test_op_attrs}; + + use super::UvGradient; + + #[test] + fn test_gradient_tetrahedron() { + UvGradient::::default(); + } + + test_op_attrs!(UvGradient::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/mod.rs new file mode 100644 index 0000000..b174cac --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/gradient/mod.rs @@ -0,0 +1,3 @@ +pub mod gradient_central_diff; +pub mod gradient_tetrahedron; +pub mod gradient_uv; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/hollow.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/hollow.rs new file mode 100644 index 0000000..58d6f67 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/hollow.rs @@ -0,0 +1,87 @@ +//! Convert a solid shape into a hollow one with an infinitely thin surface. + +use core::ops::Mul; + +use rust_gpu_bridge::{Abs, Sign}; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, + Distance, Field, FieldOperator, Normal, Operator, Tangent, Uv, + }, +}; + +/// Convert a solid shape into a hollow one with an infinitely thin surface. +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct HollowOp; + +impl FieldOperator> for HollowOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Distance { + sdf.field(input).abs().into() + } +} + +impl FieldOperator> for HollowOp +where + Sdf: Field>, + Sdf: Field>, + Input: Clone + Mul, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Normal { + let d = >>::field(sdf, input); + let s = d.sign(); + >>::field(sdf, &((*input).clone() * s)) + } +} + +impl FieldOperator> for HollowOp +where + Sdf: Field>, + Sdf: Field>, + Dim: Clone + Mul, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Tangent { + let d = >>::field(sdf, input); + let s = d.sign(); + >>::field(sdf, &((*input).clone() * s)) + } +} + +impl FieldOperator> for HollowOp +where + Sdf: Field>, + Sdf: Field>, + Input: Clone + Mul, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Uv { + let d = >>::field(sdf, input); + let s = d.sign(); + >>::field(sdf, &((*input).clone() * s)) + } +} + +impl_passthrough_op_1!(HollowOp, AttrColor, Dim); + +/// Convert a solid shape into a hollow one with an infinitely thin surface. +pub type Hollow = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{prelude::Point, test_op_attrs}; + + use super::Hollow; + + #[test] + fn test_gradient_tetrahedron() { + Hollow::::default(); + } + + test_op_attrs!(Hollow::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/isosurface.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/isosurface.rs new file mode 100644 index 0000000..3b6959c --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/isosurface.rs @@ -0,0 +1,77 @@ +//! Shift the isosurface of a distance field by a given amount. + +use core::ops::Div; + +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, + Distance, Field, FieldOperator, Operator, + }, +}; + +/// Shift the isosurface of a distance field by a given amount. +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[cfg_attr(feature = "bevy", derive(bevy::reflect::TypeUuid))] +#[cfg_attr(feature = "bevy", uuid = "d588f817-4e15-4b1e-b98c-dc2b0d47f719")] +#[repr(C)] +pub struct IsosurfaceOp { + pub delta: f32, +} + +impl Default for IsosurfaceOp { + fn default() -> Self { + IsosurfaceOp { delta: 1.0 } + } +} + +impl FieldOperator> for IsosurfaceOp +where + SdfA: Field>, + Input: Clone, +{ + fn operator(&self, sdf_a: &SdfA, input: &Position) -> Distance { + sdf_a.field(input) - self.delta + } +} + +impl_passthrough_op_1!(IsosurfaceOp, AttrNormal, Dim); +impl_passthrough_op_1!(IsosurfaceOp, AttrTangent, Dim); + +impl FieldOperator> for IsosurfaceOp +where + SdfA: crate::prelude::Field>, + Input: Clone + Div, +{ + fn operator( + &self, + sdf_a: &SdfA, + input: &Position, + ) -> as crate::prelude::Attribute>::Output { + let p = (*input).clone() / self.delta; + sdf_a.field(&p) + } +} + +impl_passthrough_op_1!(IsosurfaceOp, AttrColor, Dim); + +/// Add an arbitrary radius to a distance field. +pub type Isosurface = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Isosurface, Point}, + test_op_attrs, + }; + + #[test] + fn test_isosurface() { + Isosurface::::default(); + } + + test_op_attrs!(Isosurface::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/isosurface_proxy.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/isosurface_proxy.rs new file mode 100644 index 0000000..74a2586 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/isosurface_proxy.rs @@ -0,0 +1,71 @@ +//! Shift the isosurface of a distance field by a given amount. + +use core::ops::Div; + +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_2, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, + DisplaceProxyOp, Distance, Field, FieldOperator, Operator, + }, +}; + +/// Shift the isosurface of a distance field by a given amount. +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct IsosurfaceProxyOp; + +impl FieldOperator<(SdfA, SdfB), AttrDistance> for IsosurfaceProxyOp +where + SdfA: Field>, + SdfB: Field>, + Input: Clone, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Distance { + let d1 = sdf_a.field(p); + let d2 = sdf_b.field(p); + d1 - *d2 + } +} + +impl_passthrough_op_2!(IsosurfaceProxyOp, AttrNormal, 0, SdfA, Dim); +impl_passthrough_op_2!(IsosurfaceProxyOp, AttrTangent, 0, SdfA, Dim); + +impl FieldOperator<(SdfA, SdfB), AttrUv> for IsosurfaceProxyOp +where + SdfA: crate::prelude::Field>, + SdfB: crate::prelude::Field>, + Input: Clone + Div, +{ + fn operator( + &self, + (sdf_a, sdf_b): &(SdfA, SdfB), + input: &Position, + ) -> as crate::prelude::Attribute>::Output { + let p = (*input).clone() / *sdf_b.field(input); + sdf_a.field(&p) + } +} + +impl_passthrough_op_2!(IsosurfaceProxyOp, AttrColor, 0, SdfA, Dim); + +/// Add an arbitrary radius to a distance field. +pub type IsosurfaceProxy = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{IsosurfaceProxy, Point}, + test_op_attrs, + }; + + #[test] + fn test_isosurface() { + IsosurfaceProxy::::default(); + } + + test_op_attrs!(IsosurfaceProxy::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/mod.rs new file mode 100644 index 0000000..9a28f3c --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/mod.rs @@ -0,0 +1,177 @@ +//! Types that modify a distance field. + +pub mod checker; +pub mod color_normal; +pub mod color_tangent; +pub mod color_uv; +pub mod composite; +pub mod displace; +pub mod displace_proxy; +pub mod elongate; +pub mod hollow; +pub mod isosurface; +pub mod isosurface_proxy; +pub mod normalize; +pub mod scale_uv; +pub mod sided; +pub mod stretch; +pub mod triplanar_uv; +pub mod twist; + +pub mod arity; +pub mod boolean; +pub mod coordinate_system; +pub mod gradient; +pub mod proxy; +pub mod raycast; +pub mod reflect; +pub mod repeat; +pub mod smooth_boolean; +pub mod transform; + +use crate::prelude::{Attribute, Field}; + +/// Modifies the input / output of a [`FieldAttribute`]. +pub trait FieldOperator +where + Attr: Attribute, +{ + fn operator(&self, sdf: &Sdf, input: &Attr::Input) -> Attr::Output; +} + +/// Applies a [`FieldOperator`] to a [`FieldAttribute`]. +#[derive( + Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Hash, type_fields::macros::Field, +)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[cfg_attr(feature = "bevy", derive(bevy::reflect::TypeUuid))] +#[cfg_attr(feature = "bevy", uuid = "d588f817-4e15-4b1e-b98c-dc2b0d47f719")] +#[repr(C)] +pub struct Operator { + pub target: Sdf, + pub op: Op, +} + +impl Field for Operator +where + Op: FieldOperator, + Attr: Attribute, +{ + fn field(&self, p: &Attr::Input) -> Attr::Output { + self.op.operator(&self.target, p) + } +} + +#[cfg(feature = "glam")] +pub mod boxed { + extern crate alloc; + use alloc::boxed::Box; + + use crate::prelude::{Attribute, FieldOperator}; + + impl FieldOperator for Box> + where + Attr: Attribute, + { + fn operator( + &self, + sdf: &Sdf, + input: &::Input, + ) -> ::Output { + self.as_ref().operator(sdf, input) + } + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use type_fields::field::Field; + + use crate::prelude::{IsosurfaceProxyOp, Operator, Point}; + + #[test] + fn test_operator() { + Operator::::default() + .with(Operator::target, Point::default()) + .with(Operator::op, IsosurfaceProxyOp::default()); + } +} + +#[macro_export] +macro_rules! impl_passthrough_op_1 { + ($ty:ty, $attr:ty, $($gen:tt)*) => { + impl FieldOperator for $ty + where + Sdf: crate::prelude::Field<$attr>, + { + fn operator( + &self, + sdf: &Sdf, + input: &<$attr as crate::prelude::Attribute>::Input, + ) -> <$attr as crate::prelude::Attribute>::Output { + sdf.field(input) + } + } + }; +} + +#[macro_export] +macro_rules! impl_passthrough_op_2 { + ($ty:ty, $attr:ty, $field:tt, $sdf:ident $($gen:tt)*) => { + impl FieldOperator<(SdfA, SdfB), $attr> for $ty + where + $sdf: crate::prelude::Field<$attr>, + { + fn operator( + &self, + sdf: &(SdfA, SdfB), + input: &<$attr as crate::prelude::Attribute>::Input, + ) -> <$attr as crate::prelude::Attribute>::Output { + sdf.$field.field(input) + } + } + }; +} + +#[macro_export] +macro_rules! test_op_attrs { + ($ty:ty) => { + crate::test_op_attrs_1d!($ty); + crate::test_op_attrs_2d!($ty); + crate::test_op_attrs_3d!($ty); + }; +} + +#[macro_export] +macro_rules! test_op_attrs_1d { + ($ty:ty) => { + crate::test_op_attrs_impl!($ty, test_attrs_1d, crate::prelude::Position, [crate::prelude::AttrDistance, crate::prelude::AttrNormal, crate::prelude::AttrUv]); + }; +} + +#[macro_export] +macro_rules! test_op_attrs_2d { + ($ty:ty) => { + crate::test_op_attrs_impl!($ty, test_attrs_2d, crate::prelude::Position, [crate::prelude::AttrDistance, crate::prelude::AttrNormal, crate::prelude::AttrUv]); + }; +} + +#[macro_export] +macro_rules! test_op_attrs_3d { + ($ty:ty) => { + crate::test_op_attrs_impl!($ty, test_attrs_3d, crate::prelude::Position, [crate::prelude::AttrDistance, crate::prelude::AttrNormal, crate::prelude::AttrUv]); + }; +} + +#[macro_export] +macro_rules! test_op_attrs_impl { + ($ty:ty, $ident:ident, $pos:ty, [$($attrs:ty),+]) => { + #[test] + fn $ident() { + let f = <$ty>::default(); + $( + let _ = crate::prelude::Field::<$attrs>::field(&f, &<$pos>::default()); + )* + } + }; +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/normalize.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/normalize.rs new file mode 100644 index 0000000..4686077 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/normalize.rs @@ -0,0 +1,55 @@ +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, Field, + Normal, Raycast, Tangent, + }, +}; + +use super::{FieldOperator, Operator}; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct NormalizeOp; + +impl FieldOperator> for NormalizeOp +where + Sdf: Field>, + Input: Clone + rust_gpu_bridge::Normalize, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Normal { + (*sdf.field(p)).clone().normalize().into() + } +} + +impl FieldOperator> for NormalizeOp +where + Sdf: Field>, + Input: Clone + rust_gpu_bridge::Normalize, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Tangent { + (*sdf.field(p)).clone().normalize().into() + } +} + +impl_passthrough_op_1!(NormalizeOp, AttrDistance, Dim); +impl_passthrough_op_1!(NormalizeOp, AttrUv, Dim); +impl_passthrough_op_1!(NormalizeOp, AttrColor, Dim); +impl_passthrough_op_1!(NormalizeOp, Raycast,); + +pub type Normalize = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{prelude::Point, test_op_attrs}; + + use super::Normalize; + + #[test] + fn test_normalize() { + Normalize::::default(); + } + + test_op_attrs!(Normalize::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/mod.rs new file mode 100644 index 0000000..1810f0e --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/mod.rs @@ -0,0 +1,4 @@ +pub mod proxy_color; +pub mod proxy_normal; +pub mod proxy_tangent; +pub mod proxy_uv; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_color.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_color.rs new file mode 100644 index 0000000..8ff762f --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_color.rs @@ -0,0 +1,63 @@ +//! Override the colors of an SDF with the colors of another SDF + +use rust_gpu_bridge::glam::Vec4; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_2, + prelude::{AttrColor, AttrDistance, FieldOperator, AttrNormal, Operator, Raycast, AttrTangent, AttrUv, items::position::Position}, impl_passthrough_op_1, +}; + +/// Override the colors of an SDF with the colors of another SDF +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ProxyColorOp; + +impl_passthrough_op_2!(ProxyColorOp, AttrDistance, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyColorOp, AttrNormal, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyColorOp, AttrTangent, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyColorOp, AttrUv, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyColorOp, AttrColor, 1, SdfB, Dim); +impl_passthrough_op_2!(ProxyColorOp, Raycast, 0, SdfA); + +pub type ProxyColor = Operator; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct WhiteOp; + +impl_passthrough_op_1!(WhiteOp, AttrDistance, Dim); +impl_passthrough_op_1!(WhiteOp, AttrNormal, Dim); +impl_passthrough_op_1!(WhiteOp, AttrTangent, Dim); +impl_passthrough_op_1!(WhiteOp, AttrUv, Dim); + +impl crate::prelude::FieldOperator> for WhiteOp { + fn operator( + &self, + _: &Sdf, + _: &Position, + ) -> as crate::prelude::Attribute>::Output { + Vec4::ONE.into() + } +} + +impl_passthrough_op_2!(WhiteOp, Raycast, 0, SdfA); + +pub type White = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Point, ProxyColor}, + test_op_attrs, + }; + + #[test] + fn test_sdf_color() { + ProxyColor::::default(); + } + + test_op_attrs!(ProxyColor::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_normal.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_normal.rs new file mode 100644 index 0000000..e935277 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_normal.rs @@ -0,0 +1,31 @@ +use crate::{ + impl_passthrough_op_2, + prelude::{AttrColor, AttrDistance, FieldOperator, AttrNormal, Operator, AttrTangent, AttrUv, Raycast}, +}; + +/// Override the normals of an SDF with the normals of another SDF +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ProxyNormalOp; + +impl_passthrough_op_2!(ProxyNormalOp, AttrDistance, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyNormalOp, AttrNormal, 1, SdfB, Dim); +impl_passthrough_op_2!(ProxyNormalOp, AttrTangent, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyNormalOp, AttrUv, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyNormalOp, AttrColor, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyNormalOp, Raycast, 0, SdfA); + +pub type ProxyNormal = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{prelude::{Point, ProxyNormal}, test_op_attrs}; + + #[test] + fn test_sdf_normal() { + ProxyNormal::::default(); + } + + test_op_attrs!(ProxyNormal::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_tangent.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_tangent.rs new file mode 100644 index 0000000..8f88594 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_tangent.rs @@ -0,0 +1,36 @@ +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_2, + prelude::{AttrColor, AttrDistance, FieldOperator, AttrNormal, Operator, Raycast, AttrTangent, AttrUv}, +}; + +/// Override the tangents of an SDF with the tangents of another SDF +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ProxyTangentOp; + +impl_passthrough_op_2!(ProxyTangentOp, AttrDistance, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyTangentOp, AttrNormal, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyTangentOp, AttrTangent, 1, SdfB, Dim); +impl_passthrough_op_2!(ProxyTangentOp, AttrUv, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyTangentOp, AttrColor, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyTangentOp, Raycast, 0, SdfA); + +pub type ProxyTangent = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Point, ProxyTangent}, + test_op_attrs, + }; + + #[test] + fn test_sdf_tangent() { + ProxyTangent::::default(); + } + + test_op_attrs!(ProxyTangent::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_uv.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_uv.rs new file mode 100644 index 0000000..3a6bbb6 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/proxy/proxy_uv.rs @@ -0,0 +1,38 @@ +//! Override the UVs of an SDF with the UVs of another SDF + +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_2, + prelude::{AttrColor, AttrDistance, FieldOperator, AttrNormal, Operator, Raycast, AttrTangent, AttrUv}, +}; + +/// Override the UVs of an SDF with the UVs of another SDF +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ProxyUvOp; + +impl_passthrough_op_2!(ProxyUvOp, AttrDistance, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyUvOp, AttrNormal, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyUvOp, AttrTangent, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyUvOp, AttrUv, 1, SdfB, Dim); +impl_passthrough_op_2!(ProxyUvOp, AttrColor, 0, SdfA, Dim); +impl_passthrough_op_2!(ProxyUvOp, Raycast, 0, SdfA); + +pub type ProxyUv = Operator; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Point, ProxyUv}, + test_op_attrs, + }; + + #[test] + fn test_sdf_uv() { + ProxyUv::::default(); + } + + test_op_attrs!(ProxyUv::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/mod.rs new file mode 100644 index 0000000..6c36c6a --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/mod.rs @@ -0,0 +1,83 @@ +//! Operators dedicating to visualizing 3D distance functions via ray intersection + +pub mod raytrace; +pub mod sphere_trace_lipschitz; +pub mod sphere_trace_naive; + +use rust_gpu_bridge::glam::Vec3; + +use crate::{default, prelude::Attribute}; + +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Raycast; + +impl Attribute for Raycast { + type Input = RaycastInput; + type Output = RaycastOutput; +} + +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +pub struct RaycastInput { + pub eye: Vec3, + pub dir: Vec3, + pub start: f32, + pub end: f32, +} + +impl Default for RaycastInput { + fn default() -> Self { + RaycastInput { + eye: Vec3::ZERO, + dir: -Vec3::Z, + start: 0.0, + end: 1000.0, + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] +#[repr(C)] +pub struct RaycastOutput { + /// Minimum distance encountered between the ray and shape + pub closest_dist: f32, + /// Time at which the closest distance was encountered + pub closest_t: f32, + /// The amount of steps taken by this march + pub steps: u32, +} + +impl Default for RaycastOutput { + fn default() -> Self { + RaycastOutput { + closest_dist: f32::MAX, + closest_t: f32::MAX, + steps: default(), + } + } +} + +impl RaycastOutput { + /// Notify the output that a step was taken at time `t` + /// with a resulting distance of `dist` + pub fn march_step(&mut self, t: f32, dist: f32) { + if dist < self.closest_dist { + self.closest_dist = dist; + self.closest_t = t; + } + } + + /// Notify the output that marching ended in a hit at step `step` + pub fn march_hit(&mut self, step: u32) { + self.steps = step; + } + + /// Notify the output that marching ended in a miss at step `step` + pub fn march_miss(&mut self, step: u32) { + self.steps = step; + } + + pub fn hit(&self) -> bool { + self.closest_dist <= 0.0 + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/raytrace.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/raytrace.rs new file mode 100644 index 0000000..f2462e2 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/raytrace.rs @@ -0,0 +1,55 @@ +//! Analytical raytracer. + +use rust_gpu_bridge::glam::Vec3; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + AttrColor, AttrDistance, FieldOperator, AttrNormal, Operator, Raycast, RaycastInput, RaycastOutput, + AttrTangent, AttrUv, + }, +}; + +/// Compute the intersection between self and the given ray +pub trait RayIntersection { + fn intersect(&self, eye: Vec3, dir: Vec3) -> Option; +} + +/// Analytical raytracer. +/// +/// Evaluates the [`RayIntersection`] of the provided type. +#[derive(Default, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct RaytraceOp; + +impl FieldOperator for RaytraceOp +where + Sdf: RayIntersection, +{ + fn operator( + &self, + sdf: &Sdf, + input: &RaycastInput, + ) -> ::Output { + let mut out = RaycastOutput::default(); + + out.steps = 1; + + if let Some(t) = sdf.intersect(input.eye + input.dir * input.start, input.dir) { + out.closest_t = t; + out.closest_dist = 0.0; + } + + out + } +} + +impl_passthrough_op_1!(RaytraceOp, AttrDistance, Pos,); +impl_passthrough_op_1!(RaytraceOp, AttrNormal, Pos,); +impl_passthrough_op_1!(RaytraceOp, AttrTangent, Pos,); +impl_passthrough_op_1!(RaytraceOp, AttrUv, Pos,); +impl_passthrough_op_1!(RaytraceOp, AttrColor, Pos,); + +pub type Raytrace = Operator; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/sphere_trace_lipschitz.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/sphere_trace_lipschitz.rs new file mode 100644 index 0000000..c944979 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/sphere_trace_lipschitz.rs @@ -0,0 +1,95 @@ +use rust_gpu_bridge::{glam::Vec3, Abs}; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + AttrColor, AttrDistance, Field, FieldOperator, AttrNormal, Operator, Raycast, RaycastOutput, AttrTangent, + AttrUv, + }, +}; + +use super::RaycastInput; + +/// Sphere tracer that operates with respect to a precomputed Lipschitz bound. +/// +/// Costs 1 extra divide per step compared to [`SphereTraceNaive`], +/// but results in overall faster intersections. +/// +/// Note: The precomputed lipschitz bound `k` must be correct in respect to the +/// provided SDF for accurate behaviour; incorrect values will result in visual artifacting. +#[derive(Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SphereTraceLipschitzOp { + pub epsilon: f32, + pub frac_1_k: f32, +} + +impl Default for SphereTraceLipschitzOp { + fn default() -> Self { + SphereTraceLipschitzOp { + epsilon: 0.0001, + frac_1_k: 1.0 / (SphereTraceLipschitzOp::::falloff_k(1.0, 3.0) * 3.0), + } + } +} + +impl SphereTraceLipschitzOp { + // Computes the global lipschitz bound of the falloff function + // e: energy + // R: radius + fn falloff_k(e: f32, r: f32) -> f32 { + 1.72 * e.abs() / r + } +} + +impl FieldOperator for SphereTraceLipschitzOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, input: &RaycastInput) -> RaycastOutput { + let mut out = RaycastOutput::default(); + + let mut t = input.start; + for i in 0..MAX_STEPS { + let pos = input.eye + input.dir * t; + let dist = sdf.field(&pos.into()); + + out.march_step(t, *dist); + + if *dist < 0.0 { + out.march_hit(i); + break; + } + + t += self.epsilon.max(dist.abs() * self.frac_1_k); + + if t > input.end { + out.march_miss(i); + break; + } + } + + out + } +} + +impl_passthrough_op_1!(SphereTraceLipschitzOp, AttrDistance, Pos, const MAX_STEPS: u32); +impl_passthrough_op_1!(SphereTraceLipschitzOp, AttrNormal, Pos, const MAX_STEPS: u32); +impl_passthrough_op_1!(SphereTraceLipschitzOp, AttrTangent, Pos, const MAX_STEPS: u32); +impl_passthrough_op_1!(SphereTraceLipschitzOp, AttrUv, Pos, const MAX_STEPS: u32); +impl_passthrough_op_1!(SphereTraceLipschitzOp, AttrColor, Pos, const MAX_STEPS: u32); + +pub type SphereTraceLipschitz = + Operator, Sdf>; + +impl SphereTraceLipschitz { + pub fn epsilon(&mut self) -> &mut f32 { + self.op().epsilon() + } + + pub fn frac_1_k(&mut self) -> &mut f32 { + self.op().frac_1_k() + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/sphere_trace_naive.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/sphere_trace_naive.rs new file mode 100644 index 0000000..a066d6c --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/raycast/sphere_trace_naive.rs @@ -0,0 +1,78 @@ +use rust_gpu_bridge::{glam::Vec3, Abs}; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + AttrColor, AttrDistance, Field, FieldOperator, AttrNormal, Operator, RaycastInput, Raycast, + RaycastOutput, AttrTangent, AttrUv, + }, +}; + +/// Basic sphere tracer. +/// +/// Marches along a ray, sampling the provided SDF at each step to determine +/// a minimum safe distance for the following iteration. +#[derive(Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SphereTraceNaiveOp { + pub epsilon: f32, +} + +impl Default for SphereTraceNaiveOp { + fn default() -> Self { + SphereTraceNaiveOp { epsilon: 0.0001 } + } +} + +impl FieldOperator + for SphereTraceNaiveOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + input: &RaycastInput, + ) -> ::Output { + let mut out = RaycastOutput::default(); + + let mut t = input.start; + + for step in 0..MAX_STEPS { + let pos = input.eye + input.dir * t; + let dist = sdf.field(&pos.into()); + + out.march_step(t, *dist); + + if *dist < 0.0 { + out.march_hit(step); + break; + } + + t += self.epsilon.max(dist.abs()); + + if t > input.end { + out.march_miss(step); + break; + } + } + + out + } +} + +impl_passthrough_op_1!(SphereTraceNaiveOp, AttrDistance, Pos, const MAX_STEPS: u32); +impl_passthrough_op_1!(SphereTraceNaiveOp, AttrNormal, Pos, const MAX_STEPS: u32); +impl_passthrough_op_1!(SphereTraceNaiveOp, AttrTangent, Pos, const MAX_STEPS: u32); +impl_passthrough_op_1!(SphereTraceNaiveOp, AttrUv, Pos, const MAX_STEPS: u32); +impl_passthrough_op_1!(SphereTraceNaiveOp, AttrColor, Pos, const MAX_STEPS: u32); + +pub type SphereTraceNaive = Operator, Sdf>; + +impl SphereTraceNaive { + pub fn epsilon(&mut self) -> &mut f32 { + self.op().epsilon() + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/axial_reflect.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/axial_reflect.rs new file mode 100644 index 0000000..877b84a --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/axial_reflect.rs @@ -0,0 +1,232 @@ +//! Reflect a distance field about an arbitrary axis. + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Abs, +}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, Attribute, AttrDistance, Field, FieldOperator, AttrNormal, Operator, AttrUv, Distance, Normal, Uv, +}; + +pub const AXIS_X: usize = 1; +pub const AXIS_Y: usize = 2; +pub const AXIS_Z: usize = 4; + +pub const AXIS_XY: usize = AXIS_X | AXIS_Y; +pub const AXIS_XYZ: usize = AXIS_XY | AXIS_Z; + +/// Cheaply reflect a distance field about X / Y / Z using a const axis bitmask. +/// NOTE: Will produce a bound unless any geometry crossing +/// the reflecting planes is already a field w.r.t. its reflection. +#[derive(Debug, Default, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct AxialReflectOp; + +impl FieldOperator for AxialReflectOp +where + Attr: Attribute>, + Sdf: Field, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Attr::Output { + let mut input = **input; + + if AXIS & AXIS_X > 0 { + input = input.abs(); + } + + sdf.field(&input.into()) + } +} + +impl FieldOperator> for AxialReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Distance { + let mut input = **input; + + if AXIS & AXIS_X > 0 { + input.x = input.x.abs(); + } + + if AXIS & AXIS_Y > 0 { + input.y = input.y.abs(); + } + + sdf.field(&input.into()) + } +} + +impl FieldOperator> for AxialReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Normal { + let mut pa = **p; + + if AXIS & AXIS_X > 0 { + pa.x = p.x.abs(); + } + + if AXIS & AXIS_Y > 0 { + pa.y = p.y.abs(); + } + + let mut n = sdf.field(&pa.into()); + + if AXIS & AXIS_X > 0 && p.x < 0.0 { + n.x *= -1.0; + } + + if AXIS & AXIS_Y > 0 && p.y < 0.0 { + n.y *= -1.0; + } + + n + } +} + +impl FieldOperator> for AxialReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Uv { + let mut pa = *p; + + if AXIS & AXIS_X > 0 { + pa.x = p.x.abs(); + } + + if AXIS & AXIS_Y > 0 { + pa.y = p.y.abs(); + } + + let mut n = sdf.field(&pa); + + if AXIS & AXIS_X > 0 && p.x < 0.0 { + n.x *= -1.0; + } + + if AXIS & AXIS_Y > 0 && p.y < 0.0 { + n.y *= -1.0; + } + + n + } +} + +impl FieldOperator> for AxialReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Distance { + let mut p = *p; + + if AXIS & AXIS_X > 0 { + p.x = p.x.abs(); + } + + if AXIS & AXIS_Y > 0 { + p.y = p.y.abs(); + } + + if AXIS & AXIS_Z > 0 { + p.z = p.z.abs(); + } + + sdf.field(&p) + } +} + +impl FieldOperator> for AxialReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Normal { + let mut pa = *p; + + if AXIS & AXIS_X > 0 { + pa.x = p.x.abs(); + } + + if AXIS & AXIS_Y > 0 { + pa.y = p.y.abs(); + } + + if AXIS & AXIS_Z > 0 { + pa.z = p.z.abs(); + } + + let mut n = sdf.field(&pa); + + if AXIS & AXIS_X > 0 && p.x < 0.0 { + n.x *= -1.0; + } + + if AXIS & AXIS_Y > 0 && p.y < 0.0 { + n.y *= -1.0; + } + + if AXIS & AXIS_Z > 0 && p.z < 0.0 { + n.z *= -1.0; + } + + n + } +} + +impl FieldOperator> for AxialReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Uv { + let mut pa = *p; + + if AXIS & AXIS_X > 0 { + pa.x = p.x.abs(); + } + + if AXIS & AXIS_Y > 0 { + pa.y = p.y.abs(); + } + + if AXIS & AXIS_Z > 0 { + pa.z = p.z.abs(); + } + + let mut n = sdf.field(&pa); + + if AXIS & AXIS_X > 0 && p.x < 0.0 { + n.x *= -1.0; + } + + if AXIS & AXIS_Y > 0 && p.y < 0.0 { + n.y *= -1.0; + } + + n + } +} + +/// Reflect a distance field about X / Y / Z +pub type AxialReflect = Operator, Sdf>; + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use crate::{ + prelude::{Circle, Cube}, + test_op_attrs, + }; + + use super::{AxialReflect, AXIS_XYZ}; + + #[test] + fn test_axial_reflect() { + AxialReflect::::default(); + } + + test_op_attrs!(AxialReflect::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/mod.rs new file mode 100644 index 0000000..b92dc6b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/mod.rs @@ -0,0 +1,2 @@ +pub mod axial_reflect; +pub mod reflect; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/reflect.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/reflect.rs new file mode 100644 index 0000000..87e72de --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/reflect/reflect.rs @@ -0,0 +1,177 @@ +//! Reflect a distance field about an arbitrary axis. + +use core::ops::{Mul, Sub}; + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3, Vec3Swizzles}, + Dot, IsNormalized, Mix, Reflect as ReflectTrait, Splat, Step, +}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrUv, Distance, Field, FieldOperator, + Normal, Operator, Uv, +}; + +/// Reflect a distance field about an arbitrary axis. +#[derive(Debug, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ReflectOp { + pub axis: Dim, +} + +impl Default for ReflectOp { + fn default() -> Self { + ReflectOp { axis: 1.0 } + } +} + +impl Default for ReflectOp { + fn default() -> Self { + ReflectOp { axis: Vec2::X } + } +} + +impl Default for ReflectOp { + fn default() -> Self { + ReflectOp { axis: Vec3::X } + } +} + +impl FieldOperator> for ReflectOp +where + Sdf: Field>, + Input: Clone + Sub + Mul + IsNormalized + Dot, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Distance { + assert!( + self.axis.clone().is_normalized(), + "ReflectOp axis must be normalized" + ); + + let q = input.clone() + - self.axis.clone() * (**input).clone().dot(self.axis.clone()).min(0.0) * 2.0; + + sdf.field(&q) + } +} + +impl FieldOperator> for ReflectOp +where + Sdf: Field>, + Input: Clone + + Sub + + Mul + + IsNormalized + + Dot + + ReflectTrait + + Mix + + Splat, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Normal { + assert!( + self.axis.clone().is_normalized(), + "ReflectOp axis must be normalized" + ); + + let c = (**input).clone().dot(self.axis.clone()); + let pc = self.axis.clone() * c.min(0.0) * 2.0; + let q = (**input).clone() - pc; + + let n = (*sdf.field(&q.into())).clone(); + n.clone() + .mix(n.reflect(self.axis.clone()), Input::splat(c.step(0.0))) + .into() + } +} + +impl FieldOperator> for ReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Uv { + assert!( + self.axis.is_normalized(), + "ReflectOp axis must be normalized" + ); + + let c = p; + let pc = c.min(0.0) * 2.0; + let q = **p - pc; + + let n = *sdf.field(&q.into()); + n.mix(n * Vec2::new(-1.0, 1.0), Vec2::splat(c.step(0.0))) + .into() + } +} + +impl FieldOperator> for ReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Uv { + assert!( + self.axis.is_normalized(), + "ReflectOp axis must be normalized" + ); + + let c = p.dot(self.axis); + let pc = self.axis * c.min(0.0) * 2.0; + let q = **p - pc; + + let n = sdf.field(&q.into()); + n.mix(n.reflect(self.axis), Vec2::splat(c.step(0.0))).into() + } +} + +impl FieldOperator> for ReflectOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Uv { + assert!( + self.axis.is_normalized(), + "ReflectOp axis must be normalized" + ); + + let c = p.dot(self.axis); + let pc = self.axis * c.min(0.0) * 2.0; + let q = **p - pc; + + let n = sdf.field(&q.into()); + n.mix(n.reflect(self.axis.xy()), Vec2::splat(c.step(0.0))) + .into() + } +} + +/// Reflect a distance field about an arbitrary axis. +pub type Reflect = Operator, Sdf>; + +impl Reflect { + pub fn axis(&mut self) -> &mut Dim { + &mut self.op.axis + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Point, Sphere}, + test_op_attrs_1d, test_op_attrs_2d, test_op_attrs_3d, + }; + + use super::Reflect; + + #[test] + fn test_reflect() { + Reflect::<_, Sphere>::default().with(Reflect::axis, Vec3::default()); + } + + test_op_attrs_1d!(Reflect::); + test_op_attrs_2d!(Reflect::); + test_op_attrs_3d!(Reflect::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/mod.rs new file mode 100644 index 0000000..63d4928 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/mod.rs @@ -0,0 +1,2 @@ +pub mod repeat_count; +pub mod repeat_infinite; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/repeat_count.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/repeat_count.rs new file mode 100644 index 0000000..a9f2658 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/repeat_count.rs @@ -0,0 +1,104 @@ +//! Operators for repeating distance fields across a domain. + +use core::ops::{Div, Mul, Neg, Sub}; + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Clamp, Round, +}; +use type_fields::macros::Field; + +use crate::prelude::{Attribute, Field, FieldOperator, Operator, Position}; + +/// Repeat a distance field a set number of times in one or more axes. +#[derive(Debug, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct RepeatCountOp { + pub period: Dim, + pub count: Dim, +} + +impl Default for RepeatCountOp { + fn default() -> Self { + RepeatCountOp { + period: 1.0, + count: 1.0, + } + } +} + +impl Default for RepeatCountOp { + fn default() -> Self { + RepeatCountOp { + period: Vec2::ONE, + count: Vec2::ONE, + } + } +} + +impl Default for RepeatCountOp { + fn default() -> Self { + RepeatCountOp { + period: Vec3::ONE, + count: Vec3::ONE, + } + } +} + +impl FieldOperator for RepeatCountOp +where + Attr: Attribute>, + Sdf: Field, + Dim: Clone + + Div + + Neg + + Mul + + Sub + + Round + + Clamp, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + let q = p.clone() + - self.period.clone() + * ((**p).clone() / self.period.clone()) + .round() + .clamp(-self.count.clone(), self.count.clone()); + sdf.field(&q) + } +} + +/// Repeat a distance field a set number of times in one or more axes. +pub type RepeatCount = Operator, Sdf>; + +impl RepeatCount { + pub fn period(&mut self) -> &mut Dim { + &mut self.op.period + } + + pub fn count(&mut self) -> &mut Dim { + &mut self.op.count + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Point, RepeatCount, Sphere}, + test_op_attrs_1d, test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_repeat_count() { + RepeatCount::<_, Sphere>::default() + .with(RepeatCount::period, Vec3::default()) + .with(RepeatCount::count, Vec3::default()); + } + + test_op_attrs_1d!(RepeatCount::); + test_op_attrs_2d!(RepeatCount::); + test_op_attrs_3d!(RepeatCount::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/repeat_infinite.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/repeat_infinite.rs new file mode 100644 index 0000000..d647ce4 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/repeat/repeat_infinite.rs @@ -0,0 +1,84 @@ +use core::ops::{Add, Mul, Sub}; + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Mod, +}; +use type_fields::macros::Field; + +use crate::prelude::{Attribute, Field, FieldOperator, Operator, Position}; + +/// Repeat a distance field infinitely in one or more axes. +#[derive(Debug, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct RepeatInfiniteOp { + pub period: Dim, +} + +impl Default for RepeatInfiniteOp { + fn default() -> Self { + RepeatInfiniteOp { period: 1.0 } + } +} + +impl Default for RepeatInfiniteOp { + fn default() -> Self { + RepeatInfiniteOp { period: Vec2::ONE } + } +} + +impl Default for RepeatInfiniteOp { + fn default() -> Self { + RepeatInfiniteOp { period: Vec3::ONE } + } +} + +impl FieldOperator for RepeatInfiniteOp +where + Attr: Attribute>, + Sdf: Field, + Input: Add + + Add + + Sub + + Mul + + Mul + + Mod + + Clone, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + let q = ((**p).clone().add(0.5).mul(self.period.clone())) + .modulo(self.period.clone()) + .sub(self.period.clone().mul(0.5)); + sdf.field(&q.into()) + } +} + +/// Repeat a distance field infinitely in one or more axes. +pub type RepeatInfinite = Operator, Sdf>; + +impl RepeatInfinite { + pub fn period(&mut self) -> &mut Dim { + &mut self.op.period + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Point, RepeatInfinite, Sphere}, + test_op_attrs_1d, test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_repeat_infinite() { + RepeatInfinite::<_, Sphere>::default().with(RepeatInfinite::period, Vec3::default()); + } + + test_op_attrs_1d!(RepeatInfinite::); + test_op_attrs_2d!(RepeatInfinite::); + test_op_attrs_3d!(RepeatInfinite::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/scale_uv.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/scale_uv.rs new file mode 100644 index 0000000..cb735ef --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/scale_uv.rs @@ -0,0 +1,47 @@ +use rust_gpu_bridge::glam::Vec2; + +use crate::{ + impl_passthrough_op_1, + prelude::{ + items::position::Position, AttrColor, AttrDistance, AttrNormal, AttrTangent, AttrUv, Field, + Raycast, + }, +}; + +use super::{FieldOperator, Operator}; + +#[derive(Copy, Clone, PartialEq, type_fields::macros::Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +pub struct ScaleUvOp { + pub scale: Vec2, +} + +impl Default for ScaleUvOp { + fn default() -> Self { + ScaleUvOp { + scale: Vec2::ONE * 10.0, + } + } +} + +impl FieldOperator> for ScaleUvOp +where + Sdf: Field>, +{ + fn operator( + &self, + sdf: &Sdf, + p: &Position, + ) -> as crate::prelude::Attribute>::Output { + let uv = *sdf.field(p); + (uv * self.scale).into() + } +} + +impl_passthrough_op_1!(ScaleUvOp, AttrDistance, Dim); +impl_passthrough_op_1!(ScaleUvOp, AttrNormal, Dim); +impl_passthrough_op_1!(ScaleUvOp, AttrTangent, Dim); +impl_passthrough_op_1!(ScaleUvOp, AttrColor, Dim); +impl_passthrough_op_1!(ScaleUvOp, Raycast,); + +pub type ScaleUv = Operator; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/sided.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/sided.rs new file mode 100644 index 0000000..e0fe32b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/sided.rs @@ -0,0 +1,104 @@ +//! Given an infinitely-thin surface, +//! divide space into interior and exterior based on axis. + +use core::ops::Mul; + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Dot, Sign, +}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrUv, Distance, Field, Normal, Uv, +}; + +use super::{FieldOperator, Operator}; + +/// Given an infinitely-thin surface, +/// divide space into interior and exterior based on axis. +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SidedOp { + pub axis: Dim, +} + +impl Default for SidedOp { + fn default() -> Self { + SidedOp { axis: 1.0 } + } +} + +impl Default for SidedOp { + fn default() -> Self { + SidedOp { axis: Vec2::Y } + } +} + +impl Default for SidedOp { + fn default() -> Self { + SidedOp { axis: Vec3::Y } + } +} + +impl FieldOperator> for SidedOp +where + Sdf: Field>, + Input: Clone + Mul + Sign + Dot, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Distance { + (*sdf.field(p) * (**p).clone().dot(self.axis.clone()).sign()).into() + } +} + +impl FieldOperator> for SidedOp +where + Sdf: Field>, + Input: Clone + Dot + Mul, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Normal { + let n = (*sdf.field(p)).clone(); + (n * (**p).clone().dot(self.axis.clone()).sign()).into() + } +} + +impl FieldOperator> for SidedOp +where + Sdf: Field>, + Input: Clone + Dot + Mul, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Uv { + ((*sdf.field(p)).clone() * (**p).clone().dot(self.axis.clone()).sign()).into() + } +} + +pub type Sided = Operator, Sdf>; + +/// Given an infinitely-thin surface, +/// divide space into interior and exterior based on axis. +impl Sided { + pub fn axis(&mut self) -> &mut Dim { + &mut self.op.axis + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Line, Point, Sided}, + test_op_attrs_1d, test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_sided() { + Sided::<_, Line>::default().with(Sided::axis, Vec3::default()); + } + + test_op_attrs_1d!(Sided::); + test_op_attrs_2d!(Sided::); + test_op_attrs_3d!(Sided::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/mod.rs new file mode 100644 index 0000000..42df966 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/mod.rs @@ -0,0 +1,3 @@ +pub mod smooth_intersection; +pub mod smooth_subtraction; +pub mod smooth_union; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_intersection.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_intersection.rs new file mode 100644 index 0000000..0666cc4 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_intersection.rs @@ -0,0 +1,163 @@ +//! Compute the blended boolean intersection of two distance fields. + +use core::ops::{Add, Div, Mul, Sub}; + +use rust_gpu_bridge::{glam::Vec2, Clamp, Mix, Normalize, Saturate, Splat, Step}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrTangent, AttrUv, Distance, Field, + FieldOperator, Normal, Operator, Tangent, Uv, +}; + +/// Compute the blended boolean intersection of two distance fields. +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SmoothIntersectionOp { + pub k: f32, +} + +impl FieldOperator<(SdfA, SdfB), AttrDistance> for SmoothIntersectionOp +where + SdfA: Field>, + SdfB: Field>, + Input: Clone, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Distance { + let d1 = *sdf_a.field(p); + let d2 = *sdf_b.field(p); + let h = (0.5 - 0.5 * (d2 - d1) / self.k).clamp(0.0, 1.0); + d2.mix(d1, h).add(self.k.mul(h).mul(1.0 - h)).into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrNormal> for SmoothIntersectionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Dim: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Normal { + let d1 = (*Field::>::field(sdf_a, p)).clone(); + let d2 = (*Field::>::field(sdf_b, p)).clone(); + + let h = (d2 - d1).div(self.k).mul(0.5).sub(0.5).saturate(); + + let n1 = (*Field::>::field(sdf_a, p)).clone(); + let n2 = (*Field::>::field(sdf_b, p)).clone(); + + n2.mix(n1, Dim::splat(h)).normalize().into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrTangent> for SmoothIntersectionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Input: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Tangent { + let d1 = (*Field::>::field(sdf_a, p)).clone(); + let d2 = (*Field::>::field(sdf_b, p)).clone(); + + let h = (d2 - d1).div(self.k).mul(0.5).sub(0.5).saturate(); + + let n1 = (*Field::>::field(sdf_a, p)).clone(); + let n2 = (*Field::>::field(sdf_b, p)).clone(); + + n2.mix(n1, Input::splat(h)).normalize().into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrUv> for SmoothIntersectionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Input: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Uv { + let d1 = (*Field::>::field(sdf_a, p)).clone(); + let d2 = (*Field::>::field(sdf_b, p)).clone(); + + let h = (d2 - d1).div(self.k).mul(0.5).sub(0.5).saturate(); + + let uv1 = *Field::>::field(sdf_a, p); + let uv2 = *Field::>::field(sdf_b, p); + + uv2.mix(uv1, Vec2::splat(h.step(0.5))).into() + } +} + +/// Compute the blended boolean intersection of two distance fields. +pub type SmoothIntersection = Operator; + +impl SmoothIntersection { + pub fn sdf_a(&mut self) -> &mut SdfA { + &mut self.target().0 + } + + pub fn sdf_b(&mut self) -> &mut SdfB { + &mut self.target().1 + } + + pub fn k(&mut self) -> &mut f32 { + self.op().k() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use type_fields::field::Field; + + use crate::{ + prelude::{Cube, Point, SmoothIntersection, Sphere}, + test_op_attrs, + }; + + #[test] + fn test_smooth_intersection() { + SmoothIntersection::::default().with(SmoothIntersection::k, f32::default()); + } + + test_op_attrs!(SmoothIntersection::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_subtraction.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_subtraction.rs new file mode 100644 index 0000000..55e3aad --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_subtraction.rs @@ -0,0 +1,170 @@ +//! Compute the blended boolean subtraction of two distance fields. +use core::ops::{Add, Div, Mul, Sub}; + +use rust_gpu_bridge::{glam::Vec2, Clamp, Mix, Normalize, Saturate, Splat, Step}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrTangent, AttrUv, Distance, Field, + FieldOperator, Normal, Operator, Tangent, Uv, +}; + +/// Compute the blended boolean subtraction of two distance fields. +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SmoothSubtractionOp { + pub k: f32, +} + +impl FieldOperator<(SdfA, SdfB), AttrDistance> for SmoothSubtractionOp +where + SdfA: Field>, + SdfB: Field>, + Input: Clone, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Distance { + let d1 = *sdf_a.field(p); + let d2 = *sdf_b.field(p); + let h = (0.5 - 0.5 * (d2 + d1) / self.k).clamp(0.0, 1.0); + d2.mix(-d1, h).add(self.k.mul(h).mul(1.0 - h)).into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrNormal> for SmoothSubtractionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Input: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Normal { + let d1 = (*Field::>::field(sdf_a, p)).clone(); + let d2 = (*Field::>::field(sdf_b, p)).clone(); + + let h = (d2 + d1).div(self.k).mul(0.5).sub(0.5).saturate(); + + let n1 = (*Field::>::field(sdf_a, p)).clone(); + let n2 = (*Field::>::field(sdf_b, p)).clone(); + + n2.mix(n1.mul(-1.0), Input::splat(h)).normalize().into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrTangent> for SmoothSubtractionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Input: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Tangent { + let d1 = *Field::>::field(sdf_a, p); + let d2 = *Field::>::field(sdf_b, p); + + let h = (d2.clone() + d1.clone()) + .div(self.k) + .mul(0.5) + .sub(0.5) + .saturate(); + + let t1 = (*Field::>::field(sdf_a, p)).clone(); + let t2 = (*Field::>::field(sdf_b, p)).clone(); + + t2.mix(t1.mul(-1.0), Input::splat(h)).normalize().into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrUv> for SmoothSubtractionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Input: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Uv { + let d1 = *Field::>::field(sdf_a, p); + let d2 = *Field::>::field(sdf_b, p); + + let h = (d2.clone() + d1.clone()) + .div(self.k) + .mul(0.5) + .sub(0.5) + .saturate(); + + let uv1 = *Field::>::field(sdf_a, p); + let uv2 = *Field::>::field(sdf_b, p); + + uv2.mix(uv1.mul(-1.0), Vec2::splat(h.step(0.5))).into() + } +} + +/// Compute the blended boolean subtraction of two distance fields. +pub type SmoothSubtraction = Operator; + +impl SmoothSubtraction { + pub fn sdf_a(&mut self) -> &mut SdfA { + &mut self.target().0 + } + + pub fn sdf_b(&mut self) -> &mut SdfB { + &mut self.target().1 + } + + pub fn k(&mut self) -> &mut f32 { + &mut self.op().k + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use type_fields::field::Field; + + use crate::{ + prelude::{Cube, Point, SmoothSubtraction, Sphere}, + test_op_attrs, + }; + + #[test] + fn test_smooth_subtraction() { + SmoothSubtraction::::default().with(SmoothSubtraction::k, f32::default()); + } + + test_op_attrs!(SmoothSubtraction::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_union.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_union.rs new file mode 100644 index 0000000..ecbe518 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/smooth_boolean/smooth_union.rs @@ -0,0 +1,163 @@ +//! Compute the blended boolean union of two distance fields. + +use core::ops::{Add, Div, Mul, Sub}; + +use rust_gpu_bridge::{Clamp, Mix, Normalize, Saturate, Splat}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrTangent, AttrUv, Distance, Field, + FieldOperator, Normal, Operator, Tangent, Uv, +}; + +/// Compute the blended boolean union of two distance fields. +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct SmoothUnionOp { + pub k: f32, +} + +impl FieldOperator<(SdfA, SdfB), AttrDistance> for SmoothUnionOp +where + SdfA: Field>, + SdfB: Field>, + Input: Clone, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Distance { + let d1 = *sdf_a.field(input); + let d2 = *sdf_b.field(input); + let h = (0.5 + 0.5 * (d2 - d1) / self.k).clamp(0.0, 1.0); + d2.mix(d1, h).sub(self.k * h * (1.0 - h)).into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrNormal> for SmoothUnionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Input: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Normal { + let d1 = *Field::>::field(sdf_a, input); + let d2 = *Field::>::field(sdf_b, input); + + let h = ((d2 - d1).div(self.k).mul(0.5).add(0.5)).saturate(); + + let n1 = (*Field::>::field(sdf_a, input)).clone(); + let n2 = (*Field::>::field(sdf_b, input)).clone(); + + n2.mix(n1, Input::splat(h)).normalize().into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrTangent> for SmoothUnionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Dim: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), p: &Position) -> Tangent { + let d1 = *Field::>::field(sdf_a, p); + let d2 = *Field::>::field(sdf_b, p); + let h = ((d2 - d1).div(self.k).mul(0.5).add(0.5)).saturate(); + + let t1 = (*Field::>::field(sdf_a, p)).clone(); + let t2 = (*Field::>::field(sdf_b, p)).clone(); + + t2.mix(t1, Dim::splat(h)).normalize().into() + } +} + +impl FieldOperator<(SdfA, SdfB), AttrUv> for SmoothUnionOp +where + SdfA: Field>, + SdfA: Field>, + SdfB: Field>, + SdfB: Field>, + Input: Clone + + Sub + + Div + + Mul + + Mul + + Add + + Clamp + + Mix + + Saturate + + Normalize + + Splat, +{ + fn operator(&self, (sdf_a, sdf_b): &(SdfA, SdfB), input: &Position) -> Uv { + let d1 = *Field::>::field(sdf_a, input); + let d2 = *Field::>::field(sdf_b, input); + + let h = ((d2 - d1).div(self.k).mul(0.5).add(0.5)).saturate(); + + let uv1 = Field::>::field(sdf_a, input); + let uv2 = Field::>::field(sdf_b, input); + + if h > 0.5 { + uv1 + } else { + uv2 + } + } +} + +/// Compute the blended boolean union of two distance fields. +pub type SmoothUnion = Operator; + +impl SmoothUnion { + pub fn sdf_a(&mut self) -> &mut SdfA { + &mut self.target().0 + } + + pub fn sdf_b(&mut self) -> &mut SdfB { + &mut self.target().1 + } + + pub fn k(&mut self) -> &mut f32 { + &mut self.op.k + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use type_fields::field::Field; + + use crate::{ + prelude::{Cube, Point, SmoothUnion, Sphere}, + test_op_attrs, + }; + + #[test] + fn test_smooth_union() { + SmoothUnion::::default().with(SmoothUnion::k, f32::default()); + } + + test_op_attrs!(SmoothUnion::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/stretch.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/stretch.rs new file mode 100644 index 0000000..a2e5360 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/stretch.rs @@ -0,0 +1,170 @@ +//! Stretch a shape along an arbitrary axis, preserving exterior geometry as caps. + +use core::ops::{Mul, Sub}; + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Dot, IsNormalized, +}; +use type_fields::macros::Field; + +use crate::prelude::{items::position::Position, Attribute, Field, FieldOperator, Operator}; + +/// Extrude a shape infinitely along an arbitrary axis. +#[derive(Debug, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct StretchInfiniteOp { + pub dir: Dim, +} + +impl Default for StretchInfiniteOp { + fn default() -> Self { + StretchInfiniteOp { dir: 1.0 } + } +} + +impl Default for StretchInfiniteOp { + fn default() -> Self { + StretchInfiniteOp { dir: Vec2::X } + } +} + +impl Default for StretchInfiniteOp { + fn default() -> Self { + StretchInfiniteOp { dir: Vec3::X } + } +} + +impl FieldOperator for StretchInfiniteOp +where + Attr: Attribute>, + Sdf: Field, + Input: Clone + Mul + Sub + IsNormalized + Dot, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Attr::Output { + assert!( + self.dir.clone().is_normalized(), + "ExtrudeInfiniteOp dir must be normalized" + ); + let q = (*input).clone() - self.dir.clone() * (**input).clone().dot(self.dir.clone()); + sdf.field(&q) + } +} + +/// Extrude a shape infinitely along an arbitrary axis. +pub type StretchInfinite = Operator, Sdf>; + +impl StretchInfinite { + pub fn dir(&mut self) -> &mut Dim { + &mut self.op.dir + } +} + +/// Extrude a shape by an arbitrary distance along an arbitrary axis, preserving exterior geometry as caps. +#[derive(Debug, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct StretchDistOp { + pub dir: Dim, + pub dist: f32, +} + +impl Default for StretchDistOp { + fn default() -> Self { + StretchDistOp { + dir: 1.0, + dist: 1.0, + } + } +} + +impl Default for StretchDistOp { + fn default() -> Self { + StretchDistOp { + dir: Vec2::X, + dist: 1.0, + } + } +} + +impl Default for StretchDistOp { + fn default() -> Self { + StretchDistOp { + dir: Vec3::X, + dist: 1.0, + } + } +} + +impl FieldOperator for StretchDistOp +where + Attr: Attribute>, + Sdf: Field, + Input: Clone + Mul + Sub + Dot, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Attr::Output { + let q = (*input).clone() + - (self.dir.clone() + * (**input) + .clone() + .dot(self.dir.clone()) + .clamp(-self.dist, self.dist)); + sdf.field(&q) + } +} + +/// Extrude a shape by an arbitrary distance along an arbitrary axis, preserving exterior geometry as caps. +pub type StretchDist = Operator, Sdf>; + +impl StretchDist { + pub fn dir(&mut self) -> &mut Dim { + &mut self.op.dir + } + + pub fn dist(&mut self) -> &mut f32 { + &mut self.op.dist + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test_stretch_infinite { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Cube, Point, StretchInfinite}, + test_op_attrs_1d, test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_stretch_infinite() { + StretchInfinite::<_, Cube>::default().with(StretchInfinite::dir, Vec3::default()); + } + + test_op_attrs_1d!(StretchInfinite::); + test_op_attrs_2d!(StretchInfinite::); + test_op_attrs_3d!(StretchInfinite::); +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test_stretch_dist { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Cube, Point, StretchDist}, + test_op_attrs_1d, test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_stretch_dist() { + StretchDist::<_, Cube>::default() + .with(StretchDist::dir, Vec3::default()) + .with(StretchDist::dist, f32::default()); + } + + test_op_attrs_1d!(StretchDist::); + test_op_attrs_2d!(StretchDist::); + test_op_attrs_3d!(StretchDist::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/mod.rs new file mode 100644 index 0000000..601408a --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/mod.rs @@ -0,0 +1,40 @@ +pub mod rotate; +pub mod scale; +pub mod translate; + +use rust_gpu_bridge::glam::Quat; + +use crate::prelude::{Rotate3d, Scale, Translate}; + +/// Translate, rotate, and scale the wrapped SDF. +pub type Transform = Translate>>; + +impl Transform { + pub fn rotation(&mut self) -> &mut Quat { + &mut self.target.op.rotation + } + + pub fn scale(&mut self) -> &mut f32 { + &mut self.target.target.op.scale + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use rust_gpu_bridge::glam::{Quat, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Cube, Sphere, Transform}, + test_op_attrs_3d, + }; + + #[test] + fn test_transform() { + Transform::::default() + .with(Transform::rotation, Quat::default()) + .with(Transform::scale, f32::default()); + } + + test_op_attrs_3d!(Transform::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/rotate.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/rotate.rs new file mode 100644 index 0000000..caaba76 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/rotate.rs @@ -0,0 +1,91 @@ +//! Rotate a distance field. +use core::fmt::Debug; + +use rust_gpu_bridge::glam::{Quat, Vec2, Vec3}; +use type_fields::macros::Field; + +use crate::prelude::{items::position::Position, Attribute, Field, FieldOperator, Operator}; + +/// Rotate a distance field. +#[derive(Debug, Default, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct Rotate2dOp { + pub angle: f32, +} + +impl FieldOperator for Rotate2dOp +where + Attr: Attribute>, + Sdf: Field, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + sdf.field(&Vec2::from_angle(-self.angle).rotate(**p).into()) + } +} + +/// Rotate a 3D distance field. +pub type Rotate2d = Operator; + +impl Rotate2d { + pub fn angle(&mut self) -> &mut f32 { + &mut self.op.angle + } +} + +/// Rotate a distance field. +#[derive(Default, Copy, Clone, PartialEq, Field)] +#[repr(C)] +pub struct Rotate3dOp { + pub rotation: Quat, +} + +#[cfg(not(feature = "spirv-std"))] +impl Debug for Rotate3dOp { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.rotation.fmt(f) + } +} + +impl FieldOperator for Rotate3dOp +where + Attr: Attribute>, + Sdf: Field, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + sdf.field(&(self.rotation.inverse() * **p).into()) + } +} + +/// Rotate a distance field. +pub type Rotate3d = Operator; + +impl Rotate3d { + pub fn rotation(&mut self) -> &mut Quat { + &mut self.op.rotation + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use rust_gpu_bridge::glam::Quat; + use type_fields::field::Field; + + use crate::{ + prelude::{Cube, Point, Rotate2d, Rotate3d, Square}, + test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_rotate_2d() { + Rotate2d::::default().with(Rotate2d::angle, f32::default()); + } + + #[test] + fn test_rotate_3d() { + Rotate3d::::default().with(Rotate3d::rotation, Quat::default()); + } + + test_op_attrs_2d!(Rotate2d::); + test_op_attrs_3d!(Rotate3d::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/scale.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/scale.rs new file mode 100644 index 0000000..12fc893 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/scale.rs @@ -0,0 +1,53 @@ +//! Uniformly scale a distance field. + +use core::ops::{Div, Mul}; + +use type_fields::macros::Field; + +use crate::prelude::{Attribute, Field, FieldOperator, Operator}; + +/// Uniformly scale a distance field. +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ScaleOp { + pub scale: f32, +} + +impl FieldOperator for ScaleOp +where + Attr: Attribute, + Sdf: Field, + Attr::Input: Clone + Div, + Attr::Output: Mul, +{ + fn operator(&self, sdf: &Sdf, input: &Attr::Input) -> Attr::Output { + sdf.field(&(input.clone() / self.scale)).mul(self.scale) + } +} + +/// Uniformly scale a distance field. +pub type Scale = Operator; + +impl Scale { + pub fn scale(&mut self) -> &mut f32 { + &mut self.op.scale + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use type_fields::field::Field; + + use crate::{ + prelude::{Cube, Point, Scale}, + test_op_attrs, + }; + + #[test] + fn test_scale() { + Scale::::default().with(Scale::scale, f32::default()); + } + + test_op_attrs!(Scale::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/translate.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/translate.rs new file mode 100644 index 0000000..c14d261 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/transform/translate.rs @@ -0,0 +1,55 @@ +//! Apply a positional translation to a distance field. + +use core::ops::Sub; + +use type_fields::macros::Field; + +use crate::prelude::{items::position::Position, Attribute, Field, FieldOperator, Operator}; + +/// Apply a positional translation to a distance field. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct TranslateOp { + pub translation: Dim, +} + +impl FieldOperator for TranslateOp +where + Attr: Attribute>, + Sdf: Field, + Input: Clone + Sub, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + sdf.field(&(p.clone() - self.translation.clone()).into()) + } +} + +/// Apply a positional translation to a distance field. +pub type Translate = Operator, Sdf>; + +impl Translate { + pub fn translation(&mut self) -> &mut Dim { + &mut self.op.translation + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Point, Sphere, Translate}, + test_op_attrs_1d, test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_translation() { + Translate::<_, Sphere>::default().with(Translate::translation, Vec3::default()); + } + + test_op_attrs_1d!(Translate::); + test_op_attrs_2d!(Translate::); + test_op_attrs_3d!(Translate::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/triplanar_uv.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/triplanar_uv.rs new file mode 100644 index 0000000..b53e180 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/triplanar_uv.rs @@ -0,0 +1,69 @@ +use rust_gpu_bridge::{ + glam::{Vec3, Vec3Swizzles}, + Pow, +}; +use type_fields::macros::Field; + +use crate::{ + impl_passthrough_op_1, + prelude::{AttrColor, AttrDistance, Field, AttrNormal, AttrTangent, AttrUv, items::position::Position}, +}; + +use super::{FieldOperator, Operator}; + +/// Apply triplanar UV mapping to the provided SDF +#[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct TriplanarUvOp { + pub k: f32, +} + +impl FieldOperator> for TriplanarUvOp +where + Sdf: Field>, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> as crate::prelude::Attribute>::Output { + let front = input.xy(); + let side = input.zy(); + let top = input.xz(); + + let weights = sdf + .field(input) + .abs() + .pow(Vec3::splat(self.k)) + .normalize(); + + (front * weights.z + side * weights.x + top * weights.y).into() + } +} + +impl_passthrough_op_1!(TriplanarUvOp, AttrDistance, Dim); +impl_passthrough_op_1!(TriplanarUvOp, AttrNormal, Dim); +impl_passthrough_op_1!(TriplanarUvOp, AttrTangent, Dim); +impl_passthrough_op_1!(TriplanarUvOp, AttrColor, Dim); + +pub type TriplanarUv = Operator; + +impl TriplanarUv { + pub fn k(&mut self) -> &mut f32 { + self.op().k() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::{ + prelude::{Point, Sphere}, + test_op_attrs_3d, + }; + + use super::TriplanarUv; + + #[test] + fn test_triplanar_uv() { + TriplanarUv::::default(); + } + + test_op_attrs_3d!(TriplanarUv::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/twist.rs b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/twist.rs new file mode 100644 index 0000000..1ef455b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/field_operator/twist.rs @@ -0,0 +1,99 @@ +//! Twist a distance field around an arbitrary axis. + +use rust_gpu_bridge::glam::{Quat, Vec2, Vec3}; +use type_fields::macros::Field; + +use crate::prelude::{items::position::Position, Attribute, Field}; + +use super::{FieldOperator, Operator}; + +/// Twist a distance field around an arbitrary axis. +#[derive(Debug, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct TwistOp { + pub axis_pos: Dim, + pub axis_rot: Dim, + pub k: f32, +} + +impl Default for TwistOp { + fn default() -> Self { + TwistOp { + axis_pos: Vec2::Y, + axis_rot: Vec2::Y, + k: 1.0, + } + } +} + +impl Default for TwistOp { + fn default() -> Self { + TwistOp { + axis_pos: Vec3::Y, + axis_rot: Vec3::Y, + k: 1.0, + } + } +} + +impl FieldOperator for TwistOp +where + Attr: Attribute>, + Sdf: Field, +{ + fn operator(&self, sdf: &Sdf, input: &Position) -> Attr::Output { + let q = Vec2::from_angle(self.k * self.axis_pos.dot(**input)).rotate(**input); + sdf.field(&q.into()) + } +} + +impl FieldOperator for TwistOp +where + Attr: Attribute>, + Sdf: Field, +{ + fn operator(&self, sdf: &Sdf, p: &Position) -> Attr::Output { + let q = Quat::from_axis_angle(self.axis_rot, self.k * self.axis_pos.dot(**p)) * **p; + sdf.field(&q.into()) + } +} + +/// Twist a distance field around an arbitrary axis. +pub type Twist = Operator, Sdf>; + +impl Twist { + pub fn axis_pos(&mut self) -> &mut Dim { + &mut self.op.axis_pos + } + + pub fn axis_rot(&mut self) -> &mut Dim { + &mut self.op.axis_rot + } + + pub fn k(&mut self) -> &mut f32 { + &mut self.op.k + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + use type_fields::field::Field; + + use crate::{ + prelude::{Point, Torus, Twist}, + test_op_attrs_2d, test_op_attrs_3d, + }; + + #[test] + fn test_twist() { + Twist::<_, Torus>::default() + .with(Twist::axis_pos, Vec3::default()) + .with(Twist::axis_rot, Vec3::default()) + .with(Twist::k, f32::default()); + } + + test_op_attrs_2d!(Twist::); + test_op_attrs_3d!(Twist::); +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/metric/chebyshev.rs b/bevy-app/crates/rust-gpu-sdf/src/field/metric/chebyshev.rs new file mode 100644 index 0000000..bfc95a6 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/metric/chebyshev.rs @@ -0,0 +1,81 @@ +//! Chebyshev distance metric. + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Abs, Mix, Sign, Step, +}; + +use crate::prelude::{AttrDistance, Field, AttrNormal, items::position::Position, Distance, Normal}; + +/// Chebyshev distance metric. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct ChebyshevMetric; + +impl Field> for ChebyshevMetric { + fn field(&self, p: &Position) -> Distance { + p.abs().into() + } +} + +impl Field> for ChebyshevMetric { + fn field(&self, p: &Position) -> Distance { + p.x.abs().max(p.y.abs()).into() + } +} + +impl Field> for ChebyshevMetric { + fn field(&self, p: &Position) -> Distance { + p.x.abs().max(p.y.abs()).max(p.z.abs()).into() + } +} + +impl Field> for ChebyshevMetric { + fn field(&self, p: &Position) -> Normal { + p.sign().into() + } +} + +impl Field> for ChebyshevMetric { + fn field(&self, p: &Position) -> Normal { + let a = p.abs(); + let s = p.sign(); + + (Vec2::X * s.x).mix(Vec2::Y * s.y, Vec2::splat(a.x.step(a.y))).into() + } +} + +impl Field> for ChebyshevMetric { + fn field(&self, p: &Position) -> Normal { + let a = p.abs(); + let s = p.sign(); + + (Vec3::X * s.x) + .mix(Vec3::Z * s.z, Vec3::splat(a.x.step(a.z))) + .mix( + (Vec3::Y * s.y).mix(Vec3::Z * s.z, Vec3::splat(a.y.step(a.z))), + Vec3::splat(a.x.step(a.y)), + ) + .into() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + + use crate::prelude::{BoundTester, ChebyshevMetric}; + + #[test] + #[should_panic] + pub fn test_chebyshev_metric_2d() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + #[should_panic] + pub fn test_chebyshev_metric_3d() { + assert!(BoundTester::::default().is_field_3d()); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/metric/euclidean.rs b/bevy-app/crates/rust-gpu-sdf/src/field/metric/euclidean.rs new file mode 100644 index 0000000..a2ce57a --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/metric/euclidean.rs @@ -0,0 +1,78 @@ +//! Euclidean distance metric. + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Asin, Atan2, Length, Normalize, +}; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, AttrUv, Distance, Field, Normal, Uv, +}; + +/// Euclidian distance metric. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[cfg_attr(feature = "bevy", derive(bevy::reflect::TypeUuid))] +#[cfg_attr(feature = "bevy", uuid = "9c0e79ee-c437-47aa-9230-d3c13f3bacb8")] +#[repr(C)] +pub struct EuclideanMetric; + +impl Field> for EuclideanMetric +where + Input: Clone + Length, +{ + fn field(&self, input: &Position) -> Distance { + (**input).clone().length().into() + } +} + +impl Field> for EuclideanMetric +where + Dim: Default + Clone + PartialEq + Normalize, +{ + fn field(&self, input: &Position) -> Normal { + let d = Dim::default(); + if **input == d { + return d.into(); + } + + (**input).clone().normalize().into() + } +} + +impl Field> for EuclideanMetric { + fn field(&self, p: &Position) -> Uv { + Vec2::new(**p, 0.0).into() + } +} + +impl Field> for EuclideanMetric { + fn field(&self, p: &Position) -> Uv { + Vec2::new((p.x.atan2(p.y) / core::f32::consts::TAU) + 0.5, p.length()).into() + } +} + +impl Field> for EuclideanMetric { + fn field(&self, p: &Position) -> Uv { + Vec2::new( + (p.x.atan2(p.z) / core::f32::consts::TAU) + 0.5, + (p.y.asin() / core::f32::consts::PI) + 0.5, + ) + .into() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::prelude::{BoundTester, EuclideanMetric}; + + #[test] + fn test_euclidean_metric_2d() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_euclidean_metric_3d() { + assert!(BoundTester::::default().is_field_3d()); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/metric/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/metric/mod.rs new file mode 100644 index 0000000..7284b7f --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/metric/mod.rs @@ -0,0 +1,6 @@ +//! Distance metrics. + +pub mod chebyshev; +pub mod euclidean; +pub mod taxicab; +pub mod superellipse; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/metric/superellipse.rs b/bevy-app/crates/rust-gpu-sdf/src/field/metric/superellipse.rs new file mode 100644 index 0000000..87a50d1 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/metric/superellipse.rs @@ -0,0 +1,46 @@ +use rust_gpu_bridge::{glam::Vec2, Abs, Pow, Sign}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, Distance, Field, Normal, +}; + +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct Superellipse { + pub n: f32, +} + +impl Default for Superellipse { + fn default() -> Self { + Superellipse { n: 1.0 } + } +} + +impl Field> for Superellipse { + fn field(&self, p: &Position) -> Distance { + (p.x.abs().pow(self.n) + p.y.abs().pow(self.n)) + .pow(1.0 / self.n) + .into() + } +} + +impl Field> for Superellipse { + fn field(&self, p: &Position) -> Normal { + (p.abs().pow(Vec2::splat(self.n)).normalize() * p.sign()).into() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::prelude::BoundTester; + + use super::Superellipse; + + #[test] + #[should_panic] + fn test_lame_curve() { + assert!(BoundTester::::default().is_field_2d()) + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/metric/taxicab.rs b/bevy-app/crates/rust-gpu-sdf/src/field/metric/taxicab.rs new file mode 100644 index 0000000..09d66c1 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/metric/taxicab.rs @@ -0,0 +1,62 @@ +//! Taxicab distance metric. + +use core::ops::Add; + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Abs, Normalize, Sign, +}; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, Distance, Field, Normal, +}; + +/// Taxicab distance metric. +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct TaxicabMetric; + +impl Field> for TaxicabMetric { + fn field(&self, p: &Position) -> Distance { + p.abs().into() + } +} + +impl Field> for TaxicabMetric { + fn field(&self, p: &Position) -> Distance { + p.x.abs().add(p.y.abs()).into() + } +} + +impl Field> for TaxicabMetric { + fn field(&self, p: &Position) -> Distance { + p.x.abs().add(p.y.abs()).add(p.z.abs()).into() + } +} + +impl Field> for TaxicabMetric +where + Input: Clone + Sign + Normalize, +{ + fn field(&self, input: &Position) -> Normal { + (**input).clone().sign().normalize().into() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::prelude::{BoundTester, TaxicabMetric}; + + #[test] + #[should_panic] + pub fn test_taxicab_metric_2d() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + #[should_panic] + pub fn test_taxicab_metric_3d() { + assert!(BoundTester::::default().is_field_3d()); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/mod.rs new file mode 100644 index 0000000..335fe1e --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/mod.rs @@ -0,0 +1,26 @@ +//! Function associating an attribute value with a point in space. + +pub mod metric; +pub mod shape; + +pub mod field_operator; + +pub mod traits; + +#[cfg(feature = "glam")] +pub mod boxed { + extern crate alloc; + use alloc::boxed::Box; + + use crate::prelude::{Attribute, Field}; + + impl Field for Box> + where + Attr: Attribute, + { + fn field(&self, input: &::Input) -> ::Output { + self.as_ref().field(input) + } + } +} + diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/shape/composite.rs b/bevy-app/crates/rust-gpu-sdf/src/field/shape/composite.rs new file mode 100644 index 0000000..0566978 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/shape/composite.rs @@ -0,0 +1,469 @@ +//! Shapes composed from other shapes. + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Cos, Sin, Sqrt, Tan, +}; + +use crate::prelude::{ + raytrace::RayIntersection, AxialReflect, Elongate, EuclideanMetric, Isosurface, Reflect, Sided, + StretchDist, Sweep, Translate, AXIS_X, AXIS_XY, D2, D3, +}; + +/// An infinitely small point. +/// Not very useful on its own; primarily used for composition. +pub type Point = EuclideanMetric; + +/// An infinitely thin line. +/// Not very useful on its own; primarily used for composition. +pub type Line = StretchDist; + +/// A ball. +pub type Ball = Isosurface; + +impl Ball { + pub fn radius(&mut self) -> &mut f32 { + self.op().delta() + } +} + +/// A 2D circle. +pub type Circle = Ball; + +/// A 3D sphere. +pub type Sphere = Ball; + +impl RayIntersection for Sphere { + fn intersect(&self, eye: Vec3, dir: Vec3) -> Option { + let b = eye.dot(dir); + let r = self.op.delta; + let c = eye.dot(eye) - r * r; + + // Exit if r’s origin outside s (c > 0) and r pointing away from s (b > 0) + if c > 0.0 && b > 0.0 { + return None; + } + let discr = b * b - c; + + // A negative discriminant corresponds to ray missing sphere + if discr < 0.0 { + return None; + } + + // Ray now found to intersect sphere, compute smallest t value of intersection + let mut t = -b - discr.sqrt(); + + // If t is negative, ray started inside sphere so clamp t to zero + if t < 0.0 { + t = 0.0; + } + + Some(t) + } +} + +/// A capsule. +pub type Capsule = Isosurface>; + +/// A box. +pub type Box = Elongate; + +/// A 2D square. +pub type Square = Box; + +/// A 3D cube. +pub type Cube = Box; + +/// A 3D torus. +pub type Torus = Sweep; + +impl Torus { + pub fn torus() -> Self { + use type_fields::field::Field; + + ::default() + .with((Torus::core, Circle::radius), 0.75) + .with((Torus::shell, Circle::radius), 0.25) + } +} + +pub type NgonMirror = Reflect; + +impl NgonMirror { + pub fn new(sin: f32, cos: f32) -> Self + where + Sdf: Default + 'static, + { + use type_fields::field::Field; + let mut sdf = as Default>::default() + .with(Self::sin, sin) + .with(Self::cos, cos); + *sdf.axis() = sdf.axis().normalize(); + sdf + } + + pub fn sdf(&mut self) -> &mut Sdf { + &mut self.target + } + + pub fn sin(&mut self) -> &mut f32 { + &mut self.op.axis.y + } + + pub fn cos(&mut self) -> &mut f32 { + &mut self.op.axis.x + } +} + +pub type Triangle = + AxialReflect>>>>; + +impl Triangle { + pub fn triangle() -> Self { + use type_fields::field::Field; + let angle = core::f32::consts::PI / 3 as f32; + let sin = angle.sin(); + let cos = angle.cos(); + let tan = angle.tan(); + ::default() + .with(Self::target, NgonMirror::new(sin, -cos)) + .with(Self::tan, tan) + .with(Self::radius, 1.0) + } + + pub fn tan(&mut self) -> &mut f32 { + self.target().sdf().dist() + } + + pub fn radius(&mut self) -> &mut f32 { + &mut self.target().sdf().target().translation().y + } +} + +pub type Quadrilateral = + AxialReflect>>>>; + +impl Quadrilateral { + pub fn quadrilateral() -> Self { + use type_fields::field::Field; + let angle = core::f32::consts::PI / 4.0; + let sin = angle.sin(); + let cos = angle.cos(); + let tan = angle.tan(); + + ::default() + .with(Self::target, NgonMirror::new(sin, -cos)) + .with(Self::tan, tan) + .with(Self::radius, 1.0) + } + + pub fn tan(&mut self) -> &mut f32 { + self.target().sdf().dist() + } + + pub fn radius(&mut self) -> &mut f32 { + &mut self.target().sdf().target().translation().y + } +} + +pub type Pentagon = AxialReflect< + AXIS_X, + NgonMirror>>>>, +>; + +impl Pentagon { + pub fn pentagon() -> Self { + use type_fields::field::Field; + let angle = core::f32::consts::PI / 5 as f32; + let sin = angle.sin(); + let cos = angle.cos(); + let tan = angle.tan(); + + ::default() + .with(Self::target, NgonMirror::new(sin, -cos)) + .with((Self::target, NgonMirror::sdf), NgonMirror::new(sin, cos)) + .with(Self::tan, tan) + .with(Self::radius, 1.0) + } + + pub fn tan(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().op.dist + } + + pub fn radius(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().target.op.translation.y + } +} + +pub type Hexagon = + AxialReflect>>>>; + +impl Hexagon { + pub fn hexagon() -> Self { + use type_fields::field::Field; + let angle = core::f32::consts::PI / 6 as f32; + let sin = angle.sin(); + let cos = angle.cos(); + let tan = angle.tan(); + + ::default() + .with(Self::target, NgonMirror::new(sin, -cos)) + .with(Self::tan, tan) + .with(Self::radius, 1.0) + } +} + +pub type Septagon = AxialReflect< + AXIS_X, + NgonMirror>>>>>, +>; + +impl Septagon { + pub fn septagon() -> Self { + use type_fields::field::Field; + let angle = core::f32::consts::PI / 7 as f32; + let sin = angle.sin(); + let cos = angle.cos(); + let tan = angle.tan(); + + ::default() + .with(Self::target, NgonMirror::new(sin, -cos)) + .with((Self::target, NgonMirror::sdf), NgonMirror::new(sin, cos)) + .with( + (Self::target, NgonMirror::sdf, NgonMirror::sdf), + NgonMirror::new(sin, -cos), + ) + .with(Self::tan, tan) + .with(Self::radius, 1.0) + } + + pub fn tan(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().sdf().op.dist + } + + pub fn radius(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().sdf().target.op.translation.y + } +} + +pub type Octagon = AxialReflect< + AXIS_XY, + NgonMirror>>>>, +>; + +impl Octagon { + pub fn octagon() -> Self { + use type_fields::field::Field; + let angle = core::f32::consts::PI / 8 as f32; + let sin = angle.sin(); + let cos = angle.cos(); + let tan = angle.tan(); + + ::default() + .with(Self::target, NgonMirror::new(sin, -cos)) + .with((Self::target, NgonMirror::sdf), NgonMirror::new(sin, cos)) + .with(Self::tan, tan) + .with(Self::radius, 1.0) + } + + pub fn tan(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().op.dist + } + + pub fn radius(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().target.op.translation.y + } +} + +pub type Nonagon = AxialReflect< + AXIS_X, + NgonMirror< + NgonMirror>>>>>, + >, +>; + +impl Nonagon { + pub fn nonagon() -> Self { + use type_fields::field::Field; + let angle = core::f32::consts::PI / 9 as f32; + let sin = angle.sin(); + let cos = angle.cos(); + let tan = angle.tan(); + + ::default() + .with(Self::target, NgonMirror::new(sin, -cos)) + .with((Self::target, NgonMirror::sdf), NgonMirror::new(sin, cos)) + .with( + (Self::target, NgonMirror::sdf, NgonMirror::sdf), + NgonMirror::new(sin, -cos), + ) + .with( + ( + Self::target, + NgonMirror::sdf, + NgonMirror::sdf, + NgonMirror::sdf, + ), + NgonMirror::new(sin, cos), + ) + .with(Self::tan, tan) + .with(Self::radius, 1.0) + } + + pub fn tan(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().sdf().sdf().op.dist + } + + pub fn radius(&mut self) -> &mut f32 { + &mut self + .target() + .sdf() + .sdf() + .sdf() + .sdf() + .target + .op + .translation + .y + } +} + +pub type Decagon = AxialReflect< + AXIS_XY, + NgonMirror>>>>>, +>; + +impl Decagon { + pub fn decagon() -> Self { + use type_fields::field::Field; + let angle = core::f32::consts::PI / 10 as f32; + let sin = angle.sin(); + let cos = angle.cos(); + let tan = angle.tan(); + + ::default() + .with(Self::target, NgonMirror::new(sin, -cos)) + .with((Self::target, NgonMirror::sdf), NgonMirror::new(sin, cos)) + .with( + (Self::target, NgonMirror::sdf, NgonMirror::sdf), + NgonMirror::new(sin, cos), + ) + .with(Self::tan, tan) + .with(Self::radius, 1.0) + } + + pub fn tan(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().sdf().op.dist + } + + pub fn radius(&mut self) -> &mut f32 { + &mut self.target().sdf().sdf().sdf().target.op.translation.y + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod tests { + use rust_gpu_bridge::glam::{Vec2, Vec3}; + + use crate::prelude::{ + BoundTester, Capsule, Cube, Decagon, Hexagon, Line, Nonagon, Octagon, Pentagon, + Quadrilateral, Septagon, Square, Torus, Triangle, + }; + + use super::{Circle, Point, Sphere}; + + #[test] + fn test_point_2d() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_line_2d() { + assert!(BoundTester::>::default().is_field_2d()); + } + + #[test] + fn test_point_3d() { + assert!(BoundTester::::default().is_field_3d()); + } + + #[test] + fn test_line_3d() { + assert!(BoundTester::>::default().is_field_3d()); + } + + #[test] + fn test_circle() { + assert!(BoundTester::::default().is_field_3d()); + } + + #[test] + fn test_sphere() { + assert!(BoundTester::::default().is_field_3d()); + } + + #[test] + fn test_capsule_2d() { + assert!(BoundTester::>::default().is_field_2d()); + } + + #[test] + fn test_capsule_3d() { + assert!(BoundTester::>::default().is_field_3d()); + } + + #[test] + fn test_square() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_cube() { + assert!(BoundTester::::default().is_field_3d()); + } + + #[test] + fn test_torus() { + assert!(BoundTester::::default().is_field_3d()); + } + + #[test] + fn test_triangle() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_quadrilateral() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_pentagon() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_hexagon() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_septagon() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_octagon() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_nonagon() { + assert!(BoundTester::::default().is_field_2d()); + } + + #[test] + fn test_decagon() { + assert!(BoundTester::::default().is_field_2d()); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/shape/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/shape/mod.rs new file mode 100644 index 0000000..d4a33ae --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/shape/mod.rs @@ -0,0 +1,7 @@ +//! Distance field shapes. + +pub mod composite; +pub mod octahedron; +pub mod plane; +pub mod superellipsoid; +pub mod squircle; diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/shape/octahedron.rs b/bevy-app/crates/rust-gpu-sdf/src/field/shape/octahedron.rs new file mode 100644 index 0000000..bd13a2a --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/shape/octahedron.rs @@ -0,0 +1,70 @@ +//! An octahedron. + +use rust_gpu_bridge::{glam::Vec3, Normalize, Sign}; +use type_fields::macros::Field; + +use crate::prelude::{ + items::position::Position, AttrDistance, AttrNormal, Distance, Field, Normal, +}; + +/// An octahedron. +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct Octahedron { + pub size: f32, +} + +impl Default for Octahedron { + fn default() -> Self { + Octahedron { size: 1.0 } + } +} + +impl Field> for Octahedron { + fn field(&self, p: &Position) -> Distance { + // Axial reflection + let p = p.abs(); + + // Signed distance minus size + let m = p.x + p.y + p.z - self.size; + + let q = if 3.0 * p.x < m { + p + } else if 3.0 * p.y < m { + Vec3::new(p.y, p.z, p.x) + } else if 3.0 * p.z < m { + Vec3::new(p.z, p.x, p.y) + } else { + return (m * 0.57735027).into(); + }; + + let k = (0.5 * (q.z - q.y + self.size)).clamp(0.0, self.size); + + let j = Vec3::new(q.x, q.y - self.size + k, q.z - k); + + // Euclidean metric + j.length().into() + } +} + +impl Field> for Octahedron +where + Dim: Clone + Sign + Normalize, +{ + fn field(&self, p: &Position) -> Normal { + (**p).clone().sign().normalize().into() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::prelude::BoundTester; + + use super::Octahedron; + + #[test] + fn test_octahedron() { + assert!(BoundTester::::default().is_field_3d()) + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/shape/plane.rs b/bevy-app/crates/rust-gpu-sdf/src/field/shape/plane.rs new file mode 100644 index 0000000..385c35b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/shape/plane.rs @@ -0,0 +1,83 @@ +//! A plane. +use core::ops::Neg; + +use rust_gpu_bridge::{ + glam::{Vec2, Vec3}, + Abs, +}; +use type_fields::macros::Field; + +use crate::prelude::{AttrDistance, Field, AttrNormal, items::position::Position, Distance, Normal}; + +/// A plane. +#[derive(Debug, Copy, Clone, PartialEq, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct Plane { + pub dir: Dim, +} + +impl Default for Plane { + fn default() -> Self { + Plane { dir: 1.0 } + } +} + +impl Default for Plane { + fn default() -> Self { + Plane { dir: Vec2::Y } + } +} + +impl Default for Plane { + fn default() -> Self { + Plane { dir: Vec3::Y } + } +} + +impl Field> for Plane { + fn field(&self, p: &Position) -> Distance { + assert!(self.dir.abs() == 1.0, "Plane dir must be normalized"); + (**p * -self.dir).into() + } +} + +impl Field> for Plane { + fn field(&self, p: &Position) -> Distance { + assert!(self.dir.is_normalized(), "Plane dir must be normalized"); + p.dot(-self.dir).into() + } +} + +impl Field> for Plane { + fn field(&self, p: &Position) -> Distance { + assert!(self.dir.is_normalized(), "Plane dir must be normalized"); + p.dot(-self.dir).into() + } +} + +impl Field> for Plane +where + Dim: Clone + Neg, +{ + fn field(&self, _: &Position) -> Normal { + self.dir.clone().neg().into() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::prelude::BoundTester; + + use super::Plane; + + #[test] + pub fn test_plane_2d() { + assert!(BoundTester::>::default().is_field_2d()) + } + + #[test] + pub fn test_plane_3d() { + assert!(BoundTester::>::default().is_field_3d()) + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/shape/squircle.rs b/bevy-app/crates/rust-gpu-sdf/src/field/shape/squircle.rs new file mode 100644 index 0000000..427538d --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/shape/squircle.rs @@ -0,0 +1,75 @@ +use rust_gpu_bridge::{ + glam::{Vec2, Vec2Swizzles}, + Abs, Acos, Cos, Pow, Sign, Sin, Sqrt, +}; + +use crate::prelude::{AttrDistance, Field, items::position::Position, Distance}; + +// Inigo Quilez' quadratic circle +// Appears to be a superellipse / lame curve with n = 1.0 / 0.75 +// Can be generalized to 3D as a superellipsoid +// +// Desmos decomposition: https://www.desmos.com/calculator/i9cgthn0ls +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct Squircle; + +impl Field> for Squircle { + fn field(&self, p: &Position) -> Distance { + // Axial reflection + let mut p = p.abs(); + + // Cheap diagonal mirror + if p.y > p.x { + p = p.yx() + } + + // Diagonal X maximum + let a = p.x - p.y; + + // Diagonal Y minimum + let b = p.x + p.y; + + // Diagonal Y maximum + let c = (2.0 * b - 1.0) / 3.0; + + // Semicircle at (0.5, 0.5) + let h = a * a + c * c * c; + + let t = if h >= 0.0 { + // Appears identical to h in graph plot, maybe field related + let h = h.sqrt(); + // Uneven circular curve + (h - a).sign() * (h - a).abs().pow(1.0 / 3.0) - (h + a).pow(1.0 / 3.0) + } else { + // Negative Y minimum + let z = (-c).sqrt(); + // Uneven tangent curve + let v = (a / (c * z)).acos() / 3.0; + // Uneven tangent curve, repeating w/different frequency + -z * (v.cos() + v.sin() * 1.732050808) + } * 0.5; + + // Bounded quadradic curve + let w = Vec2::new(-t, t) + 0.75 - t * t - p; + + // Quadratic curve sign + let s = (a * a * 0.5 + b - 1.5).sign(); + + // Final curve w / sign + (w.length() * s).into() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::prelude::{BoundTester, NormalTetrahedron}; + + use super::Squircle; + + #[test] + pub fn test_squircle() { + assert!(BoundTester::>::default().is_field_2d()) + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/shape/superellipsoid.rs b/bevy-app/crates/rust-gpu-sdf/src/field/shape/superellipsoid.rs new file mode 100644 index 0000000..09dbd9b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/shape/superellipsoid.rs @@ -0,0 +1,50 @@ +use rust_gpu_bridge::{glam::Vec3, Abs, Pow, Sign}; +use type_fields::macros::Field; + +use crate::prelude::{items::position::Position, AttrDistance, Field, AttrNormal, Distance, Normal}; + +// TODO: Apply pow(1.0 / foo) to un-exponentiate distance after axes are summed, +// as per Superellipse +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Field)] +#[cfg_attr(feature = "glam", derive(rust_gpu_bridge::Named))] +#[repr(C)] +pub struct Superellipsoid { + pub e1: f32, + pub e2: f32, +} + +impl Default for Superellipsoid { + fn default() -> Self { + Superellipsoid { e1: 1.0, e2: 1.0 } + } +} + +impl Field> for Superellipsoid { + fn field(&self, p: &Position) -> Distance { + let d = (p.x.abs().pow(self.e1) + p.y.abs().pow(self.e2)).pow(self.e2 / self.e1) + + p.z.abs().pow(self.e1); + + (d - 1.0).into() + } +} + +impl Field> for Superellipsoid { + fn field(&self, p: &Position) -> Normal { + let pa = p.abs(); + let pp = pa.pow(Vec3::new(self.e1, self.e2, self.e1)); + (pp.normalize() * p.sign()).into() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +pub mod test { + use crate::prelude::BoundTester; + + use super::Superellipsoid; + + #[test] + #[should_panic] + fn test_superellipsoid() { + assert!(BoundTester::::default().is_field_3d()) + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field.rs new file mode 100644 index 0000000..94ab053 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field.rs @@ -0,0 +1,10 @@ +use crate::prelude::Attribute; + +/// Evalute the attribute `Attr` of a field function. +pub trait Field +where + Attr: Attribute, +{ + fn field(&self, input: &Attr::Input) -> Attr::Output; +} + diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attribute.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attribute.rs new file mode 100644 index 0000000..db015cb --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attribute.rs @@ -0,0 +1,21 @@ +use crate::prelude::{Attribute, Field}; + +/// Evalute the attribute `Attr` of a field function. +/// +/// Moves `Attr` into the function position. +pub trait FieldAttribute { + fn field_attribute(&self, input: &Attr::Input) -> Attr::Output + where + Self: Field, + Attr: Attribute; +} + +impl FieldAttribute for T { + fn field_attribute(&self, input: &Attr::Input) -> Attr::Output + where + Self: Field, + Attr: Attribute, + { + self.field(input) + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attribute_register.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attribute_register.rs new file mode 100644 index 0000000..6e5bc29 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attribute_register.rs @@ -0,0 +1,24 @@ +use crate::prelude::{AttributeRef, Register, FieldRegister}; + +/// Evalute the attribute `Attr` of a field function, drawing input from `Ctx`. +/// +/// Moves `Attr` into the function position. +pub trait FieldAttributeRegister<'a, Ctx, State> { + fn field_attribute_register(&self, p: Ctx) -> Attr::Output + where + Self: FieldRegister<'a, Attr, Ctx, State>, + Attr: AttributeRef<'a>, + Ctx: Register; +} + +impl<'a, T, Ctx, State> FieldAttributeRegister<'a, Ctx, State> for T { + fn field_attribute_register(&self, ctx: Ctx) -> Attr::Output + where + T: FieldRegister<'a, Attr, Ctx, State>, + Attr: AttributeRef<'a>, + Ctx: Register, + { + self.field_register(ctx) + } +} + diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes.rs new file mode 100644 index 0000000..6310460 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes.rs @@ -0,0 +1,29 @@ +use type_fields::t_funk::hlist::ToTList; + +use crate::prelude::{Attributes, ConsAttributes, Fields}; + +/// Evalute multiple attributes of a field function. +/// +/// Moves `Attrs` into the function position. +pub trait FieldAttributes { + fn field_attributes<'a, Attrs>( + &self, + input: &::Input, + ) -> Attrs::UnconsOutput + where + Self: Fields, + Attrs: ConsAttributes<'a>; +} + +impl FieldAttributes for T { + fn field_attributes<'a, Attr>( + &self, + input: &::Input, + ) -> Attr::UnconsOutput + where + Self: Fields, + Attr: ConsAttributes<'a>, + { + self.fields(input).to_tlist() + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes_register.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes_register.rs new file mode 100644 index 0000000..f6603db --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes_register.rs @@ -0,0 +1,25 @@ +use type_fields::t_funk::hlist::ToTList; + +use crate::prelude::{ConsAttributes, FieldsRegister, Register}; + +/// Evalute multiple attributes of a field function, drawing input from `Ctx`. +/// +/// Moves `Attrs` into the function position. +pub trait FieldAttributesRegister<'a, Ctx, State> { + fn field_attributes_register(&self, ctx: Ctx) -> Attr::UnconsOutput + where + Self: FieldsRegister<'a, Ctx, State, Attr::HList>, + Ctx: Register, + Attr: ConsAttributes<'a>; +} + +impl<'a, T, Ctx, State> FieldAttributesRegister<'a, Ctx, State> for T { + fn field_attributes_register(&self, ctx: Ctx) -> Attr::UnconsOutput + where + Self: FieldsRegister<'a, Ctx, State, Attr::HList>, + Ctx: Register, + Attr: ConsAttributes<'a>, + { + self.fields_register(ctx).to_tlist() + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes_register_cons.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes_register_cons.rs new file mode 100644 index 0000000..b07455e --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_attributes_register_cons.rs @@ -0,0 +1,61 @@ +use type_fields::t_funk::{tlist::AsHListRef, hlist::ToTList}; + +use crate::prelude::{ConsAttributes, FieldsRegister, FieldsRegisters, Register, Registers}; + +/// Evalute multiple attributes of a field function, +/// drawing input from `Ctx` and `Uncons`ing the result. +/// +/// Moves `Attrs` into the function position. +pub trait FieldAttributesRegisterCons<'a, Ctx, State> +where + Ctx: AsHListRef, +{ + fn field_attributes_register_cons(&self, ctx: &'a Ctx) -> Attrs::UnconsOutput + where + Self: FieldsRegister<'a, Ctx::HListRef<'a>, State, Attrs::HList>, + Ctx::HListRef<'a>: Register, + Attrs: ConsAttributes<'a>; +} + +impl<'a, T, Ctx, State> FieldAttributesRegisterCons<'a, Ctx, State> for T +where + Ctx: AsHListRef, +{ + fn field_attributes_register_cons(&self, ctx: &'a Ctx) -> Attr::UnconsOutput + where + Self: FieldsRegister<'a, Ctx::HListRef<'a>, State, Attr::HList>, + Ctx::HListRef<'a>: Register, + Attr: ConsAttributes<'a>, + { + self.fields_register(ctx.as_hlist_ref()).to_tlist() + } +} + +/// Evalute multiple attributes of a field function, +/// drawing multiple inputs from `Ctx` and `Uncons`ing the result. +/// +/// Moves `Attrs` into the function position. +pub trait FieldAttributesRegistersCons<'a, Ctx, State> +where + Ctx: AsHListRef, +{ + fn field_attributes_registers_cons(&self, ctx: &'a Ctx) -> Attrs::UnconsOutput + where + Self: FieldsRegisters<'a, Ctx::HListRef<'a>, State, Attrs::HList>, + Attrs: ConsAttributes<'a>, + Ctx::HListRef<'a>: Registers; +} + +impl<'a, T, Ctx, State> FieldAttributesRegistersCons<'a, Ctx, State> for T +where + Ctx: AsHListRef, +{ + fn field_attributes_registers_cons(&self, ctx: &'a Ctx) -> Attrs::UnconsOutput + where + Self: FieldsRegisters<'a, Ctx::HListRef<'a>, State, Attrs::HList>, + Attrs: ConsAttributes<'a>, + Ctx::HListRef<'a>: Registers, + { + self.fields_registers(ctx.as_hlist_ref()).to_tlist() + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_register.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_register.rs new file mode 100644 index 0000000..660e6aa --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_register.rs @@ -0,0 +1,22 @@ +use crate::prelude::{AttributeRef, Register, Field}; + +/// Evalute the attribute `Attr` of a field function, drawing input from `Ctx`. +pub trait FieldRegister<'a, Attr, Ctx, State>: Field +where + Attr: AttributeRef<'a>, + Ctx: Register, +{ + fn field_register(&self, ctx: Ctx) -> Attr::Output; +} + +impl<'a, T, Attr, Ctx, State> FieldRegister<'a, Attr, Ctx, State> for T +where + Self: Field, + Attr: AttributeRef<'a>, + Ctx: Register, +{ + fn field_register(&self, ctx: Ctx) -> Attr::Output { + self.field(ctx.register()) + } +} + diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_registers.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_registers.rs new file mode 100644 index 0000000..390ef53 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_registers.rs @@ -0,0 +1,57 @@ +use crate::prelude::{AttributeRef, Registers, Field}; + +pub trait FieldRegisters<'a, Attr, Ctx, State>: Field +where + Attr: AttributeRef<'a>, + Ctx: Registers, +{ + fn field_registers(&self, ctx: Ctx) -> Attr::Output; +} + +impl<'a, T, Attr, Ctx, State> FieldRegisters<'a, Attr, Ctx, State> for T +where + Self: Field, + Attr: AttributeRef<'a>, + Ctx: Registers, +{ + fn field_registers(&self, ctx: Ctx) -> Attr::Output { + self.field(&ctx.registers()) + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use core::marker::PhantomData; + + use type_fields::t_funk::tlist::AsHListRef; + + use crate::prelude::{Attribute, Registers, Field, FieldRegisters}; + + #[test] + pub fn test_field_contexts() { + let context = (1usize, 2.0, "three").as_hlist_ref(); + + let (_float, (_int, ())) = Registers::<_, (&f32, (&usize, ()))>::registers(context); + + pub struct TestContexts; + + #[derive(Debug, Default, Copy, Clone)] + pub struct AttrTestContexts<'a>(PhantomData<&'a ()>); + + impl<'a> Attribute for AttrTestContexts<'a> { + type Input = (&'a f32, (&'a usize, ())); + type Output = (usize, f32); + } + + impl Field> for TestContexts { + fn field( + &self, + (float, (int, ())): &::Input, + ) -> ::Output { + (**int, **float) + } + } + + let _out = TestContexts.field_registers(context); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_registers_uncons.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_registers_uncons.rs new file mode 100644 index 0000000..6035c08 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/field_registers_uncons.rs @@ -0,0 +1,63 @@ +use type_fields::t_funk::{hlist::ToTList, tlist::ToHList}; + +use crate::prelude::{AttributeRef, Field, RegistersUncons}; + +pub trait FieldRegistersUncons<'a, Attr, Ctx, State>: Field +where + Attr: AttributeRef<'a>, + Attr::InputRef: ToHList, + ::HList: ToTList, + Ctx: RegistersUncons::HList>, +{ + fn field_registers_uncons(&self, ctx: Ctx) -> Attr::Output; +} + +impl<'a, T, Attr, Ctx, State> FieldRegistersUncons<'a, Attr, Ctx, State> for T +where + Self: Field, + Attr: AttributeRef<'a>, + Attr::InputRef: ToHList, + ::HList: ToTList, + Ctx: RegistersUncons::HList>, +{ + fn field_registers_uncons(&self, ctx: Ctx) -> Attr::Output { + self.field(&ctx.registers_uncons()) + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use core::marker::PhantomData; + + use type_fields::t_funk::tlist::AsHListRef; + + use crate::prelude::{Attribute, Field, FieldRegistersUncons, RegistersUncons}; + + #[test] + pub fn test_field_contexts_uncons() { + let context = (1usize, 2.0, "three").as_hlist_ref(); + + let (_float, _int) = RegistersUncons::<_, (&f32, &usize)>::registers_uncons(context); + + pub struct TestContextsUncons; + + #[derive(Debug, Default, Copy, Clone)] + pub struct AttrTestContextsUncons<'a>(PhantomData<&'a ()>); + + impl<'a> Attribute for AttrTestContextsUncons<'a> { + type Input = (&'a f32, &'a usize); + type Output = (usize, f32); + } + + impl Field> for TestContextsUncons { + fn field( + &self, + (float, int): &::Input, + ) -> ::Output { + (**int, **float) + } + } + + let _out = TestContextsUncons.field_registers_uncons(context); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields.rs new file mode 100644 index 0000000..c19cdbe --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields.rs @@ -0,0 +1,40 @@ +use crate::prelude::{Attribute, Attributes, Field}; + +/// Function associating several attribute values with a point in space. +/// +/// Extension trait of `Field`; +/// impls over `(LHS, RHS)` and `(LHS, ())` to allow recursive +/// evaluation of `Attribute` cons lists. +pub trait Fields +where + Attrs: Attributes, +{ + fn fields(&self, input: &Attrs::Input) -> Attrs::Output; +} + +impl Fields<(LHS, RHS)> for T +where + T: Field + Fields, + LHS: Attribute, + RHS: Attributes, +{ + fn fields( + &self, + input: &<(LHS, RHS) as Attributes>::Input, + ) -> <(LHS, RHS) as Attributes>::Output { + (self.field(input), self.fields(input)) + } +} + +impl Fields<(LHS, ())> for T +where + T: Field, + LHS: Attribute, +{ + fn fields( + &self, + input: &<(LHS, ()) as Attributes>::Input, + ) -> <(LHS, ()) as Attributes>::Output { + (self.field(input), ()) + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_register.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_register.rs new file mode 100644 index 0000000..48de8f0 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_register.rs @@ -0,0 +1,26 @@ +use crate::prelude::{AttributesRef, Register, Fields}; + +/// Function associating an attribute value with a point in space. +/// +/// API extension trait of `Fields`; +/// moves the `Attr` generic into the function position, +/// and obscures the `attr` parameter using `Attribute`'s `Default` constraint +pub trait FieldsRegister<'a, Ctx, State, Attr>: Fields +where + Attr: AttributesRef<'a>, + Ctx: Register, +{ + fn fields_register(&self, p: Ctx) -> Attr::Output; +} + +impl<'a, T, Ctx, State, Attrs> FieldsRegister<'a, Ctx, State, Attrs> for T +where + Self: Fields, + Attrs: AttributesRef<'a>, + Ctx: Register, +{ + fn fields_register(&self, ctx: Ctx) -> Attrs::Output { + self.fields(ctx.register()) + } +} + diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_registers.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_registers.rs new file mode 100644 index 0000000..9447520 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_registers.rs @@ -0,0 +1,21 @@ +use crate::prelude::{AttributesRef, Registers, Fields}; + +/// Evalute multiple attributes of a field function, drawing input from `Ctx`. +pub trait FieldsRegisters<'a, Ctx, State, Attrs>: Fields +where + Attrs: AttributesRef<'a>, + Ctx: Registers, +{ + fn fields_registers(&self, ctx: Ctx) -> Attrs::Output; +} + +impl<'a, T, Attrs, Ctx, State> FieldsRegisters<'a, Ctx, State, Attrs> for T +where + Self: Fields, + Attrs: AttributesRef<'a>, + Ctx: Registers, +{ + fn fields_registers(&self, ctx: Ctx) -> Attrs::Output { + self.fields(&ctx.registers()) + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_registers_uncons.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_registers_uncons.rs new file mode 100644 index 0000000..2b8b6e8 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_registers_uncons.rs @@ -0,0 +1,119 @@ +use type_fields::t_funk::{hlist::ToTList, tlist::ToHList}; + +use crate::prelude::{Attributes, AttributesRef, Fields, RegistersUncons}; + +/// Evalute multiple attributes of a field function, +/// drawing input from `Ctx` and `Uncons`ing the result. +pub trait FieldsRegistersUncons<'a, Attrs, Ctx, State>: Fields +where + Attrs: ToHList, + Attrs::HList: AttributesRef<'a>, + >::InputRef: ToHList, + <>::InputRef as ToHList>::HList: + ToTList>::InputRef>, + ::Output: ToTList, + Ctx: RegistersUncons< + State, + >::InputRef, + Type = <>::InputRef as ToHList>::HList, + >, +{ + fn fields_registers_uncons(&self, ctx: Ctx) -> ::Output; +} + +impl<'a, T, Attrs, Ctx, State> FieldsRegistersUncons<'a, Attrs, Ctx, State> for T +where + Self: Fields, + Attrs: ToHList, + Attrs::HList: AttributesRef<'a>, + >::InputRef: ToHList, + <>::InputRef as ToHList>::HList: + ToTList>::InputRef>, + ::Output: ToTList, + Ctx: RegistersUncons< + State, + >::InputRef, + Type = <>::InputRef as ToHList>::HList, + >, +{ + fn fields_registers_uncons(&self, ctx: Ctx) -> ::Output { + self.fields(&ctx.registers_uncons()) + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use core::marker::PhantomData; + + use type_fields::t_funk::tlist::AsHListRef; + + use crate::prelude::{Attribute, Field, FieldOperator, FieldsRegistersUncons, Operator}; + + #[test] + pub fn test_fields_contexts_uncons() { + let context = (1usize, 2.0, "three").as_hlist_ref(); + + #[derive(Default)] + pub struct TestFieldsContextsUncons; + + #[derive(Debug, Default, Copy, Clone)] + pub struct AttrTestFieldsContextsUncons<'a>(PhantomData<&'a ()>); + + impl<'a> Attribute for AttrTestFieldsContextsUncons<'a> { + type Input = (&'a f32, &'a usize); + type Output = (usize, f32); + } + + impl Field> for TestFieldsContextsUncons { + fn field( + &self, + (float, int): &::Input, + ) -> ::Output { + (**int, **float) + } + } + + #[derive(Default)] + pub struct TestFieldsContextsUncons2; + + #[derive(Debug, Default, Copy, Clone)] + pub struct AttrTestFieldsContextsUncons2<'a>(PhantomData<&'a ()>); + + impl<'a> Attribute for AttrTestFieldsContextsUncons2<'a> { + type Input = (&'a f32, &'a usize); + type Output = (&'static str, u8); + } + + impl FieldOperator> for TestFieldsContextsUncons2 { + fn operator( + &self, + _: &Sdf, + (float, _): & as Attribute>::Input, + ) -> as Attribute>::Output { + ("hello", **float as u8) + } + } + + impl<'a, Sdf> FieldOperator> for TestFieldsContextsUncons2 + where + Sdf: Field>, + { + fn operator( + &self, + sdf: &Sdf, + input: & as Attribute>::Input, + ) -> as Attribute>::Output { + sdf.field(input) + } + } + + let ((_int, _float), ((_string, _smallint), ())) = FieldsRegistersUncons::< + (AttrTestFieldsContextsUncons, AttrTestFieldsContextsUncons2), + _, + _, + >::fields_registers_uncons( + &Operator::::default(), + context, + ); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_uncons_registers_uncons.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_uncons_registers_uncons.rs new file mode 100644 index 0000000..891919b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/fields_uncons_registers_uncons.rs @@ -0,0 +1,127 @@ +use type_fields::t_funk::{hlist::ToTList, tlist::ToHList}; + +use crate::prelude::{Attributes, AttributesRef, FieldsRegistersUncons, RegistersUncons}; + +pub trait FieldsUnconsRegistersUncons<'a, Attrs, Ctx, State>: + FieldsRegistersUncons<'a, Attrs, Ctx, State> +where + Attrs: ToHList, + Attrs::HList: AttributesRef<'a>, + >::InputRef: ToHList, + <>::InputRef as ToHList>::HList: + ToTList>::InputRef>, + ::Output: ToTList, + Ctx: RegistersUncons< + State, + >::InputRef, + Type = <>::InputRef as ToHList>::HList, + >, +{ + fn fields_uncons_registers_uncons( + &self, + ctx: Ctx, + ) -> <::Output as ToTList>::TList; +} + +impl<'a, T, Attrs, Ctx, State> FieldsUnconsRegistersUncons<'a, Attrs, Ctx, State> for T +where + Self: FieldsRegistersUncons<'a, Attrs, Ctx, State>, + Attrs: ToHList, + Attrs::HList: AttributesRef<'a>, + >::InputRef: ToHList, + <>::InputRef as ToHList>::HList: + ToTList>::InputRef>, + ::Output: ToTList, + Ctx: RegistersUncons< + State, + >::InputRef, + Type = <>::InputRef as ToHList>::HList, + >, +{ + fn fields_uncons_registers_uncons( + &self, + ctx: Ctx, + ) -> <::Output as ToTList>::TList { + self.fields(&ctx.registers_uncons()).to_tlist() + } +} + +#[cfg(all(not(feature = "spirv-std"), test))] +mod test { + use core::marker::PhantomData; + + use type_fields::t_funk::tlist::AsHListRef; + + use crate::prelude::{ + fields_uncons_registers_uncons::FieldsUnconsRegistersUncons, Attribute, Field, + FieldOperator, Operator, + }; + + #[test] + pub fn test_fields_uncons_registers_uncons() { + let context = (1usize, 2.0, "three").as_hlist_ref(); + + #[derive(Default)] + pub struct TestFieldsContextsUncons; + + #[derive(Debug, Default, Copy, Clone)] + pub struct AttrTestFieldsContextsUncons<'a>(PhantomData<&'a ()>); + + impl<'a> Attribute for AttrTestFieldsContextsUncons<'a> { + type Input = (&'a f32, &'a usize); + type Output = (usize, f32); + } + + impl Field> for TestFieldsContextsUncons { + fn field( + &self, + (float, int): &::Input, + ) -> ::Output { + (**int, **float) + } + } + + #[derive(Default)] + pub struct TestFieldsContextsUncons2; + + #[derive(Debug, Default, Copy, Clone)] + pub struct AttrTestFieldsContextsUncons2<'a>(PhantomData<&'a ()>); + + impl<'a> Attribute for AttrTestFieldsContextsUncons2<'a> { + type Input = (&'a f32, &'a usize); + type Output = (&'static str, u8); + } + + impl FieldOperator> for TestFieldsContextsUncons2 { + fn operator( + &self, + _: &Sdf, + (float, _): & as Attribute>::Input, + ) -> as Attribute>::Output { + ("hello", **float as u8) + } + } + + impl<'a, Sdf> FieldOperator> for TestFieldsContextsUncons2 + where + Sdf: Field>, + { + fn operator( + &self, + sdf: &Sdf, + input: & as Attribute>::Input, + ) -> as Attribute>::Output { + sdf.field(input) + } + } + + let ((_int, _float), (_string, _smallint)) = FieldsUnconsRegistersUncons::< + (AttrTestFieldsContextsUncons, AttrTestFieldsContextsUncons2), + _, + _, + >::fields_uncons_registers_uncons( + &Operator::::default(), + context, + ); + } +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/field/traits/mod.rs b/bevy-app/crates/rust-gpu-sdf/src/field/traits/mod.rs new file mode 100644 index 0000000..2b1464f --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/field/traits/mod.rs @@ -0,0 +1,14 @@ +pub mod field; +pub mod field_attribute; +pub mod field_attribute_register; +pub mod field_attributes; +pub mod field_attributes_register; +pub mod field_attributes_register_cons; +pub mod field_register; +pub mod field_registers; +pub mod field_registers_uncons; +pub mod fields; +pub mod fields_register; +pub mod fields_registers; +pub mod fields_registers_uncons; +pub mod fields_uncons_registers_uncons; diff --git a/bevy-app/crates/rust-gpu-sdf/src/lib.rs b/bevy-app/crates/rust-gpu-sdf/src/lib.rs new file mode 100644 index 0000000..a64c68b --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/lib.rs @@ -0,0 +1,480 @@ +#![no_std] + +pub mod bound_tester; +pub use type_fields; +pub mod attribute; +pub mod context; +pub mod field; + +pub mod field_type_machine { + use core::marker::PhantomData; + + use rust_gpu_bridge::{ + glam::{Vec2, Vec2Swizzles, Vec3}, + Abs, Asin, Atan2, Length, Normalize, + }; + use type_fields::{ + t_funk::{Copointed, Pointed, Tagged}, + type_machine::instruction::Instruction, + }; + + use crate::{impl_newtype, prelude::RaycastOutput}; + + pub enum Distance {} + pub enum Normal {} + pub enum Position {} + pub enum Uv {} + + #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct EuclideanMetric(PhantomData); + + impl Instruction for EuclideanMetric + where + for<'a> Dim: Clone + Length + 'a, + { + type Input<'a> = Tagged + where + Self: 'a; + + type Output = Tagged; + + fn exec<'a>(self, input: Self::Input<'a>) -> Self::Output { + let p = input.copoint(); + Tagged::::point(p.length()) + } + } + + pub struct EuclideanNormal(PhantomData); + + impl Instruction for EuclideanNormal + where + for<'a> Dim: Normalize + 'a, + { + type Input<'a> = Tagged + where + Self: 'a; + + type Output = Tagged; + + fn exec<'a>(self, input: Self::Input<'a>) -> Self::Output { + let p = input.copoint(); + Tagged::::point(p.normalize()) + } + } + + pub struct SphereUv; + + impl Instruction for SphereUv { + type Input<'a> = Tagged + where + Self: 'a; + + type Output = Tagged; + + fn exec<'a>(self, input: Self::Input<'a>) -> Self::Output { + let p = input.copoint(); + Tagged::::point(Vec2::new( + (p.x.atan2(p.z) / core::f32::consts::TAU) + 0.5, + (p.y.asin() / core::f32::consts::PI) + 0.5, + )) + } + } + + #[derive(Default, Copy, Clone, PartialEq)] + pub struct UvGradient { + pub axis: Vec2, + pub epsilon: f32, + } + + pub struct GradientTetrahedron + where + T: Instruction + 'static, + { + inner: T, + axis: T::Input<'static>, + epsilon: f32, + } + + impl_newtype!( + #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct Gradient(T); + ); + + impl Instruction for GradientTetrahedron + where + for<'a> T: Clone + Instruction, + for<'a> T::Input<'a>: Clone + Pointed + Copointed, + for<'a> T::Output: Pointed + Copointed, + { + type Input<'a> = T::Input<'a> + where + Self: 'a; + + type Output = Gradient; + + fn exec<'a>(self, input: Self::Input<'a>) -> Self::Output { + let input = input.copoint(); + + let k = Vec2::new(1.0, -1.0); + let out = k.xyy() + * self + .inner + .clone() + .exec(T::Input::point(input + k.xyy() * self.epsilon)) + .copoint() + .dot(self.axis.clone().copoint()) + + k.yyx() + * self + .inner + .clone() + .exec(T::Input::point(input + k.yyx() * self.epsilon)) + .copoint() + .dot(self.axis.clone().copoint()) + + k.yxy() + * self + .inner + .clone() + .exec(T::Input::point(input + k.yxy() * self.epsilon)) + .copoint() + .dot(self.axis.clone().copoint()) + + k.xxx() + * self + .inner + .clone() + .exec(T::Input::point(input + k.xxx() * self.epsilon)) + .copoint() + .dot(self.axis.clone().copoint()); + + Gradient(T::Output::point(out)) + } + } + + #[derive(Debug, Default, Copy, Clone, PartialEq, PartialOrd)] + pub struct Isosurface { + pub delta: f32, + } + + impl Instruction for Isosurface { + type Input<'a> = Tagged + where + Self: 'a; + + type Output = Tagged; + + fn exec<'a>(self, input: Self::Input<'a>) -> Self::Output { + let d = input.copoint(); + Tagged::::point(d - self.delta) + } + } + + pub enum RaymarchSteps {} + pub enum RayPosition {} + pub enum RayDirection {} + pub enum RayStart {} + pub enum RayEnd {} + + /// Sphere tracer that operates with respect to a precomputed Lipschitz bound. + /// + /// Costs 1 extra divide per step compared to [`SphereTraceNaive`], + /// but results in overall faster intersections. + /// + /// Note: The precomputed lipschitz bound `k` must be correct in respect to the + /// provided SDF for accurate behaviour; incorrect values will result in visual artifacting. + #[derive(Copy, Clone, PartialEq)] + #[repr(C)] + pub struct SphereTraceLipschitz { + pub epsilon: f32, + pub frac_1_k: f32, + pub _phantom: PhantomData, + } + + impl Default for SphereTraceLipschitz + where + T: Default, + { + fn default() -> Self { + SphereTraceLipschitz { + epsilon: 0.0001, + frac_1_k: 1.0 / (Self::falloff_k(1.0, 3.0) * 3.0), + _phantom: Default::default(), + } + } + } + + impl SphereTraceLipschitz { + // Computes the global lipschitz bound of the falloff function + // e: energy + // R: radius + fn falloff_k(e: f32, r: f32) -> f32 { + 1.72 * e.abs() / r + } + } + + impl Instruction for SphereTraceLipschitz + where + for<'a> T: Clone + + Instruction = Tagged, Output = Tagged> + + 'a, + { + type Input<'a> = (Tagged, Tagged, Tagged, Tagged, T) + where + Self: 'a; + + type Output = (Tagged, Tagged); + + fn exec<'a>(self, (eye, dir, start, end, inner): Self::Input<'a>) -> Self::Output { + let eye = eye.copoint(); + let dir = dir.copoint(); + let start = start.copoint(); + let end = end.copoint(); + + let mut out = RaycastOutput::default(); + + let mut t = start; + for i in 0..MAX_STEPS { + let pos = eye + dir * t; + let dist = inner + .clone() + .exec(Tagged::::point(pos)) + .copoint(); + + out.march_step(t, dist); + + if dist < 0.0 { + out.march_hit(i); + break; + } + + t += self.epsilon.max(dist.abs() * self.frac_1_k); + + if t > end { + out.march_miss(i); + break; + } + } + + ( + Tagged::::point(out.closest_dist), + Tagged::::point(out.steps), + ) + } + } +} + +pub mod util { + #[macro_export] + macro_rules! impl_newtype { + (#[derive($($derive:ident),*)] pub struct $ident:ident($ty:ident);) => { + #[derive( $($derive),* )] + pub struct $ident(pub $ty); + + crate::impl_morphisms_newtype!($ident($ty)); + crate::impl_arith_newtype!($ident($ty)); + }; + + (#[derive($($derive:ident),*)] pub struct $ident:ident<$ty:ident>($ty2:ident);) => { + #[derive( $($derive),* )] + pub struct $ident<$ty>(pub $ty); + + crate::impl_morphisms_newtype!($ident<$ty>); + crate::impl_arith_newtype!($ident<$ty>); + }; + } + + #[macro_export] + macro_rules! impl_morphisms_newtype { + ($ident:ident($ty:ident)) => { + impl core::ops::Deref for $ident { + type Target = $ty; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl core::ops::DerefMut for $ident { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + impl From<$ty> for $ident { + fn from(value: $ty) -> Self { + $ident(value) + } + } + + impl type_fields::t_funk::Pointed for $ident { + type Pointed = $ty; + + fn point(unit: Self::Pointed) -> Self { + $ident(unit) + } + } + + impl type_fields::t_funk::Copointed for $ident { + type Copointed = $ty; + + fn copoint(self) -> Self::Copointed { + self.0 + } + } + }; + ($ident:ident<$ty:ident>) => { + impl<$ty> core::ops::Deref for $ident<$ty> { + type Target = $ty; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl<$ty> core::ops::DerefMut for $ident<$ty> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + impl<$ty> From<$ty> for $ident<$ty> { + fn from(value: $ty) -> Self { + $ident(value) + } + } + + impl<$ty> type_fields::t_funk::Pointed for $ident<$ty> { + type Pointed = $ty; + + fn point(unit: Self::Pointed) -> Self { + $ident(unit) + } + } + + impl<$ty> type_fields::t_funk::Copointed for $ident<$ty> { + type Copointed = $ty; + + fn copoint(self) -> Self::Copointed { + self.0 + } + } + + impl<$ty, F, O> type_fields::t_funk::Fmap for $ident<$ty> + where + F: Fn($ty) -> O, + { + type Fmap = $ident; + + fn fmap(self, f: F) -> Self::Fmap { + type_fields::t_funk::Pointed::point(f(type_fields::t_funk::Copointed::copoint( + self, + ))) + } + } + + impl<$ty, _Ty, O> type_fields::t_funk::Apply<_Ty> for $ident<$ty> + where + $ty: Fn(_Ty) -> O, + { + type Apply = O; + + fn apply(self, a: _Ty) -> Self::Apply { + type_fields::t_funk::Copointed::copoint(self)(a) + } + } + + impl<$ty, F, O> type_fields::t_funk::Chain for $ident<$ty> + where + F: Fn($ty) -> O, + { + type Chain = F::Output; + + fn chain(self, f: F) -> Self::Chain { + f(type_fields::t_funk::Copointed::copoint(self)) + } + } + }; + } + + #[macro_export] + macro_rules! impl_arith_newtype { + ($ident:ident ($ty:ident)) => { + //crate::impl_arith_newtype_1!(Neg, neg, $ident($ty)); + crate::impl_arith_newtype_2!(Add, add, $ident($ty)); + crate::impl_arith_newtype_2!(Sub, sub, $ident($ty)); + crate::impl_arith_newtype_2!(Mul, mul, $ident($ty)); + crate::impl_arith_newtype_2!(Div, div, $ident($ty)); + }; + ($ident:ident <$ty:ident>) => { + //crate::impl_arith_newtype_1!(Neg, neg, $ident<$ty>); + crate::impl_arith_newtype_2!(Add, add, $ident<$ty>); + crate::impl_arith_newtype_2!(Sub, sub, $ident<$ty>); + crate::impl_arith_newtype_2!(Mul, mul, $ident<$ty>); + crate::impl_arith_newtype_2!(Div, div, $ident<$ty>); + }; + } + + #[macro_export] + macro_rules! impl_arith_newtype_1 { + ($op:ident, $fn:ident, $ident:ident ($ty:ident)) => { + impl core::ops::$op for $ident { + type Output = Self; + + fn $fn(self) -> Self::Output { + $ident(self.0.$fn()) + } + } + }; + ($op:ident, $fn:ident, $ident:ident <$ty:ident>) => { + impl<$ty> core::ops::$op for $ident<$ty> + where + $ty: core::ops::$op, + { + type Output = Self; + + fn $fn(self) -> Self::Output { + $ident(self.0.$fn()) + } + } + }; + } + + #[macro_export] + macro_rules! impl_arith_newtype_2 { + ($op:ident, $fn:ident, $ident:ident ($ty:ident)) => { + impl core::ops::$op for $ident + where + $ty: core::ops::$op, + { + type Output = Self; + + fn $fn(self, rhs: RHS) -> Self::Output { + Self(self.0.$fn(rhs)) + } + } + }; + ($op:ident, $fn:ident, $ident:ident <$ty:ident>) => { + impl<$ty, RHS> core::ops::$op for $ident<$ty> + where + $ty: core::ops::$op, + { + type Output = Self; + + fn $fn(self, rhs: RHS) -> Self::Output { + Self(self.0.$fn(rhs)) + } + } + }; + } +} + +pub mod prelude; + +use rust_gpu_bridge::glam::{Vec2, Vec3}; + +pub type D1 = f32; +pub type D2 = Vec2; +pub type D3 = Vec3; + +/// Free-standing [`Default::default()`] invocation +pub fn default() -> T { + Default::default() +} diff --git a/bevy-app/crates/rust-gpu-sdf/src/prelude.rs b/bevy-app/crates/rust-gpu-sdf/src/prelude.rs new file mode 100644 index 0000000..037fcf5 --- /dev/null +++ b/bevy-app/crates/rust-gpu-sdf/src/prelude.rs @@ -0,0 +1,56 @@ +pub use crate::{ + attribute::{ + bound_error::*, color::*, distance::*, normal::*, support_function::*, tangent::*, uv::*, *, + }, + bound_tester::*, + context::{ + items::{position::*, *}, + traits::{ + register::*, register_item::*, register_items::*, register_items_uncons::*, + registers::*, registers_uncons::*, *, + }, + *, + }, + field::{ + field_operator::{ + arity::{extrude::*, extrude_interior::*, slice::*, sweep::*, *}, + boolean::{intersection::*, subtraction::*, union::*, *}, + checker::*, + color_normal::*, + color_tangent::*, + color_uv::*, + composite::*, + coordinate_system::{cartesian_to_spherical::*, spherical_to_cartesian::*, *}, + displace::*, + displace_proxy::*, + elongate::*, + gradient::{gradient_central_diff::*, gradient_tetrahedron::*, gradient_uv::*, *}, + hollow::*, + isosurface::*, + isosurface_proxy::*, + normalize::*, + proxy::{proxy_color::*, proxy_normal::*, proxy_tangent::*, proxy_uv::*}, + raycast::{raytrace::*, sphere_trace_lipschitz::*, sphere_trace_naive::*, *}, + reflect::{axial_reflect::*, reflect::*, *}, + repeat::{repeat_count::*, repeat_infinite::*, *}, + scale_uv::*, + sided::*, + smooth_boolean::{smooth_intersection::*, smooth_subtraction::*, smooth_union::*, *}, + stretch::*, + transform::{rotate::*, scale::*, translate::*, *}, + triplanar_uv::*, + twist::*, + *, + }, + metric::{chebyshev::*, euclidean::*, superellipse::*, taxicab::*, *}, + shape::{composite::*, octahedron::*, plane::*, squircle::*, *}, + traits::{ + field::*, field_attribute::*, field_attribute_register::*, field_attributes::*, + field_attributes_register_cons::*, field_register::*, field_registers::*, + field_registers_uncons::*, fields::*, fields_register::*, fields_registers::*, + fields_registers_uncons::*, fields_uncons_registers_uncons::*, *, + }, + *, + }, + *, +}; diff --git a/bevy-app/crates/viewer/Cargo.toml b/bevy-app/crates/viewer/Cargo.toml index 5b42d77..4867b57 100644 --- a/bevy-app/crates/viewer/Cargo.toml +++ b/bevy-app/crates/viewer/Cargo.toml @@ -12,8 +12,8 @@ name = "standard-material" path = "examples/standard-material.rs" [dependencies] -bevy = { version = "0.10.0", features = ["spirv_shader_passthrough"] } - -bevy-rust-gpu = { git = "https://github.com/bevy-rust-gpu/bevy-rust-gpu", tag = "v0.5.0" } +bevy = { version = "0.11.3" } +rmp-serde="1.1.1" +bevy-rust-gpu = { path = "../bevy_rust_gpu" } rust-gpu-bridge = { git = "https://github.com/bevy-rust-gpu/rust-gpu-bridge", features = ["glam"], tag = "v0.5.0" } -rust-gpu-sdf = { git = "https://github.com/bevy-rust-gpu/rust-gpu-sdf", default_features = false, features = ["glam", "bevy"] } +rust-gpu-sdf = { path = "../rust-gpu-sdf", default_features = false, features = ["glam", "bevy"] } diff --git a/bevy-app/crates/viewer/examples/compute.rs b/bevy-app/crates/viewer/examples/compute.rs new file mode 100644 index 0000000..53ddc61 --- /dev/null +++ b/bevy-app/crates/viewer/examples/compute.rs @@ -0,0 +1,294 @@ +//! A compute shader that simulates Conway's Game of Life. +//! +//! Compute shaders use the GPU for computing arbitrary information, that may be independent of what +//! is rendered to the screen. + +use bevy::{ + asset::{AssetLoader, LoadedAsset}, + prelude::{ + default, AddAsset, App, AssetServer, Assets, Camera2dBundle, ClearColor, Color, Commands, + Deref, FromWorld, Handle, Image, IntoSystemConfigs, Plugin, PluginGroup, Res, ResMut, + Resource, Shader, Vec2, World, info, + }, + render::{ + extract_resource::{ExtractResource, ExtractResourcePlugin}, + render_asset::RenderAssets, + render_graph::{self, RenderGraph}, + render_resource::{ + BindGroup, BindGroupDescriptor, BindGroupEntry, BindGroupLayout, + BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, + CachedComputePipelineId, CachedPipelineState, ComputePassDescriptor, + ComputePipelineDescriptor, Extent3d, PipelineCache, ShaderStages, StorageTextureAccess, + TextureDimension, TextureFormat, TextureUsages, TextureViewDimension, + }, + renderer::{RenderContext, RenderDevice}, + RenderApp, RenderSet, + }, + sprite::{Sprite, SpriteBundle}, + window::{Window, WindowPlugin}, + DefaultPlugins, +}; +use bevy_rust_gpu::RustGpuBuilderOutput; +use std::borrow::Cow; + +const SIZE: (u32, u32) = (1280, 720); +const WORKGROUP_SIZE: u32 = 8; + +fn main() { + App::new() + .insert_resource(ClearColor(Color::BLACK)) + .add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + // uncomment for unthrottled FPS + // present_mode: bevy::window::PresentMode::AutoNoVsync, + ..default() + }), + ..default() + })) + .init_asset_loader::() + .add_plugins(GameOfLifeComputePlugin) + .add_startup_systems(setup) + .run(); +} + +fn setup(mut commands: Commands, mut images: ResMut>) { + let mut image = Image::new_fill( + Extent3d { + width: SIZE.0, + height: SIZE.1, + depth_or_array_layers: 1, + }, + TextureDimension::D2, + &[0, 0, 0, 255], + TextureFormat::Rgba8Unorm, + ); + image.texture_descriptor.usage = + TextureUsages::COPY_DST | TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING; + let image = images.add(image); + + commands.spawn(SpriteBundle { + sprite: Sprite { + custom_size: Some(Vec2::new(SIZE.0 as f32, SIZE.1 as f32)), + ..default() + }, + texture: image.clone(), + ..default() + }); + commands.spawn(Camera2dBundle::default()); + + commands.insert_resource(GameOfLifeImage(image)); +} + +pub struct GameOfLifeComputePlugin; + +impl Plugin for GameOfLifeComputePlugin { + fn build(&self, app: &mut App) { + // Extract the game of life image resource from the main world into the render world + // for operation on by the compute shader and display on the sprite. + app.add_plugins(ExtractResourcePlugin::::default()); + let render_app = app.sub_app_mut(RenderApp); + render_app + .init_resource::() + .add_system(queue_bind_group.in_set(RenderSet::Queue)); + + let mut render_graph = render_app.world.resource_mut::(); + render_graph.add_node("game_of_life", GameOfLifeNode::default()); + render_graph.add_node_edge( + "game_of_life", + bevy::render::main_graph::node::CAMERA_DRIVER, + ); + } +} + +#[derive(Resource, Clone, Deref, ExtractResource)] +struct GameOfLifeImage(Handle); + +#[derive(Resource)] +struct GameOfLifeImageBindGroup(BindGroup); + +fn queue_bind_group( + mut commands: Commands, + pipeline: Res, + gpu_images: Res>, + game_of_life_image: Res, + render_device: Res, +) { + let view = gpu_images.get(&game_of_life_image.0).unwrap(); + let bind_group = render_device.create_bind_group(&BindGroupDescriptor { + label: None, + layout: &pipeline.texture_bind_group_layout, + entries: &[BindGroupEntry { + binding: 0, + resource: BindingResource::TextureView(&view.texture_view), + }], + }); + commands.insert_resource(GameOfLifeImageBindGroup(bind_group)); +} + +#[derive(Resource)] +pub struct GameOfLifePipeline { + texture_bind_group_layout: BindGroupLayout, + init_pipeline: CachedComputePipelineId, + update_pipeline: CachedComputePipelineId, +} + +impl FromWorld for GameOfLifePipeline { + fn from_world(world: &mut World) -> Self { + let texture_bind_group_layout = + world + .resource::() + .create_bind_group_layout(&BindGroupLayoutDescriptor { + label: None, + entries: &[BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStages::COMPUTE, + ty: BindingType::StorageTexture { + access: StorageTextureAccess::ReadWrite, + format: TextureFormat::Rgba8Unorm, + view_dimension: TextureViewDimension::D2, + }, + count: None, + }], + }); + + let shader = world + .resource::() + .load("rust-gpu/shader.rust-gpu.msgpack"); + + // let shader = world + // .resource::() + // .load("gol.wgsl"); + let pipeline_cache = world.resource::(); + let init_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor { + label: Some("init_compute_primes".into()), + layout: vec![texture_bind_group_layout.clone()], + push_constant_ranges: Vec::new(), + shader: shader.clone(), + shader_defs: vec![], + entry_point: Cow::from("init"), + }); + let update_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor { + label: Some("update_compute_primes".into()), + layout: vec![texture_bind_group_layout.clone()], + push_constant_ranges: Vec::new(), + shader, + shader_defs: vec![], + entry_point: Cow::from("update"), + }); + + GameOfLifePipeline { + texture_bind_group_layout, + init_pipeline, + update_pipeline, + } + } +} + +enum GameOfLifeState { + Loading, + Init, + Update, +} + +struct GameOfLifeNode { + state: GameOfLifeState, +} + +impl Default for GameOfLifeNode { + fn default() -> Self { + Self { + state: GameOfLifeState::Loading, + } + } +} + +impl render_graph::Node for GameOfLifeNode { + fn update(&mut self, world: &mut World) { + let pipeline = world.resource::(); + let pipeline_cache = world.resource::(); + + // if the corresponding pipeline has loaded, transition to the next stage + match self.state { + GameOfLifeState::Loading => { + if let CachedPipelineState::Ok(_) = + pipeline_cache.get_compute_pipeline_state(pipeline.init_pipeline) + { + self.state = GameOfLifeState::Init; + } + } + GameOfLifeState::Init => { + if let CachedPipelineState::Ok(_) = + pipeline_cache.get_compute_pipeline_state(pipeline.update_pipeline) + { + self.state = GameOfLifeState::Update; + } + } + GameOfLifeState::Update => {} + } + } + + fn run( + &self, + _graph: &mut render_graph::RenderGraphContext, + render_context: &mut RenderContext, + world: &World, + ) -> Result<(), render_graph::NodeRunError> { + let texture_bind_group = &world.resource::().0; + let pipeline_cache = world.resource::(); + let pipeline = world.resource::(); + + let mut pass = render_context + .command_encoder() + .begin_compute_pass(&ComputePassDescriptor::default()); + + pass.set_bind_group(0, texture_bind_group, &[]); + + // select the pipeline based on the current state + match self.state { + GameOfLifeState::Loading => {} + GameOfLifeState::Init => { + let init_pipeline = pipeline_cache + .get_compute_pipeline(pipeline.init_pipeline) + .unwrap(); + pass.set_pipeline(init_pipeline); + pass.dispatch_workgroups(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1); + } + GameOfLifeState::Update => { + let update_pipeline = pipeline_cache + .get_compute_pipeline(pipeline.update_pipeline) + .unwrap(); + pass.set_pipeline(update_pipeline); + pass.dispatch_workgroups(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1); + } + } + + Ok(()) + } +} + +#[derive(Default)] +struct RustGpuMsgpackLoader; + +impl AssetLoader for RustGpuMsgpackLoader { + fn load<'a>( + &'a self, + bytes: &'a [u8], + load_context: &'a mut bevy::asset::LoadContext, + ) -> bevy::utils::BoxedFuture<'a, Result<(), bevy::asset::Error>> { + Box::pin(async move { + let spirv_bytes: RustGpuBuilderOutput = rmp_serde::from_slice(bytes).unwrap(); + let shader = match spirv_bytes.modules { + bevy_rust_gpu::RustGpuBuilderModules::Single(s) => { + Shader::from_spirv(s, "") + }, + bevy_rust_gpu::RustGpuBuilderModules::Multi(_) => todo!(), + }; + load_context.set_default_asset(LoadedAsset::new(shader)); + Ok(()) + }) + } + + fn extensions(&self) -> &[&str] { + &["rust-gpu.msgpack"] + } +} \ No newline at end of file diff --git a/bevy-app/crates/viewer/examples/compute_new.rs b/bevy-app/crates/viewer/examples/compute_new.rs new file mode 100644 index 0000000..8d0da03 --- /dev/null +++ b/bevy-app/crates/viewer/examples/compute_new.rs @@ -0,0 +1,289 @@ +//! A compute shader that simulates Conway's Game of Life. +//! +//! Compute shaders use the GPU for computing arbitrary information, that may be independent of what +//! is rendered to the screen. + +use bevy::{ + prelude::*, + render::{ + extract_resource::{ExtractResource, ExtractResourcePlugin}, + render_asset::RenderAssets, + render_graph::{self, RenderGraph}, + render_resource::*, + renderer::{RenderContext, RenderDevice}, + Render, RenderApp, RenderSet, + }, + window::{WindowPlugin, WindowResolution}, asset::{AssetLoader, LoadedAsset, ChangeWatcher}, +}; +use bevy_rust_gpu::RustGpuBuilderOutput; +use std::borrow::Cow; + +const SIZE: (u32, u32) = (1920*2, 1080*2); +const WORKGROUP_SIZE: u32 = 8; +use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; + +fn main() { + App::new() + .insert_resource(ClearColor(Color::BLACK)) + .add_plugins(( + DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + // uncomment for unthrottled FPS + present_mode: bevy::window::PresentMode::AutoNoVsync, + resolution: WindowResolution::new(SIZE.0 as f32, SIZE.1 as f32), + ..default() + }), + ..default() + }).set( AssetPlugin { + watch_for_changes: ChangeWatcher::with_delay(std::time::Duration::from_secs(1)), + ..default() + },), + GameOfLifeComputePlugin, + )) + .add_plugin(LogDiagnosticsPlugin::default()) + .add_plugin(FrameTimeDiagnosticsPlugin::default()) + .init_asset_loader::() + .add_systems(Startup, setup) + .run(); +} + +fn setup(mut commands: Commands, mut images: ResMut>) { + let mut image = Image::new_fill( + Extent3d { + width: SIZE.0, + height: SIZE.1, + depth_or_array_layers: 1, + }, + TextureDimension::D2, + &[0, 0, 0, 255], + TextureFormat::Rgba8Snorm, + ); + image.texture_descriptor.usage = + TextureUsages::COPY_DST | TextureUsages::STORAGE_BINDING | TextureUsages::TEXTURE_BINDING; + let image = images.add(image); + + commands.spawn(SpriteBundle { + sprite: Sprite { + custom_size: Some(Vec2::new(SIZE.0 as f32, SIZE.1 as f32)), + ..default() + }, + texture: image.clone(), + ..default() + }); + commands.spawn(Camera2dBundle::default()); + + commands.insert_resource(GameOfLifeImage(image)); +} + +pub struct GameOfLifeComputePlugin; + +impl Plugin for GameOfLifeComputePlugin { + fn build(&self, app: &mut App) { + // Extract the game of life image resource from the main world into the render world + // for operation on by the compute shader and display on the sprite. + app.add_plugins(ExtractResourcePlugin::::default()); + let render_app = app.sub_app_mut(RenderApp); + render_app.add_systems(Render, queue_bind_group.in_set(RenderSet::Queue)); + + let mut render_graph = render_app.world.resource_mut::(); + render_graph.add_node("game_of_life", GameOfLifeNode::default()); + render_graph.add_node_edge( + "game_of_life", + bevy::render::main_graph::node::CAMERA_DRIVER, + ); + } + + fn finish(&self, app: &mut App) { + let render_app = app.sub_app_mut(RenderApp); + render_app.init_resource::(); + } +} + +#[derive(Resource, Clone, Deref, ExtractResource)] +struct GameOfLifeImage(Handle); + +#[derive(Resource)] +struct GameOfLifeImageBindGroup(BindGroup); + +fn queue_bind_group( + mut commands: Commands, + pipeline: Res, + gpu_images: Res>, + game_of_life_image: Res, + render_device: Res, +) { + let view = &gpu_images[&game_of_life_image.0]; + let bind_group = render_device.create_bind_group(&BindGroupDescriptor { + label: None, + layout: &pipeline.texture_bind_group_layout, + entries: &[BindGroupEntry { + binding: 0, + resource: BindingResource::TextureView(&view.texture_view), + }], + }); + commands.insert_resource(GameOfLifeImageBindGroup(bind_group)); +} + +#[derive(Resource)] +pub struct GameOfLifePipeline { + texture_bind_group_layout: BindGroupLayout, + init_pipeline: CachedComputePipelineId, + update_pipeline: CachedComputePipelineId, +} + +impl FromWorld for GameOfLifePipeline { + fn from_world(world: &mut World) -> Self { + let texture_bind_group_layout = + world + .resource::() + .create_bind_group_layout(&BindGroupLayoutDescriptor { + label: None, + entries: &[BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStages::COMPUTE, + ty: BindingType::StorageTexture { + access: StorageTextureAccess::ReadWrite, + format: TextureFormat::Rgba8Snorm, + view_dimension: TextureViewDimension::D2, + }, + count: None, + }], + }); + let shader = world + .resource::() + .load("rust-gpu/shader.rust-gpu.msgpack"); + let pipeline_cache = world.resource::(); + let init_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor { + label: None, + layout: vec![texture_bind_group_layout.clone()], + push_constant_ranges: Vec::new(), + shader: shader.clone(), + shader_defs: vec![], + entry_point: Cow::from("init"), + }); + let update_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor { + label: None, + layout: vec![texture_bind_group_layout.clone()], + push_constant_ranges: Vec::new(), + shader, + shader_defs: vec![], + entry_point: Cow::from("update"), + }); + + GameOfLifePipeline { + texture_bind_group_layout, + init_pipeline, + update_pipeline, + } + } +} + +enum GameOfLifeState { + Loading, + Init, + Update, +} + +struct GameOfLifeNode { + state: GameOfLifeState, +} + +impl Default for GameOfLifeNode { + fn default() -> Self { + Self { + state: GameOfLifeState::Loading, + } + } +} + +impl render_graph::Node for GameOfLifeNode { + fn update(&mut self, world: &mut World) { + let pipeline = world.resource::(); + let pipeline_cache = world.resource::(); + + // if the corresponding pipeline has loaded, transition to the next stage + match self.state { + GameOfLifeState::Loading => { + if let CachedPipelineState::Ok(_) = + pipeline_cache.get_compute_pipeline_state(pipeline.init_pipeline) + { + self.state = GameOfLifeState::Init; + } + } + GameOfLifeState::Init => { + if let CachedPipelineState::Ok(_) = + pipeline_cache.get_compute_pipeline_state(pipeline.update_pipeline) + { + self.state = GameOfLifeState::Update; + } + } + GameOfLifeState::Update => {} + } + } + + fn run( + &self, + _graph: &mut render_graph::RenderGraphContext, + render_context: &mut RenderContext, + world: &World, + ) -> Result<(), render_graph::NodeRunError> { + let texture_bind_group = &world.resource::().0; + let pipeline_cache = world.resource::(); + let pipeline = world.resource::(); + + let mut pass = render_context + .command_encoder() + .begin_compute_pass(&ComputePassDescriptor::default()); + + pass.set_bind_group(0, texture_bind_group, &[]); + + // select the pipeline based on the current state + match self.state { + GameOfLifeState::Loading => {} + GameOfLifeState::Init => { + let init_pipeline = pipeline_cache + .get_compute_pipeline(pipeline.init_pipeline) + .unwrap(); + pass.set_pipeline(init_pipeline); + pass.dispatch_workgroups(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1); + } + GameOfLifeState::Update => { + let update_pipeline = pipeline_cache + .get_compute_pipeline(pipeline.update_pipeline) + .unwrap(); + pass.set_pipeline(update_pipeline); + pass.dispatch_workgroups(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1); + } + } + + Ok(()) + } +} + + +#[derive(Default)] +struct RustGpuMsgpackLoader; + +impl AssetLoader for RustGpuMsgpackLoader { + fn load<'a>( + &'a self, + bytes: &'a [u8], + load_context: &'a mut bevy::asset::LoadContext, + ) -> bevy::utils::BoxedFuture<'a, Result<(), bevy::asset::Error>> { + Box::pin(async move { + let spirv_bytes: RustGpuBuilderOutput = rmp_serde::from_slice(bytes).unwrap(); + let shader = match spirv_bytes.modules { + bevy_rust_gpu::RustGpuBuilderModules::Single(s) => { + Shader::from_spirv(s, "") + }, + bevy_rust_gpu::RustGpuBuilderModules::Multi(_) => todo!(), + }; + load_context.set_default_asset(LoadedAsset::new(shader)); + Ok(()) + }) + } + + fn extensions(&self) -> &[&str] { + &["rust-gpu.msgpack"] + } +} \ No newline at end of file diff --git a/bevy-app/crates/viewer/examples/sdf-2d-material.rs b/bevy-app/crates/viewer/examples/sdf-2d-material.rs index 103df56..c82dae5 100644 --- a/bevy-app/crates/viewer/examples/sdf-2d-material.rs +++ b/bevy-app/crates/viewer/examples/sdf-2d-material.rs @@ -8,10 +8,10 @@ use bevy::{ MaterialMeshBundle, Mesh, Msaa, PluginGroup, PointLight, PointLightBundle, Quat, Query, Res, ResMut, Transform, Vec2, Vec3, With, }, - reflect::TypeUuid, + reflect::{TypeUuid, Reflect}, render::render_resource::AsBindGroup, sprite::{Material2d, MaterialMesh2dBundle, Mesh2dHandle}, - time::Time, + time::Time, asset::ChangeWatcher, }; use bevy_rust_gpu::{ @@ -39,7 +39,7 @@ impl EntryPoint for FragmentNormal { } /// Example RustGpu material tying together [`VertexWarp`] and [`FragmentNormal`] -#[derive(Debug, Default, Copy, Clone, AsBindGroup, TypeUuid)] +#[derive(Debug, Default, Copy, Clone, AsBindGroup, TypeUuid, Reflect)] #[uuid = "cbeff76a-27e9-42c8-bb17-73e81ba62a36"] pub struct ExampleMaterial {} @@ -69,16 +69,16 @@ fn main() { app.add_plugins(DefaultPlugins.set( // Configure the asset plugin to watch the workspace path for changes AssetPlugin { - watch_for_changes: true, + watch_for_changes: ChangeWatcher::with_delay(std::time::Duration::from_secs(1)), ..default() }, )); // Add the Rust-GPU plugin - app.add_plugin(RustGpuPlugin::default()); + app.add_plugins(RustGpuPlugin::default()); // Setup `RustGpu` - app.add_plugin(RustGpuMaterial2dPlugin::::default()); + app.add_plugins(RustGpuMaterial2dPlugin::::default()); RustGpu::::export_to(ENTRY_POINTS_PATH); // Set clear color to black diff --git a/bevy-app/crates/viewer/examples/sdf-3d-material.rs b/bevy-app/crates/viewer/examples/sdf-3d-material.rs index 89880bd..5e6accb 100644 --- a/bevy-app/crates/viewer/examples/sdf-3d-material.rs +++ b/bevy-app/crates/viewer/examples/sdf-3d-material.rs @@ -8,7 +8,7 @@ use bevy::{ DirectionalLightBundle, Material, MaterialMeshBundle, Mesh, Msaa, PluginGroup, PointLight, PointLightBundle, Quat, Query, Res, ResMut, Transform, Vec3, With, }, - reflect::TypeUuid, + reflect::{TypeUuid, Reflect, TypePath, FromReflect}, render::render_resource::AsBindGroup, time::Time, utils::Uuid, @@ -64,7 +64,7 @@ where } /// Example RustGpu material tying together [`VertexWarp`] and [`FragmentNormal`] -#[derive(Debug, Default, Copy, Clone, AsBindGroup)] +#[derive(Debug, Default, Copy, Clone, AsBindGroup, Reflect)] pub struct Sdf3dMaterial { pub sdf: T, pub alpha_mode: AlphaMode, @@ -86,6 +86,7 @@ where + Clone + Send + Sync + + FromReflect + TypePath + 'static, { fn specialize( @@ -115,6 +116,7 @@ where + Clone + Send + Sync + + FromReflect + TypePath + 'static, { type Vertex = VertexSdf3d; @@ -126,6 +128,7 @@ pub struct Rotate; pub type Sdf = SphereTraceLipschitz<400, ScaleUv>>>; + fn main() { let mut app = App::default(); diff --git a/bevy-app/crates/viewer/examples/simple-material.rs b/bevy-app/crates/viewer/examples/simple-material.rs index 225a18c..c5cce39 100644 --- a/bevy-app/crates/viewer/examples/simple-material.rs +++ b/bevy-app/crates/viewer/examples/simple-material.rs @@ -5,8 +5,8 @@ use bevy::{ MaterialMeshBundle, Mesh, PluginGroup, PointLight, PointLightBundle, Quat, Res, ResMut, Transform, Vec3, }, - reflect::TypeUuid, - render::render_resource::AsBindGroup, + reflect::{TypeUuid, Reflect}, + render::render_resource::AsBindGroup, asset::ChangeWatcher, }; use bevy_rust_gpu::{ @@ -35,7 +35,7 @@ impl EntryPoint for FragmentNormal { } /// Example RustGpu material tying together [`VertexWarp`] and [`FragmentNormal`] -#[derive(Debug, Default, Copy, Clone, AsBindGroup, TypeUuid)] +#[derive(Debug, Default, Copy, Clone, AsBindGroup, TypeUuid, Reflect)] #[uuid = "cbeff76a-27e9-42c8-bb17-73e81ba62a36"] pub struct ExampleMaterial {} @@ -53,7 +53,7 @@ fn main() { app.add_plugins(DefaultPlugins.set( // Configure the asset plugin to watch the workspace path for changes AssetPlugin { - watch_for_changes: true, + watch_for_changes: ChangeWatcher::with_delay(std::time::Duration::from_secs(1)), ..default() }, )); diff --git a/bevy-app/crates/viewer/examples/standard-material.rs b/bevy-app/crates/viewer/examples/standard-material.rs index e1c90fc..5246a2e 100644 --- a/bevy-app/crates/viewer/examples/standard-material.rs +++ b/bevy-app/crates/viewer/examples/standard-material.rs @@ -1,9 +1,9 @@ -use bevy::prelude::{ +use bevy::{prelude::{ default, shape::Cube, App, AssetPlugin, AssetServer, Assets, Camera3dBundle, Color, Commands, DefaultPlugins, DirectionalLight, DirectionalLightBundle, MaterialMeshBundle, Mesh, PluginGroup, PointLight, PointLightBundle, Quat, Res, ResMut, StandardMaterial, Transform, Vec3, -}; +}, asset::ChangeWatcher}; use bevy_rust_gpu::prelude::{RustGpu, RustGpuMaterialPlugin, RustGpuPlugin}; @@ -20,7 +20,7 @@ fn main() { app.add_plugins(DefaultPlugins.set( // Configure the asset plugin to watch the workspace path for changes AssetPlugin { - watch_for_changes: true, + watch_for_changes: ChangeWatcher::with_delay(std::time::Duration::from_secs(1)), ..default() }, )); diff --git a/run-docker.sh b/run-docker.sh new file mode 100644 index 0000000..afcc6e5 --- /dev/null +++ b/run-docker.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -ex + +# fix docker when using Docker + Git for Windows Bash (mingw) +export MSYS_NO_PATHCONV=1 + +export IMGNAME="rust-gpu-builder:local" +export CONTAINER="example-rust-gpu-builder" + +if [[ "$(docker images -q $IMGNAME 2> /dev/null)" == "" ]]; then + docker build . --tag $IMGNAME +fi +( docker rm -f $CONTAINER || true; docker run --rm --name $CONTAINER -v "$(pwd):/root/mnt" $IMGNAME /root/mnt/rust-gpu/entrypoint.sh ) diff --git a/rust-gpu/Cargo.lock b/rust-gpu/Cargo.lock index d1750d2..cddf02e 100644 --- a/rust-gpu/Cargo.lock +++ b/rust-gpu/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ab_glyph" -version = "0.2.21" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5110f1c78cf582855d895ecd0746b653db010cec6d9f5575293f27934d980a39" +checksum = "80179d7dd5d7e8c285d67c4a1e652972a92de7475beddfb92028c76463b13225" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -20,24 +20,24 @@ checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" [[package]] name = "accesskit" -version = "0.10.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704d532b1cd3d912bb37499c55a81ac748cc1afa737eedd100ba441acdd47d38" +checksum = "76eb1adf08c5bcaa8490b9851fd53cca27fa9880076f178ea9d29f05196728a8" [[package]] name = "accesskit_consumer" -version = "0.14.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba8b23cfca3944012ee2e5c71c02077a400e034c720eed6bd927cb6b4d1fd9" +checksum = "04bb4d9e4772fe0d47df57d0d5dbe5d85dd05e2f37ae1ddb6b105e76be58fb00" dependencies = [ "accesskit", ] [[package]] name = "accesskit_macos" -version = "0.6.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d062544d6cc36f4213323b7cb3a0d74ddff4b0d2311ab5e7596f4278bb2cc9" +checksum = "134d0acf6acb667c89d3332999b1a5df4edbc8d6113910f392ebb73f2b03bb56" dependencies = [ "accesskit", "accesskit_consumer", @@ -47,23 +47,23 @@ dependencies = [ [[package]] name = "accesskit_windows" -version = "0.13.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf5b3c3828397ee832ba4a72fb1a4ace10f781e31885f774cbd531014059115" +checksum = "9eac0a7f2d7cd7a93b938af401d3d8e8b7094217989a7c25c55a953023436e31" dependencies = [ "accesskit", "accesskit_consumer", "arrayvec", "once_cell", "paste", - "windows 0.44.0", + "windows 0.48.0", ] [[package]] name = "accesskit_winit" -version = "0.12.4" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcb615217efc79c4bed3094c4ca76c4bc554751d1da16f3ed4ba0459b1e8f31" +checksum = "825d23acee1bd6d25cbaa3ca6ed6e73faf24122a774ec33d52c5c86c6ab423c0" dependencies = [ "accesskit", "accesskit_macos", @@ -73,9 +73,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -88,32 +88,51 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ + "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.0.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "alsa" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8512c9117059663fb5606788fbca3619e2a91dac0e3fe516242eab1fa6be5e44" +checksum = "e2562ad8dcf0f789f65c6fdaad8a8a9708ed6b488e649da28c01656ad66b8b47" dependencies = [ "alsa-sys", - "bitflags", + "bitflags 1.3.2", "libc", "nix 0.24.3", ] @@ -130,12 +149,12 @@ dependencies = [ [[package]] name = "android-activity" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c77a0045eda8b888c76ea473c2b0515ba6f471d318f8927c5c72240937035a6" +checksum = "64529721f27c2314ced0890ce45e469574a73e5e6fdd6e9da1860eb29285f5e0" dependencies = [ "android-properties", - "bitflags", + "bitflags 1.3.2", "cc", "jni-sys", "libc", @@ -143,7 +162,7 @@ dependencies = [ "ndk", "ndk-context", "ndk-sys", - "num_enum", + "num_enum 0.6.1", ] [[package]] @@ -154,9 +173,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "android_log-sys" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" +checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" [[package]] name = "android_system_properties" @@ -169,30 +188,29 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -208,9 +226,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -218,9 +236,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "approx" @@ -239,41 +257,54 @@ checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "ash" -version = "0.37.2+1.3.238" +version = "0.37.3+1.3.251" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28bf19c1f0a470be5fbf7522a308a05df06610252c5bcf5143e1b23f629a9a03" +checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" dependencies = [ - "libloading", + "libloading 0.7.4", ] [[package]] name = "async-channel" -version = "1.8.0" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "d37875bd9915b7d67c2f117ea2c30a0989874d0b2cb694fe25403c85763c0c9e" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 3.0.1", + "event-listener-strategy", "futures-core", + "pin-project-lite", ] [[package]] name = "async-executor" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" dependencies = [ - "async-lock", + "async-lock 2.8.0", "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "fastrand 2.0.1", + "futures-lite 1.13.0", "slab", ] @@ -283,32 +314,43 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "blocking", - "futures-lite", + "futures-lite 1.13.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", ] [[package]] name = "async-lock" -version = "2.7.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" dependencies = [ - "event-listener", + "event-listener 3.0.1", + "event-listener-strategy", + "pin-project-lite", ] [[package]] name = "async-task" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" [[package]] name = "atomic-waker" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" @@ -318,15 +360,15 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide 0.6.2", + "miniz_oxide", "object", "rustc-demangle", ] @@ -338,29 +380,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] -name = "bevy" -version = "0.10.1" +name = "base64" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93f906133305915d63f04108e6873c1b93a6605fe374b8f3391f6bda093e396" -dependencies = [ - "bevy_internal", -] +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] -name = "bevy-pbr-rust" -version = "0.4.0" -source = "git+https://github.com/bevy-rust-gpu/bevy-pbr-rust?tag=v0.4.0#16893a82058e902bc7aacd2a1be7d8a1b6f148f1" +name = "bevy" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c6d3ec4f89e85294dc97334c5b271ddc301fdf67ac9bb994fe44d9273e6ed7" dependencies = [ - "permutate-macro", - "rust-gpu-bridge", - "spirv-std", + "bevy_internal", ] [[package]] name = "bevy_a11y" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037c4063f7dac1a5d596eb47f40782a04ca5838dc4274dbbadc90eb81efe5169" +checksum = "132c9e35a77c5395951f6d25fa2c52ee92296353426df4f961e60f3ff47e2e42" dependencies = [ "accesskit", "bevy_app", @@ -370,9 +408,9 @@ dependencies = [ [[package]] name = "bevy_animation" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0dc19f21846ebf8ba4d96617c2517b5119038774aa5dbbaf1bff122332b359c" +checksum = "f44eae3f1c35a87e38ad146f72317f19ce7616dad8bbdfb88ee752c1282d28c5" dependencies = [ "bevy_app", "bevy_asset", @@ -381,6 +419,7 @@ dependencies = [ "bevy_hierarchy", "bevy_math", "bevy_reflect", + "bevy_render", "bevy_time", "bevy_transform", "bevy_utils", @@ -388,13 +427,14 @@ dependencies = [ [[package]] name = "bevy_app" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01db46963eb9486f7884121527ec69751d0e448f9e1d5329e80ea3424118a31a" +checksum = "f557a7d59e1e16892d7544fc37316506ee598cb5310ef0365125a30783c11531" dependencies = [ "bevy_derive", "bevy_ecs", "bevy_reflect", + "bevy_tasks", "bevy_utils", "downcast-rs", "wasm-bindgen", @@ -403,11 +443,12 @@ dependencies = [ [[package]] name = "bevy_asset" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98609b4b0694a23bde0628aed626644967991f167aad9db2afb68dacb0017540" +checksum = "9714af523da4cdf58c42a317e5ed40349708ad954a18533991fd64c8ae0a6f68" dependencies = [ "anyhow", + "async-channel 1.9.0", "bevy_app", "bevy_diagnostic", "bevy_ecs", @@ -418,9 +459,9 @@ dependencies = [ "bevy_winit", "crossbeam-channel", "downcast-rs", - "fastrand", + "fastrand 1.9.0", "js-sys", - "notify", + "notify 6.1.1", "parking_lot", "serde", "thiserror", @@ -431,13 +472,14 @@ dependencies = [ [[package]] name = "bevy_audio" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b9f9b87b0d094268ce52bb75ff346ae0054573f7acc5d66bf032e2c88f748d" +checksum = "4de308bd63a2f7a0b77ffeb7cf00cc185ec01393c5db2091fe03964f97152749" dependencies = [ "anyhow", "bevy_app", "bevy_asset", + "bevy_derive", "bevy_ecs", "bevy_math", "bevy_reflect", @@ -450,9 +492,9 @@ dependencies = [ [[package]] name = "bevy_core" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee53d7b4691b57207d72e996992c995a53f3e8d21ca7151ca3956d9ce7d232e" +checksum = "3d5272321be5fcf5ce2fb16023bc825bb10dfcb71611117296537181ce950f48" dependencies = [ "bevy_app", "bevy_ecs", @@ -465,12 +507,13 @@ dependencies = [ [[package]] name = "bevy_core_pipeline" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093ae5ced77251602ad6e43521e2acc1a5570bf85b80f232f1a7fdd43b50f8d8" +checksum = "67382fa9c96ce4f4e5833ed7cedd9886844a8f3284b4a717bd4ac738dcdea0c3" dependencies = [ "bevy_app", "bevy_asset", + "bevy_core", "bevy_derive", "bevy_ecs", "bevy_math", @@ -478,27 +521,27 @@ dependencies = [ "bevy_render", "bevy_transform", "bevy_utils", - "bitflags", + "bitflags 2.4.1", "radsort", "serde", ] [[package]] name = "bevy_derive" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff0add5ab4a6b2b7e86e18f9043bb48b6386faa3b56abaa0ed97a3d669a1992" +checksum = "a44e4e2784a81430199e4157e02903a987a32127c773985506f020e7d501b62e" dependencies = [ "bevy_macro_utils", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] name = "bevy_diagnostic" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c778422643b0adee9e82abbd07e1e906eb9947c274a9b18e0f7fbf137d4c34" +checksum = "6babb230dc383c98fdfc9603e3a7a2a49e1e2879dbe8291059ef37dca897932e" dependencies = [ "bevy_app", "bevy_core", @@ -511,41 +554,42 @@ dependencies = [ [[package]] name = "bevy_ecs" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed2f74687ccf13046c0f8e3b00dc61d7e656877b4a1380cf04635bb74d8e586" +checksum = "266144b36df7e834d5198049e037ecdf2a2310a76ce39ed937d1b0a6a2c4e8c6" dependencies = [ - "async-channel", + "async-channel 1.9.0", "bevy_ecs_macros", "bevy_ptr", "bevy_reflect", "bevy_tasks", "bevy_utils", "downcast-rs", - "event-listener", + "event-listener 2.5.3", "fixedbitset", "rustc-hash", "serde", + "thiserror", "thread_local", ] [[package]] name = "bevy_ecs_macros" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97fd126a0db7b30fb1833614b3a657b44ac88485741c33b2780e25de0f96d78" +checksum = "7157a9c3be038d5008ee3f114feb6cf6b39c1d3d32ee21a7cacb8f81fccdfa80" dependencies = [ "bevy_macro_utils", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] name = "bevy_encase_derive" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c086ebdc1f5522787d63772943277cc74a279445fb65db4d58c2c5330654648e" +checksum = "d0ac0f55ad6bca1be7b0f35bbd5fc95ed3d31e4e9db158fee8e5327f59006001" dependencies = [ "bevy_macro_utils", "encase_derive_impl", @@ -553,25 +597,48 @@ dependencies = [ [[package]] name = "bevy_gilrs" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f32eb07e8c9ea4be7195ccec10d8f9ad70200f3ae2e13adc4b84df9f50bb1c6" +checksum = "65f4d79c55829f8016014593a42453f61a564ffb06ef79460d25696ccdfac67b" dependencies = [ "bevy_app", "bevy_ecs", "bevy_input", + "bevy_log", + "bevy_time", "bevy_utils", "gilrs", + "thiserror", +] + +[[package]] +name = "bevy_gizmos" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e286a3e7276431963f4aa29165ea5429fa7dbbc6d5c5ba0c531e7dd44ecc88a2" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_core", + "bevy_core_pipeline", + "bevy_ecs", + "bevy_math", + "bevy_pbr", + "bevy_reflect", + "bevy_render", + "bevy_sprite", + "bevy_transform", + "bevy_utils", ] [[package]] name = "bevy_gltf" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2707632208617c3660ea7a1d2ef2ccc84b59f217c2f01a1d0abe81db4ae7bbde" +checksum = "f07494a733dca032e71a20f4b1f423de765da49cbff34406ae6cd813f9b50c41" dependencies = [ "anyhow", - "base64", + "base64 0.13.1", "bevy_animation", "bevy_app", "bevy_asset", @@ -590,14 +657,16 @@ dependencies = [ "bevy_utils", "gltf", "percent-encoding", + "serde", + "serde_json", "thiserror", ] [[package]] name = "bevy_hierarchy" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d04099865a13d1fd8bf3c044a80148cb3d23bfe8c3d5f082dda2ce091d85532" +checksum = "103f8f58416ac6799b8c7f0b418f1fac9eba44fa924df3b0e16b09256b897e3d" dependencies = [ "bevy_app", "bevy_core", @@ -610,9 +679,9 @@ dependencies = [ [[package]] name = "bevy_input" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15d40aa636bb656967ac16ca36066ab7a7bb9179e1b0390c5705e54208e8fd7" +checksum = "ffbd935401101ac8003f3c3aea70788c65ad03f7a32716a10608bedda7a648bc" dependencies = [ "bevy_app", "bevy_ecs", @@ -624,9 +693,9 @@ dependencies = [ [[package]] name = "bevy_internal" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862b11931c5874cb00778ffb715fc526ee49e52a493d3bcf50e8010f301858b3" +checksum = "e0e35a9b2bd29aa784b3cc416bcbf2a298f69f00ca51fd042ea39d9af7fad37e" dependencies = [ "bevy_a11y", "bevy_animation", @@ -639,6 +708,7 @@ dependencies = [ "bevy_diagnostic", "bevy_ecs", "bevy_gilrs", + "bevy_gizmos", "bevy_gltf", "bevy_hierarchy", "bevy_input", @@ -662,9 +732,9 @@ dependencies = [ [[package]] name = "bevy_log" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25980c90ceaad34d09a53291e72ca56fcc754a974cd4654fffcf5b68b283b7a7" +checksum = "07dcc615ff4f617b06c3f9522fca3c55d56f9644db293318f8ab68fcdea5d4fe" dependencies = [ "android_log-sys", "bevy_app", @@ -678,39 +748,40 @@ dependencies = [ [[package]] name = "bevy_macro_utils" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b2fee53b2497cdc3bffff2ddf52afa751242424a5fd0d51d227d4dab081d0d9" +checksum = "23ddc18d489b4e57832d4958cde7cd2f349f0ad91e5892ac9e2f2ee16546b981" dependencies = [ "quote", - "syn 1.0.109", + "rustc-hash", + "syn 2.0.39", "toml_edit", ] [[package]] name = "bevy_math" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da6a1109d06fe947990db032e719e162414cf9bf7a478dcc52742f1c7136c42a" +checksum = "78286a81fead796dc4b45ab14f4f02fe29a94423d3587bcfef872b2a8e0a474b" dependencies = [ - "glam 0.23.0", + "glam", "serde", ] [[package]] name = "bevy_mikktspace" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39106bc2ee21fce9496d2e15e0ba7925dff63e3eae10f7c1fc0094b56ad9f2bb" +checksum = "6cfc2a21ea47970a9b1f0f4735af3256a8f204815bd756110051d10f9d909497" dependencies = [ - "glam 0.23.0", + "glam", ] [[package]] name = "bevy_pbr" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f507cef55812aa70c2ec2b30fb996eb285fa7497d974cf03f76ec49c77fbe27" +checksum = "63ca796a619e61cd43a0a3b11fde54644f7f0732a1fba1eef5d406248c6eba85" dependencies = [ "bevy_app", "bevy_asset", @@ -723,22 +794,23 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags", + "bitflags 2.4.1", "bytemuck", + "naga_oil", "radsort", ] [[package]] name = "bevy_ptr" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b88451d4c5a353bff67dbaa937b6886efd26ae114769c17f2b35099c7a4de" +checksum = "72c7586401a46f7d8e436028225c1df5288f2e0082d066b247a82466fea155c6" [[package]] name = "bevy_reflect" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc3979471890e336f3ba87961ef3ecd45c331cf2cb2f582c885e541af228b48" +checksum = "0778197a1eb3e095a71417c74b7152ede02975cdc95b5ea4ddc5251ed00a2eb5" dependencies = [ "bevy_math", "bevy_ptr", @@ -746,36 +818,37 @@ dependencies = [ "bevy_utils", "downcast-rs", "erased-serde", - "glam 0.23.0", + "glam", "once_cell", "parking_lot", "serde", "smallvec", + "smol_str", "thiserror", ] [[package]] name = "bevy_reflect_derive" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc7ea7c9bc2c531eb29ba5619976613d6680453ff5dd4a7fcd08848e8bec5ad" +checksum = "342a4b2d09db22c48607d23ad59a056aff1ee004549050a51d490d375ba29528" dependencies = [ "bevy_macro_utils", "bit-set", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", "uuid", ] [[package]] name = "bevy_render" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee1e126226f0a4d439bf82fe07c1104f894a6a365888e3eba7356f9647e77a83" +checksum = "39df4824b760928c27afc7b00fb649c7a63c9d76661ab014ff5c86537ee906cb" dependencies = [ "anyhow", - "async-channel", + "async-channel 1.9.0", "bevy_app", "bevy_asset", "bevy_core", @@ -793,16 +866,18 @@ dependencies = [ "bevy_transform", "bevy_utils", "bevy_window", - "bitflags", + "bitflags 2.4.1", + "bytemuck", "codespan-reporting", "downcast-rs", "encase", - "futures-lite", + "futures-lite 1.13.0", "hexasphere", "image", + "js-sys", "ktx2", "naga", - "once_cell", + "naga_oil", "parking_lot", "regex", "ruzstd", @@ -810,27 +885,29 @@ dependencies = [ "smallvec", "thiserror", "thread_local", + "wasm-bindgen", + "web-sys", "wgpu", "wgpu-hal", ] [[package]] name = "bevy_render_macros" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652f8c4d9577c6e6a8b3dfd8a4ce331e8b6ecdbb99636a4b2701dec50104d6bc" +checksum = "0bd08c740aac73363e32fb45af869b10cec65bcb76fe3e6cd0f8f7eebf4c36c9" dependencies = [ "bevy_macro_utils", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] name = "bevy_scene" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de59637d27726251091120ce6f63917328ffd60aaccbda4d65a615873aff631" +checksum = "bd47e1263506153bef3a8be97fe2d856f206d315668c4f97510ca6cc181d9681" dependencies = [ "anyhow", "bevy_app", @@ -850,9 +927,9 @@ dependencies = [ [[package]] name = "bevy_sprite" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c110358fe3651a5796fd1c07989635680738f5b5c7e9b8a463dd50d12bb78410" +checksum = "68a8ca824fad75c6ef74cfbbba0a4ce3ccc435fa23d6bf3f003f260548813397" dependencies = [ "bevy_app", "bevy_asset", @@ -865,7 +942,7 @@ dependencies = [ "bevy_render", "bevy_transform", "bevy_utils", - "bitflags", + "bitflags 2.4.1", "bytemuck", "fixedbitset", "guillotiere", @@ -875,24 +952,23 @@ dependencies = [ [[package]] name = "bevy_tasks" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de86364316e151aeb0897eaaa917c3ad5ee5ef1471a939023cf7f2d5ab76955" +checksum = "c73bbb847c83990d3927005090df52f8ac49332e1643d2ad9aac3cd2974e66bf" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-executor", "async-task", "concurrent-queue", - "futures-lite", - "once_cell", + "futures-lite 1.13.0", "wasm-bindgen-futures", ] [[package]] name = "bevy_text" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995188f59dc06da3fc951e1f58a105cde2c817d5330ae67ddc0a140f46482f6b" +checksum = "692288ab7b0a9f8b38058964c52789fc6bcb63703b23de51cce90ec41bfca355" dependencies = [ "ab_glyph", "anyhow", @@ -913,9 +989,9 @@ dependencies = [ [[package]] name = "bevy_time" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3edbd605df1bced312eb9888d6be3d5a5fcac3d4140038bbe3233d218399eef" +checksum = "3d58d6dbae9c8225d8c0e0f04d2c5dbb71d22adc01ecd5ab3cebc364139e4a6d" dependencies = [ "bevy_app", "bevy_ecs", @@ -927,9 +1003,9 @@ dependencies = [ [[package]] name = "bevy_transform" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24383dfb97d8a14b17721ecfdf58556eff5ea9a4b2a3d91accf2b472783880b0" +checksum = "3b9b0ac0149a57cd846cb357a35fc99286f9848e53d4481954608ac9552ed2d4" dependencies = [ "bevy_app", "bevy_ecs", @@ -940,9 +1016,9 @@ dependencies = [ [[package]] name = "bevy_ui" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb597aeed4e1bf5e6913879c3e22a7d50a843b822a7f71a4a80ebdfdf79e68d4" +checksum = "59b6d295a755e5b79e869a09e087029d72974562a521ec7ccfba7141fa948a32" dependencies = [ "bevy_a11y", "bevy_app", @@ -970,14 +1046,14 @@ dependencies = [ [[package]] name = "bevy_utils" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a88ebbca55d360d72e9fe78df0d22e25cd419933c9559e79dae2757f7c4d066" +checksum = "08d9484e32434ea84dc548cff246ce0c6f756c1336f5ea03f24ac120a48595c7" dependencies = [ - "ahash", + "ahash 0.8.6", "bevy_utils_proc_macros", "getrandom", - "hashbrown 0.12.3", + "hashbrown 0.14.2", "instant", "petgraph", "thiserror", @@ -987,20 +1063,20 @@ dependencies = [ [[package]] name = "bevy_utils_proc_macros" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630b92e32fa5cd7917c7d4fdbf63a90af958b01e096239f71bc4f8f3cf40c0d2" +checksum = "5391b242c36f556db01d5891444730c83aa9dd648b6a8fd2b755d22cb3bddb57" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] name = "bevy_window" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad31234754268fbe12050290b0496e2296252a16995a38f94bfb9680a4f09fda" +checksum = "bd584c0da7c4ada6557b09f57f30fb7cff21ccedc641473fc391574b4c9b7944" dependencies = [ "bevy_app", "bevy_ecs", @@ -1013,9 +1089,9 @@ dependencies = [ [[package]] name = "bevy_winit" -version = "0.10.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf17bd6330f7e633b7c56754c776511a8f52cde4bf54c0278f34d7527548f253" +checksum = "bfdc044abdb95790c20053e6326760f0a2985f0dcd78613d397bf35f16039d53" dependencies = [ "accesskit_winit", "approx", @@ -1026,10 +1102,10 @@ dependencies = [ "bevy_hierarchy", "bevy_input", "bevy_math", + "bevy_tasks", "bevy_utils", "bevy_window", "crossbeam-channel", - "once_cell", "raw-window-handle", "wasm-bindgen", "web-sys", @@ -1038,11 +1114,11 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.64.0" +version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" dependencies = [ - "bitflags", + "bitflags 2.4.1", "cexpr", "clang-sys", "lazy_static", @@ -1053,7 +1129,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] @@ -1071,12 +1147,27 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +dependencies = [ + "serde", +] + [[package]] name = "block" version = "0.1.6" @@ -1104,64 +1195,66 @@ dependencies = [ [[package]] name = "blocking" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +checksum = "864b30e660d766b7e9b47347d9b6558a17f1cfa22274034fa6f55b274b3e4620" dependencies = [ - "async-channel", - "async-lock", + "async-channel 2.1.0", + "async-lock 3.0.0", "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "log", + "fastrand 2.0.1", + "futures-io", + "futures-lite 2.0.1", + "piper", + "tracing", ] [[package]] name = "bumpalo" -version = "3.12.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.39", ] [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -1199,50 +1292,48 @@ checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" dependencies = [ "glob", "libc", - "libloading", + "libloading 0.7.4", ] [[package]] name = "clap" -version = "4.2.5" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a1f23fa97e1d1641371b51f35535cb26959b8e27ab50d167a8b996b5bada819" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.2.5" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdc5d93c358224b4d6867ef1356d740de2303e9892edc06c5340daeccd96bab" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", - "bitflags", "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.39", ] [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "codespan-reporting" @@ -1284,9 +1375,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] @@ -1303,35 +1394,41 @@ dependencies = [ [[package]] name = "const_panic" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58baae561b85ca19b3122a9ddd35c8ec40c3bcd14fe89921824eae73f7baffbf" +checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b" [[package]] -name = "convert_case" -version = "0.6.0" +name = "const_soft_float" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ca1caa64ef4ed453e68bb3db612e51cf1b2f5b871337f0fcab1c8f87cc3dff" + +[[package]] +name = "constgebra" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +checksum = "edd23e864550e6dafc1e41ac78ce4f1ccddc8672b40c403524a04ff3f0518420" dependencies = [ - "unicode-segmentation", + "const_soft_float", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "core-foundation" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ - "core-foundation-sys 0.8.4", + "core-foundation-sys", "libc", ] -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" - [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -1344,7 +1441,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-graphics-types", "foreign-types", @@ -1353,32 +1450,31 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", - "foreign-types", "libc", ] [[package]] name = "coreaudio-rs" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb17e2d1795b1996419648915df94bc7103c28f7b48062d7acf4652fc371b2ff" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" dependencies = [ - "bitflags", - "core-foundation-sys 0.6.2", + "bitflags 1.3.2", + "core-foundation-sys", "coreaudio-sys", ] [[package]] name = "coreaudio-sys" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f034b2258e6c4ade2f73bf87b21047567fb913ee9550837c2316d139b0262b24" +checksum = "d8478e5bdad14dce236b9898ea002eabfa87cbe14f0aa538dbe3b6a4bec4332d" dependencies = [ "bindgen", ] @@ -1390,7 +1486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d959d90e938c5493000514b446987c07aed46c668faaa7d34d6c7a67b1a578c" dependencies = [ "alsa", - "core-foundation-sys 0.8.4", + "core-foundation-sys", "coreaudio-rs", "dasp_sample", "jni 0.19.0", @@ -1427,23 +1523,53 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "d3d12" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8f0de2f5a8e7bd4a9eec0e3c781992a4ce1724f68aec7d7a3715344de8b39da" dependencies = [ - "bitflags", - "libloading", + "bitflags 1.3.2", + "libloading 0.7.4", "winapi", ] @@ -1453,6 +1579,25 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -1467,102 +1612,124 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "easy-parallel" -version = "3.3.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4604923390fcaf8b65a1e10b430cc34a3f87958a3b35ebea978b529d776e001" +checksum = "2afbb9b0aef60e4f0d2b18129b6c0dff035a6f7dbbd17c2f38c1432102ee223c" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elsa" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e0aca8dce8856e420195bd13b6a64de3334235ccc9214e824b86b12bf26283" +checksum = "714f766f3556b44e7e4776ad133fcc3445a489517c25c704ace411bb14790194" dependencies = [ - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] [[package]] name = "encase" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6591f13a63571c4821802eb5b10fd1155b1290bce87086440003841c8c3909b" +checksum = "8fce2eeef77fd4a293a54b62aa00ac9daebfbcda4bf8998c5a815635b004aa1c" dependencies = [ "const_panic", "encase_derive", - "glam 0.23.0", + "glam", "thiserror", ] [[package]] name = "encase_derive" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1da6deed1f8b6f5909616ffa695f63a5de54d6a0f084fa715c70c8ed3abac9" +checksum = "0e520cde08cbf4f7cc097f61573ec06ce467019803de8ae82fb2823fa1554a0e" dependencies = [ "encase_derive_impl", ] [[package]] name = "encase_derive_impl" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae489d58959f3c4cdd1250866a05acfb341469affe4fced71aff3ba228be1693" +checksum = "3fe2568f851fd6144a45fa91cfed8fe5ca8fc0b56ba6797bfc1ed2771b90e37c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "erased-serde" -version = "0.3.25" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" dependencies = [ "serde", ] [[package]] -name = "errno" -version = "0.3.1" +name = "euclid" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", + "num-traits", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" dependencies = [ - "cc", - "libc", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "euclid" -version = "0.22.9" +name = "event-listener-strategy" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" +checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" dependencies = [ - "num-traits", + "event-listener 3.0.1", + "pin-project-lite", ] [[package]] -name = "event-listener" -version = "2.5.3" +name = "exr" +version = "1.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] [[package]] name = "fastrand" @@ -1573,24 +1740,30 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" dependencies = [ "simd-adler32", ] [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "windows-sys 0.48.0", ] @@ -1602,12 +1775,21 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", - "miniz_oxide 0.7.1", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", ] [[package]] @@ -1642,15 +1824,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -1658,7 +1840,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -1667,6 +1849,16 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -1678,9 +1870,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", @@ -1690,13 +1882,23 @@ dependencies = [ ] [[package]] -name = "gilrs" -version = "0.10.2" +name = "gif" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fd19844d0eb919aca41d3e4ea0e0b6bf60e1e827558b101c269015b8f5f27a" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" dependencies = [ - "fnv", - "gilrs-core", + "color_quant", + "weezl", +] + +[[package]] +name = "gilrs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62fd19844d0eb919aca41d3e4ea0e0b6bf60e1e827558b101c269015b8f5f27a" +dependencies = [ + "fnv", + "gilrs-core", "log", "uuid", "vec_map", @@ -1704,9 +1906,9 @@ dependencies = [ [[package]] name = "gilrs-core" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd745b0cb1a207756e8fabacf5623066ad6aa543ea0be4bab34e897e6bbe24f9" +checksum = "5ccc99e9b8d63ffcaa334c4babfa31f46e156618a11f63efb6e8e6bcb37b830d" dependencies = [ "core-foundation", "io-kit-sys", @@ -1714,36 +1916,28 @@ dependencies = [ "libc", "libudev-sys", "log", - "nix 0.26.2", + "nix 0.26.4", "uuid", "vec_map", "wasm-bindgen", "web-sys", - "windows 0.48.0", + "windows 0.51.1", ] [[package]] name = "gimli" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" - -[[package]] -name = "glam" -version = "0.22.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774" -dependencies = [ - "num-traits", -] +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "glam" -version = "0.23.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" +checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" dependencies = [ "bytemuck", + "libm", "serde", ] @@ -1755,9 +1949,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "glow" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e007a07a24de5ecae94160f141029e9a347282cfe25d1d58d85d845cf3130f1" +checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728" dependencies = [ "js-sys", "slotmap", @@ -1767,33 +1961,32 @@ dependencies = [ [[package]] name = "gltf" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd7703af6975def3b32573c60aaa5ebfebfab5d879da1e1315d87155ba57bcd" +checksum = "ad2dcfb6dd7a66f9eb3d181a29dcfb22d146b0bcdc2e1ed1713cbf03939a88ea" dependencies = [ "byteorder", "gltf-json", "lazy_static", - "urlencoding", ] [[package]] name = "gltf-derive" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b33dbe598480111e3b2e5a1e9a7e52ad5df0f836e04b8c80fc96f52a9c9f2e" +checksum = "f2cbcea5dd47e7ad4e9ee6f040384fcd7204bbf671aa4f9e7ca7dfc9bfa1de20" dependencies = [ "inflections", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] name = "gltf-json" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5511a759d99beeeef064bd6f81e207c77e3a3431c7499d7590929e35de371f31" +checksum = "7d5b810806b78dde4b71a95cc0e6fdcab34c4c617da3574df166f9987be97d03" dependencies = [ "gltf-derive", "serde", @@ -1814,11 +2007,11 @@ dependencies = [ [[package]] name = "gpu-alloc" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" +checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gpu-alloc-types", ] @@ -1828,7 +2021,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1846,24 +2039,30 @@ dependencies = [ [[package]] name = "gpu-descriptor" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0c02e1ba0bdb14e965058ca34e09c020f8e507a760df1121728e0aef68d57a" +checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" dependencies = [ - "bitflags", + "bitflags 2.4.1", "gpu-descriptor-types", - "hashbrown 0.12.3", + "hashbrown 0.14.2", ] [[package]] name = "gpu-descriptor-types" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" +checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" dependencies = [ - "bitflags", + "bitflags 2.4.1", ] +[[package]] +name = "grid" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c" + [[package]] name = "guillotiere" version = "0.6.2" @@ -1874,13 +2073,22 @@ dependencies = [ "svg_fmt", ] +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash", + "ahash 0.7.7", ] [[package]] @@ -1888,21 +2096,28 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" dependencies = [ - "ahash", + "ahash 0.8.6", + "allocator-api2", "serde", ] [[package]] name = "hassle-rs" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90601c6189668c7345fc53842cb3f3a3d872203d523be1b3cb44a36a3e62fb85" +checksum = "1397650ee315e8891a0df210707f0fc61771b0cc518c3023896064c5407cb3b0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "com-rs", "libc", - "libloading", + "libloading 0.7.4", "thiserror", "widestring", "winapi", @@ -1914,20 +2129,14 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - [[package]] name = "hexasphere" -version = "8.1.0" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd41d443f978bfa380a6dad58b62a08c43bcb960631f13e9d015b911eaf73588" +checksum = "7cb3df16a7bcb1b5bc092abd55e14f77ca70aea14445026e264586fc62889a10" dependencies = [ - "glam 0.23.0", - "once_cell", + "constgebra", + "glam", ] [[package]] @@ -1938,16 +2147,21 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "image" -version = "0.24.6" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" dependencies = [ "bytemuck", "byteorder", "color_quant", + "exr", + "gif", + "jpeg-decoder", "num-rational", "num-traits", "png", + "qoi", + "tiff", ] [[package]] @@ -1960,6 +2174,16 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.2", +] + [[package]] name = "inflections" version = "1.1.1" @@ -1972,7 +2196,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" dependencies = [ - "bitflags", + "bitflags 1.3.2", "inotify-sys", "libc", ] @@ -2000,9 +2224,9 @@ dependencies = [ [[package]] name = "internal-iterator" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668ef46056a63366da9d74f48062da9ece1a27958f2f3704aa6f7421c4433f5" +checksum = "8f104ad240332347ad0f72e8edf5013626eb8c029b61b59c066ad464ae5781af" [[package]] name = "io-kit-sys" @@ -2010,33 +2234,10 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2d4429acc1deff0fbdece0325b4997bdb02b2c245ab7023fd5deca0f6348de" dependencies = [ - "core-foundation-sys 0.8.4", + "core-foundation-sys", "mach2", ] -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "is-terminal" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" -dependencies = [ - "hermit-abi", - "io-lifetimes", - "rustix", - "windows-sys 0.48.0", -] - [[package]] name = "itertools" version = "0.10.5" @@ -2048,9 +2249,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jni" @@ -2088,27 +2289,30 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" dependencies = [ "libc", ] [[package]] -name = "js-sys" -version = "0.3.61" +name = "jpeg-decoder" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" dependencies = [ - "wasm-bindgen", + "rayon", ] [[package]] -name = "json" -version = "0.12.4" +name = "js-sys" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +dependencies = [ + "wasm-bindgen", +] [[package]] name = "khronos-egl" @@ -2117,15 +2321,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", - "libloading", + "libloading 0.7.4", "pkg-config", ] [[package]] name = "kqueue" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" dependencies = [ "kqueue-sys", "libc", @@ -2133,11 +2337,11 @@ dependencies = [ [[package]] name = "kqueue-sys" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", ] @@ -2147,7 +2351,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87d65e08a9ec02e409d27a0139eaa6b9756b4d81fe7cde71f6941a83730ce838" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2162,6 +2366,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "lewton" version = "0.10.2" @@ -2175,9 +2385,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.142" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -2189,11 +2399,32 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "libm" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall 0.4.1", +] [[package]] name = "libudev-sys" @@ -2205,17 +2436,11 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "linux-raw-sys" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c" - [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -2223,12 +2448,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "longest-increasing-subsequence" @@ -2260,14 +2482,23 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] [[package]] name = "metal" @@ -2275,7 +2506,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "core-graphics-types", "foreign-types", @@ -2289,15 +2520,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -2310,30 +2532,29 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "naga" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eafe22a23b797c9bc227c6c896419b26b5bb88fa903417a3adaed08778850d5" +checksum = "bbcc2e0513220fd2b598e6068608d4462db20322c0e77e47f6f488dfcfc279cb" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "codespan-reporting", "hexf-parse", - "indexmap", + "indexmap 1.9.3", "log", "num-traits", - "petgraph", "pp-rs", "rustc-hash", "spirv", @@ -2342,16 +2563,36 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "naga_oil" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be942a5c21c58b9b0bf4d9b99db3634ddb7a916f8e1d1d0b71820cc4150e56b" +dependencies = [ + "bit-set", + "codespan-reporting", + "data-encoding", + "indexmap 1.9.3", + "naga", + "once_cell", + "regex", + "regex-syntax 0.6.29", + "rustc-hash", + "thiserror", + "tracing", + "unicode-ident", +] + [[package]] name = "ndk" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "jni-sys", "ndk-sys", - "num_enum", + "num_enum 0.5.11", "raw-window-handle", "thiserror", ] @@ -2377,21 +2618,27 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", ] [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", - "static_assertions", +] + +[[package]] +name = "noise_perlin" +version = "1.0.0" +dependencies = [ + "image", ] [[package]] @@ -2406,20 +2653,39 @@ dependencies = [ [[package]] name = "notify" -version = "5.1.0" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" +dependencies = [ + "bitflags 1.3.2", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "notify" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags", + "bitflags 2.4.1", "crossbeam-channel", "filetime", "fsevent-sys", "inotify", "kqueue", "libc", + "log", "mio", "walkdir", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -2475,9 +2741,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", "libm", @@ -2489,7 +2755,16 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", ] [[package]] @@ -2504,6 +2779,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "objc" version = "0.2.7" @@ -2551,9 +2838,9 @@ dependencies = [ [[package]] name = "object" -version = "0.30.3" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -2592,17 +2879,17 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "orbclient" -version = "0.3.45" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "221d488cd70617f1bd599ed8ceb659df2147d9393717954d82a0f5e8032a6ab1" +checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "redox_syscall 0.3.5", + "libredox", ] [[package]] @@ -2613,18 +2900,18 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owned_ttf_parser" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "706de7e2214113d63a8238d1910463cfce781129a6f263d13fdb09ff64355ba4" +checksum = "d4586edfe4c648c71797a74c84bacb32b52b212eff5dfe2bb9f2c599844023e7" dependencies = [ "ttf-parser", ] [[package]] name = "parking" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -2638,22 +2925,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.4.1", "smallvec", - "windows-sys 0.45.0", + "windows-targets 0.48.5", ] [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "peeking_take_while" @@ -2663,54 +2950,54 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "permutate-macro" -version = "0.5.0" -source = "git+https://github.com/bevy-rust-gpu/permutate-macro?tag=v0.5.0#7fa16b92e4ad2734f241e6198db79babcf9998e6" -dependencies = [ - "json", - "proc-macro2", - "quote", - "syn 2.0.15", -] +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 2.1.0", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "png" -version = "0.17.8" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -2734,24 +3021,33 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" +checksum = "f89dff0959d98c9758c88826cc002e2c3d0b9dfac4139711d1f30de442f1139b" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2780,6 +3076,26 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "rectangle-pack" version = "0.4.2" @@ -2788,31 +3104,32 @@ checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.8.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.1", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -2824,6 +3141,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.2", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -2832,21 +3160,21 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "renderdoc-sys" -version = "0.7.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" +checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" [[package]] name = "rmp" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" dependencies = [ "byteorder", "num-traits", @@ -2855,9 +3183,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b13be192e0220b8afb7222aa5813cb62cc269ebb5cac346ca6487681d2913e" +checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" dependencies = [ "byteorder", "rmp", @@ -2866,9 +3194,9 @@ dependencies = [ [[package]] name = "rodio" -version = "0.17.1" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf1d4dea18dff2e9eb6dca123724f8b60ef44ad74a9ad283cdfe025df7e73fa" +checksum = "3b1bb7b48ee48471f55da122c0044fcc7600cfcc85db88240b89cb832935e611" dependencies = [ "cpal", "lewton", @@ -2876,13 +3204,14 @@ dependencies = [ [[package]] name = "ron" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ - "base64", - "bitflags", + "base64 0.21.5", + "bitflags 2.4.1", "serde", + "serde_derive", ] [[package]] @@ -2896,25 +3225,17 @@ dependencies = [ "spirv", ] -[[package]] -name = "rust-gpu-bridge" -version = "0.5.0" -source = "git+https://github.com/bevy-rust-gpu/rust-gpu-bridge?tag=v0.5.0#da8b209ed46f87b1e56ec3fd2b8b02d49b0de0ce" -dependencies = [ - "spirv-std", -] - [[package]] name = "rust-gpu-builder" version = "0.5.0" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-executor", "async-fs", "clap", "easy-parallel", - "futures-lite", - "notify", + "futures-lite 1.13.0", + "notify 5.2.0", "rmp-serde", "rust-gpu-builder-shared", "serde_json", @@ -2926,21 +3247,12 @@ dependencies = [ [[package]] name = "rust-gpu-builder-shared" version = "0.2.0" -source = "git+https://github.com/bevy-rust-gpu/rust-gpu-builder-shared#0994e71ae2dc7b595833343ca3751b5175111fe4" dependencies = [ "bevy", + "bevy_reflect", "serde", ] -[[package]] -name = "rust-gpu-sdf" -version = "0.1.0" -source = "git+https://github.com/bevy-rust-gpu/rust-gpu-sdf?tag=prerelease#8a7a38584f4caef54a4cdd8cfb1a7164f8b5e32e" -dependencies = [ - "rust-gpu-bridge", - "type-fields", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2955,14 +3267,14 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_codegen_spirv" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48862935255ac76002118e3561c54f3fb413a752ef5cd0bdae693cf5c5ce37a5" +checksum = "00f05d43c1d9ef3b0e5e2be3dcc9025e5ed103f99c36bb29a1b396386bd032ce" dependencies = [ "ar", "either", "hashbrown 0.11.2", - "indexmap", + "indexmap 1.9.3", "itertools", "lazy_static", "libc", @@ -2983,43 +3295,39 @@ dependencies = [ [[package]] name = "rustc_codegen_spirv-types" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339309d7fce2e7204decea1b2683c4d439a6ebe4c1518d8134fe10aefeae7362" +checksum = "13333711bd68d2a02617c2093fa6535ae40024fef610c37e6826d1ea77e97710" dependencies = [ "rspirv", "serde", ] [[package]] -name = "rustix" -version = "0.37.17" +name = "rustc_version" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc809f704c03a812ac71f22456c857be34185cac691a4316f27ab0f633bb9009" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", + "semver", ] [[package]] name = "ruzstd" -version = "0.2.4" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cada0ef59efa6a5f4dc5e491f93d9f31e3fc7758df421ff1de8a706338e1100" +checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc" dependencies = [ "byteorder", + "thiserror-core", "twox-hash", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -3042,35 +3350,41 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.191" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "a834c4821019838224821468552240d4d95d14e751986442c816572d39a080c9" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.191" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "46fa52d5646bce91b680189fe5b1c049d2ea38dabb4e2e7c8d00ca12cfbfbcfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.39", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -3081,39 +3395,36 @@ dependencies = [ name = "shader" version = "0.1.0" dependencies = [ - "bevy-pbr-rust", - "permutate-macro", - "rust-gpu-bridge", - "rust-gpu-sdf", + "noise_perlin", "spirv-std", ] [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "shlex" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "simd-adler32" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -3129,23 +3440,42 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" dependencies = [ "serde", ] [[package]] -name = "spirt" +name = "smol_str" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24fa996f12f3c667efbceaa99c222b8910a295a14d2c43c3880dfab2752def7" +checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +dependencies = [ + "serde", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spirt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e1f7903720ff818d6da824edf2c4082c6e7a029a99317fd10c39dd7c40c7ff" dependencies = [ "arrayvec", "bytemuck", + "derive_more", "elsa", - "indexmap", + "indexmap 1.9.3", "internal-iterator", "itertools", "lazy_static", @@ -3162,15 +3492,15 @@ version = "0.2.0+1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" dependencies = [ - "bitflags", + "bitflags 1.3.2", "num-traits", ] [[package]] name = "spirv-builder" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0310607328cbb098b681e4580a25871fcf72dd9e1d560e7cc09c409eedef2a27" +checksum = "8ee97a4472a73b2f6adc911468b16405fa5b732f510e5ae11a33a914f36fe5ad" dependencies = [ "memchr", "raw-string", @@ -3182,12 +3512,12 @@ dependencies = [ [[package]] name = "spirv-std" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3197bd4c021c2dfc0f9dfb356312c8f7842d972d5545c308ad86422c2e2d3e66" +checksum = "68c3c0972a2df79abe2c8af2fe7f7937a9aa558b6a1f78fc5edf93f4d480d757" dependencies = [ - "bitflags", - "glam 0.22.0", + "bitflags 1.3.2", + "glam", "num-traits", "spirv-std-macros", "spirv-std-types", @@ -3195,9 +3525,9 @@ dependencies = [ [[package]] name = "spirv-std-macros" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaffad626ab9d3ac61c4b74b5d51cb52f1939a8041d7ac09ec828eb4ad44d72" +checksum = "73f776bf9f2897ea7acff15d7753711fdf1693592bd7459a01c394262b1df45c" dependencies = [ "proc-macro2", "quote", @@ -3207,9 +3537,9 @@ dependencies = [ [[package]] name = "spirv-std-types" -version = "0.7.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab83875e851bc803c687024d2d950730f350c0073714b95b3a6b1d22e9eac42a" +checksum = "a73417b7d72d95b4995c840dceb4e3b4bcbad4ff7f35df9c1655b6826c18d3a9" [[package]] name = "spirv-tools" @@ -3266,9 +3596,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -3277,12 +3607,12 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.28.4" +version = "0.29.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c2f3ca6693feb29a89724516f016488e9aafc7f37264f898593ee4b942f31b" +checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5" dependencies = [ "cfg-if", - "core-foundation-sys 0.8.4", + "core-foundation-sys", "libc", "ntapi", "once_cell", @@ -3291,42 +3621,63 @@ dependencies = [ [[package]] name = "taffy" -version = "0.3.12" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3540ec65df399929a04a485feb50144475735920cc47eaf8eba09c70b1df4055" +checksum = "3c2287b6d7f721ada4cddf61ade5e760b2c6207df041cac9bfaa192897362fd3" dependencies = [ "arrayvec", + "grid", "num-traits", "slotmap", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] +[[package]] +name = "thiserror-core" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497" +dependencies = [ + "thiserror-core-impl", +] + +[[package]] +name = "thiserror-core-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.39", ] [[package]] @@ -3339,6 +3690,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiff" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -3356,28 +3718,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.1.0", "toml_datetime", "winnow", ] [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3385,20 +3746,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.39", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -3406,12 +3767,12 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -3446,9 +3807,9 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" [[package]] name = "twox-hash" @@ -3460,42 +3821,17 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "type-fields" -version = "0.1.0" -source = "git+https://github.com/bevy-rust-gpu/type-fields?tag=prerelease#4fbf57e6926c164eade696c65736503765150700" -dependencies = [ - "type-fields-macros", -] - -[[package]] -name = "type-fields-macros" -version = "0.1.0" -source = "git+https://github.com/bevy-rust-gpu/type-fields-macros?tag=prerelease#f5c7fe25636a4525dfc1b415b6bd56b7a40eff51" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "syn 2.0.15", -] - [[package]] name = "unicode-ident" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -3503,12 +3839,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "urlencoding" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" - [[package]] name = "utf8parse" version = "0.2.1" @@ -3517,9 +3847,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "getrandom", "serde", @@ -3545,15 +3875,15 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -3567,9 +3897,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3577,24 +3907,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -3604,9 +3934,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3614,22 +3944,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "wayland-scanner" @@ -3644,19 +3974,25 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + [[package]] name = "wgpu" -version = "0.15.1" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d745a1b6d91d85c33defbb29f0eee0450e1d2614d987e14bf6baf26009d132d7" +checksum = "480c965c9306872eb6255fa55e4b4953be55a8b64d57e61d7ff840d3dcc051cd" dependencies = [ "arrayvec", "cfg-if", @@ -3678,20 +4014,20 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.15.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7131408d940e335792645a98f03639573b0480e9e2e7cddbbab74f7c6d9f3fff" +checksum = "8f478237b4bf0d5b70a39898a66fa67ca3a007d79f2520485b8b0c3dfc46f8c2" dependencies = [ "arrayvec", "bit-vec", - "bitflags", + "bitflags 2.4.1", "codespan-reporting", - "fxhash", "log", "naga", "parking_lot", "profiling", "raw-window-handle", + "rustc-hash", "smallvec", "thiserror", "web-sys", @@ -3701,20 +4037,19 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "0.15.4" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdcf61a283adc744bb5453dd88ea91f3f86d5ca6b027661c6c73c7734ae0288b" +checksum = "1ecb3258078e936deee14fd4e0febe1cfe9bbb5ffef165cb60218d2ee5eb4448" dependencies = [ "android_system_properties", "arrayvec", "ash", "bit-set", - "bitflags", + "bitflags 2.4.1", "block", "core-graphics-types", "d3d12", "foreign-types", - "fxhash", "glow", "gpu-alloc", "gpu-allocator", @@ -3723,7 +4058,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading", + "libloading 0.8.1", "log", "metal", "naga", @@ -3733,6 +4068,7 @@ dependencies = [ "range-alloc", "raw-window-handle", "renderdoc-sys", + "rustc-hash", "smallvec", "thiserror", "wasm-bindgen", @@ -3743,20 +4079,20 @@ dependencies = [ [[package]] name = "wgpu-types" -version = "0.15.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32444e121b0bd00cb02c0de32fde457a9491bd44e03e7a5db6df9b1da2f6f110" +checksum = "d0c153280bb108c2979eb5c7391cb18c56642dd3c072e55f52065e13e2a1252a" dependencies = [ - "bitflags", + "bitflags 2.4.1", "js-sys", "web-sys", ] [[package]] name = "widestring" -version = "0.5.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "winapi" @@ -3776,9 +4112,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -3795,8 +4131,6 @@ version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" dependencies = [ - "windows-implement", - "windows-interface", "windows-targets 0.42.2", ] @@ -3815,25 +4149,35 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", + "windows-implement", + "windows-interface", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets 0.48.5", ] [[package]] -name = "windows-implement" -version = "0.44.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce87ca8e3417b02dc2a8a22769306658670ec92d78f1bd420d6310a67c245c6" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "windows-targets 0.48.5", ] [[package]] -name = "windows-interface" -version = "0.44.0" +name = "windows-implement" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "853f69a591ecd4f810d29f17e902d40e349fb05b0b11fff63b08b826bfe39c7f" +checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c" dependencies = [ "proc-macro2", "quote", @@ -3841,18 +4185,14 @@ dependencies = [ ] [[package]] -name = "windows-sys" -version = "0.42.0" +name = "windows-interface" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -3870,7 +4210,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.5", ] [[package]] @@ -3890,17 +4230,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -3911,9 +4251,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -3923,9 +4263,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -3935,9 +4275,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -3947,9 +4287,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -3959,9 +4299,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -3971,9 +4311,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -3983,18 +4323,18 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winit" -version = "0.28.3" +version = "0.28.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f504e8c117b9015f618774f8d58cd4781f5a479bc41079c064f974cbb253874" +checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94" dependencies = [ "android-activity", - "bitflags", + "bitflags 1.3.2", "cfg_aliases", "core-foundation", "core-graphics", @@ -4019,9 +4359,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.4.4" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5617da7e1f97bf363947d767b91aaf3c2bbc19db7fda9c65af1278713d58e0a2" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -4045,6 +4385,35 @@ checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" [[package]] name = "xml-rs" -version = "0.8.4" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" + +[[package]] +name = "zerocopy" +version = "0.7.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd369a67c0edfef15010f980c3cbe45d7f651deac2cd67ce097cd801de16557" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f140bda219a26ccc0cdb03dba58af72590c53b22642577d88a927bc5c87d6b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] diff --git a/rust-gpu/README.md b/rust-gpu/README.md index bed5544..d019ad5 100644 --- a/rust-gpu/README.md +++ b/rust-gpu/README.md @@ -1,5 +1,9 @@ ## `rust-gpu` Workspace +``` + +``` + Nightly rust workspace housing `rust-gpu` shader crates. `rust-toolchain` contains the necessary toolchain specification for `rust-gpu`, diff --git a/rust-gpu/crates/rust-gpu-builder b/rust-gpu/crates/rust-gpu-builder deleted file mode 160000 index 5f87368..0000000 --- a/rust-gpu/crates/rust-gpu-builder +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5f873689bc992278c123d8643add4c4e64c4f4ef diff --git a/rust-gpu/crates/rust-gpu-builder/.github/workflows/create-tag-release.yml b/rust-gpu/crates/rust-gpu-builder/.github/workflows/create-tag-release.yml new file mode 100644 index 0000000..623532c --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/.github/workflows/create-tag-release.yml @@ -0,0 +1,44 @@ +name: Release on Tag + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + +jobs: + release: + runs-on: ubuntu-latest + + permissions: + contents: write + pull-requests: read + + name: Generate Release + steps: + - name: checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Get previous tag + id: previousTag + run: | + name=$(git --no-pager tag --sort=creatordate --merged ${{ github.ref_name }} | tail -2 | head -1) + echo "previousTag: $name" + echo "previousTag=$name" >> $GITHUB_ENV + + - name: Generate changelog + id: changelog + uses: metcalfc/changelog-generator@v4.1.0 + with: + myToken: ${{ secrets.GITHUB_TOKEN }} + head-ref: ${{ env.previousTag }} + base-ref: ${{ github.ref_name }} + + - name: Create Release + uses: ncipollo/release-action@v1.12.0 + with: + draft: true + token: ${{ github.token }} + name: "Release ${{ github.ref_name }}" + body: "## Release Notes\n\nTODO\n\n## Commits\n\n${{ steps.changelog.outputs.changelog }}" diff --git a/rust-gpu/crates/rust-gpu-builder/.github/workflows/publish-rust-docs.yml b/rust-gpu/crates/rust-gpu-builder/.github/workflows/publish-rust-docs.yml new file mode 100644 index 0000000..df0d494 --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/.github/workflows/publish-rust-docs.yml @@ -0,0 +1,11 @@ +name: Publish Rust Docs +run-name: ${{ github.actor }} is publishing documentation 🚀 +on: + push: + +permissions: + contents: write + +jobs: + publish-cargo-doc: + uses: Shfty/github-actions/.github/workflows/publish-rust-docs.yml@master diff --git a/rust-gpu/crates/rust-gpu-builder/.github/workflows/rust.yml b/rust-gpu/crates/rust-gpu-builder/.github/workflows/rust.yml new file mode 100644 index 0000000..d54fa2f --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/.github/workflows/rust.yml @@ -0,0 +1,22 @@ +name: Rust + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/rust-gpu/crates/rust-gpu-builder/.gitignore b/rust-gpu/crates/rust-gpu-builder/.gitignore new file mode 100644 index 0000000..1e7caa9 --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target/ diff --git a/rust-gpu/crates/rust-gpu-builder/Cargo.toml b/rust-gpu/crates/rust-gpu-builder/Cargo.toml new file mode 100644 index 0000000..92484b7 --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "rust-gpu-builder" +version = "0.5.0" +edition = "2021" + +[dependencies] +rust-gpu-builder-shared = { path = "../../../bevy-app/crates/bevy_rust_gpu/lib/rust-gpu-builder-shared" } + +spirv-builder = "0.9.0" +notify = "5.1.0" +serde_json = "1.0.94" +rmp-serde = "1.1.1" + +futures-lite = "1.12.0" +async-executor = "1.5.0" +async-channel = "1.8.0" +async-fs = "1.6.0" +easy-parallel = "3.2.0" + +tracing = "0.1.37" +tracing-subscriber = "0.3.16" +clap = { version = "4.1.6", features = ["derive"] } \ No newline at end of file diff --git a/rust-gpu/crates/rust-gpu-builder/LICENSE-APACHE b/rust-gpu/crates/rust-gpu-builder/LICENSE-APACHE new file mode 100644 index 0000000..d9a10c0 --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/rust-gpu/crates/rust-gpu-builder/LICENSE-MIT b/rust-gpu/crates/rust-gpu-builder/LICENSE-MIT new file mode 100644 index 0000000..9cf1062 --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/LICENSE-MIT @@ -0,0 +1,19 @@ +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. diff --git a/rust-gpu/crates/rust-gpu-builder/README.md b/rust-gpu/crates/rust-gpu-builder/README.md new file mode 100644 index 0000000..24ccb1f --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/README.md @@ -0,0 +1,26 @@ +
+ +# `rust-gpu-builder` + +[![Documentation](https://img.shields.io/badge/docs-API-blue)](https://bevy-rust-gpu.github.io/rust-gpu-builder/) + +`rust-gpu` helper program for automating shader crate compilation. + +Can compile once, or run in daemon mode and recompile in response to filesystem changes. + +
+ +## Usage + +`rust-gpu-builder` relies on the [`spirv-builder`](https://embarkstudios.github.io/rust-gpu/api/spirv_builder/) crate, which in turn relies on the cargo ecosystem +to configure the appropriate nightly toolchain for `rust-gpu`. As such, it needs to be run from inside a workspace via `cargo run`. + +Thus, it's recommended to add `rust-gpu-builder` as a a git submodule of your cargo workspace, and set it up as the default binary target. + +### One-shot compilation + +`cargo run --release -- ` will compile the provided shader crate and output `.spv` and `.spv.json` to `target/spirv-unknown-spv1.5/release/deps/`. + +### Hot-recompile + +`cargo run --release -- -w ` will compile as per the above, then watch the provided path and recompile whenever it changes. diff --git a/rust-gpu/crates/rust-gpu-builder/build.rs b/rust-gpu/crates/rust-gpu-builder/build.rs new file mode 100644 index 0000000..fc2b7fb --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/build.rs @@ -0,0 +1,12 @@ +use std::{env, error::Error}; + +fn main() -> Result<(), Box> { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS"); + println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_ARCH"); + // While OUT_DIR is set for both build.rs and compiling the crate, PROFILE is only set in + // build.rs. So, export it to crate compilation as well. + let profile = env::var("PROFILE").unwrap(); + println!("cargo:rustc-env=PROFILE={profile}"); + Ok(()) +} diff --git a/rust-gpu/crates/rust-gpu-builder/rust-toolchain.toml b/rust-gpu/crates/rust-gpu-builder/rust-toolchain.toml new file mode 100644 index 0000000..89b72f0 --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/rust-toolchain.toml @@ -0,0 +1,7 @@ +[toolchain] +channel = "nightly-2023-05-27" +components = ["rust-src", "rustc-dev", "llvm-tools-preview"] +# commit_hash = 44cfafe2fafe816395d3acc434663a45d5178c41 + +# Whenever changing the nightly channel, update the commit hash above, and make +# sure to change REQUIRED_TOOLCHAIN in crates/rustc_codegen_spirv/src/build.rs also. diff --git a/rust-gpu/crates/rust-gpu-builder/src/main.rs b/rust-gpu/crates/rust-gpu-builder/src/main.rs new file mode 100644 index 0000000..a9aa606 --- /dev/null +++ b/rust-gpu/crates/rust-gpu-builder/src/main.rs @@ -0,0 +1,390 @@ +use std::{ + // collections::BTreeMap, + error::Error, + path::{Path, PathBuf}, + str::FromStr, +}; + +use rust_gpu_builder_shared::{RustGpuBuilderModules, RustGpuBuilderOutput}; + +use clap::{error::ErrorKind, Parser}; + +use async_channel::{unbounded, Receiver, Sender}; +use async_executor::Executor; +use easy_parallel::Parallel; +use futures_lite::future; + +use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher}; + +use spirv_builder::{ + Capability, CompileResult, MetadataPrintout, SpirvBuilder, SpirvBuilderError, SpirvMetadata, +}; + +use tracing::{error, info}; + +#[derive(Debug, Copy, Clone)] +pub enum OutputFormat { + Json, + Messagepack, +} + +impl FromStr for OutputFormat { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "Json" => Ok(Self::Json), + "Messagepack" => Ok(Self::Messagepack), + _ => Err("Unrecognized output mode"), + } + } +} + +/// Clap application struct. +#[derive(Debug, Clone, Parser)] +#[command(author, version, about, long_about = None)] +struct ShaderBuilder { + /// Shader crate to compile. + path_to_crate: PathBuf, + /// If set, combined SPIR-V and entrypoint metadata will be written to this file on succesful compile. + output_path: Option, + /// The format to write output in. + #[arg(long, default_value = "Messagepack")] + output_format: OutputFormat, + /// rust-gpu compile target. + #[arg(short, long, default_value = "spirv-unknown-vulkan1.2")] + target: String, + /// Treat warnings as errors during compilation. + #[arg(long, default_value = "false")] + deny_warnings: bool, + /// Compile shaders in release mode. + #[arg(long, default_value = "true")] + release: bool, + /// Enables the provided SPIR-V capability. + #[arg(long, value_parser=Self::spirv_capability)] + capability: Vec, + /// Compile one .spv file per entry point. + #[arg(long, default_value = "false")] + multimodule: bool, + /// Set the level of metadata included in the SPIR-V binary. + #[arg(long, value_parser=Self::spirv_metadata, default_value = "none")] + spirv_metadata: SpirvMetadata, + /// Allow store from one struct type to a different type with compatible layout and members. + #[arg(long, default_value = "false")] + relax_struct_store: bool, + /// Allow allocating an object of a pointer type and returning a pointer value from a function + /// in logical addressing mode. + #[arg(long, default_value = "false")] + relax_logical_pointer: bool, + /// Enable VK_KHR_relaxed_block_layout when checking standard uniform, + /// storage buffer, and push constant layouts. + /// This is the default when targeting Vulkan 1.1 or later. + #[arg(long, default_value = "false")] + relax_block_layout: bool, + /// Enable VK_KHR_uniform_buffer_standard_layout when checking standard uniform buffer layouts. + #[arg(long, default_value = "false")] + uniform_buffer_standard_layout: bool, + /// Enable VK_EXT_scalar_block_layout when checking standard uniform, storage buffer, and push + /// constant layouts. + /// Scalar layout rules are more permissive than relaxed block layout so in effect this will + /// override the --relax-block-layout option. + #[arg(long, default_value = "false")] + scalar_block_layout: bool, + /// Skip checking standard uniform / storage buffer layout. Overrides any --relax-block-layout + /// or --scalar-block-layout option. + #[arg(long, default_value = "false")] + skip_block_layout: bool, + /// Preserve unused descriptor bindings. Useful for reflection. + #[arg(long, default_value = "false")] + preserve_bindings: bool, + /// If set, will watch the provided directory and recompile on change. + /// + /// Can be specified multiple times to watch more than one directory. + #[arg(short, long)] + watch_paths: Option>, +} + +impl ShaderBuilder { + /// Clap value parser for `SpirvMetadata`. + fn spirv_metadata(s: &str) -> Result { + match s { + "none" => Ok(SpirvMetadata::None), + "name-variables" => Ok(SpirvMetadata::NameVariables), + "full" => Ok(SpirvMetadata::Full), + _ => Err(clap::Error::new(ErrorKind::InvalidValue)), + } + } + + /// Clap value parser for `Capability`. + fn spirv_capability(s: &str) -> Result { + match Capability::from_str(s) { + Ok(capability) => Ok(capability), + Err(_) => Err(clap::Error::new(ErrorKind::InvalidValue)), + } + } + + /// Builds a shader with the provided set of options. + pub fn build_shader(&self) -> Result { + // As per `spirv-builder`, apply env vars set in build.rs + // to work around potentially suboptimal cargo behaviour + std::env::set_var("OUT_DIR", env!("OUT_DIR")); + std::env::set_var("PROFILE", env!("PROFILE")); + + let mut builder = SpirvBuilder::new(&self.path_to_crate, &self.target) + .deny_warnings(self.deny_warnings) + .release(self.release) + .multimodule(self.multimodule) + .spirv_metadata(self.spirv_metadata) + .relax_struct_store(self.relax_struct_store) + .relax_logical_pointer(self.relax_logical_pointer) + .relax_block_layout(self.relax_block_layout) + .uniform_buffer_standard_layout(self.uniform_buffer_standard_layout) + .scalar_block_layout(self.scalar_block_layout) + .skip_block_layout(self.skip_block_layout) + .preserve_bindings(self.preserve_bindings) + .print_metadata(MetadataPrintout::None); + + for capability in &self.capability { + builder = builder.capability(*capability); + } + + builder.build() + } +} + +enum Msg { + Change, + Build(Result), +} + +/// Instantiate an async watcher and return it alongside a channel to receive events on. +fn async_watcher() -> notify::Result<(RecommendedWatcher, Receiver>)> { + let (tx, rx) = unbounded(); + + // Automatically select the best implementation for your platform. + // You can also access each implementation directly e.g. INotifyWatcher. + let watcher = RecommendedWatcher::new( + move |res| { + future::block_on(async { + tx.send(res).await.unwrap(); + }) + }, + Default::default(), + )?; + + Ok((watcher, rx)) +} + +/// Watch a file or directory, sending relevant events through the provided channel. +async fn async_watch>( + path: P, + change_tx: Sender, +) -> Result<(), Box> { + let path = path.as_ref(); + let path = std::fs::canonicalize(path) + .unwrap_or_else(|e| panic!("Failed to canonicalize path {path:?}: {e:}")); + + let (mut watcher, rx) = async_watcher()?; + + // Add a path to be watched. All files and directories at that path and + // below will be monitored for changes. + let watch_path = if path.is_dir() { + path.clone() + } else { + path.parent().unwrap().to_owned() + }; + watcher.watch(watch_path.as_ref(), RecursiveMode::Recursive)?; + + while let Ok(res) = rx.recv().await { + match res { + Ok(event) => { + if path.is_dir() + || event + .paths + .iter() + .find(|candidate| **candidate == path) + .is_some() + { + change_tx.send(Msg::Change).await.unwrap(); + } + } + Err(e) => error!("Watch error: {:?}", e), + } + } + + Ok(()) +} + +async fn handle_compile_result( + result: CompileResult, + output_path: Option, + output_format: OutputFormat, +) { + info!("Entry Points:"); + for entry in &result.entry_points { + println!("{entry:}"); + } + + let entry_points = result.entry_points; + + println!(); + + info!("Modules:"); + match &result.module { + spirv_builder::ModuleResult::SingleModule(single) => { + println!("{single:?}"); + } + + spirv_builder::ModuleResult::MultiModule(multi) => { + for (k, module) in multi { + println!("{k:}: {module:?}"); + } + } + }; + + let Some(output_path) = output_path else { + return + }; + + let modules = match result.module { + spirv_builder::ModuleResult::SingleModule(single) => { + let module = async_fs::read(single) + .await + .expect("Failed to read module file"); + RustGpuBuilderModules::Single(module) + } + + spirv_builder::ModuleResult::MultiModule(multi) => { + let mut out = std::collections::HashMap::default(); + for (k, module) in multi { + let module = async_fs::read(module) + .await + .expect("Failed to read module file"); + out.insert(k, module); + } + RustGpuBuilderModules::Multi(out) + } + }; + + let out = RustGpuBuilderOutput { + entry_points, + modules, + }; + + let output_dir = output_path.parent().expect("Output path must be a valid directory"); + async_fs::create_dir_all(&output_dir).await.ok(); + + match output_format { + OutputFormat::Json => { + let out = serde_json::to_string_pretty(&out).expect("Failed to serialize output"); + + async_fs::write(&output_path, out) + .await + .expect("Failed to write output"); + } + OutputFormat::Messagepack => { + let out = rmp_serde::to_vec_named(&out).expect("Failed to serialize output"); + async_fs::write(&output_path, out) + .await + .expect("Failed to write output"); + } + } + println!(); + info!("Wrote output to {output_path:?}"); +} + +fn main() { + tracing_subscriber::fmt().init(); + + let mut args = ShaderBuilder::parse(); + + println!(); + info!("Shader Builder"); + println!(); + + info!("Building shader..."); + println!(); + match args.build_shader() { + Ok(result) => { + future::block_on(handle_compile_result( + result, + args.output_path.clone(), + args.output_format, + )); + } + Err(e) => { + error!("Build failed!\n{e:}"); + } + } + println!(); + + let Some(watch_paths) = args.watch_paths.take() else { + return + }; + + let ex = Executor::new(); + let (change_tx, change_rx) = unbounded::(); + let (build_tx, build_rx) = unbounded::(); + + Parallel::new() + // Spawn file watchers + .each(watch_paths, |path| { + info!("Watching {path:} for changes..."); + future::block_on(async { + async_watch(path, change_tx) + .await + .expect("Async watcher error"); + }); + }) + // Spawn message Bus + .add(|| { + let mut building = false; + loop { + match future::block_on(futures_lite::future::race( + change_rx.recv(), + build_rx.recv(), + )) { + // On file change, spawn a build task + Ok(Msg::Change) => { + if !building { + building = true; + println!(); + info!("Building shader..."); + println!(); + ex.spawn({ + let build_tx = build_tx.clone(); + let args = args.clone(); + async move { + build_tx + .send(Msg::Build(args.build_shader())) + .await + .unwrap(); + } + }) + .detach(); + } + } + // On build complete, spawn a handle_compile_result task + Ok(Msg::Build(result)) => { + if let Ok(result) = result { + let output_path = args.output_path.clone(); + let output_format = args.output_format; + ex.spawn(handle_compile_result(result, output_path, output_format)) + .detach(); + } else { + error!("Build failed!"); + } + println!(); + building = false; + } + Err(e) => { + panic!("{e:}") + } + } + } + }) + // Run executor on main thread + .finish(|| loop { + future::block_on(ex.tick()) + }); +} diff --git a/rust-gpu/crates/shader/Cargo.toml b/rust-gpu/crates/shader/Cargo.toml index 2b7fb24..eddc412 100644 --- a/rust-gpu/crates/shader/Cargo.toml +++ b/rust-gpu/crates/shader/Cargo.toml @@ -7,9 +7,12 @@ edition = "2021" crate-type = ["dylib"] [dependencies] -spirv-std = "0.7.0" +spirv-std = "0.9.0" +# noise = {version= "0.8.2", default_features = false, features=[]} +# noise = {path= "./lib/noise-rs", default_features = false, features=[]} +noise_perlin = {path="lib/perlin-rs-main"} -bevy-pbr-rust = { git = "https://github.com/bevy-rust-gpu/bevy-pbr-rust", tag = "v0.4.0" } -rust-gpu-sdf = { git = "https://github.com/bevy-rust-gpu/rust-gpu-sdf", features = ["spirv-std"], tag = "prerelease" } -rust-gpu-bridge = { git = "https://github.com/bevy-rust-gpu/rust-gpu-bridge", features = ["spirv-std"], tag = "v0.5.0" } -permutate-macro = { git = "https://github.com/bevy-rust-gpu/permutate-macro", tag = "v0.5.0" } +# bevy-pbr-rust = { git = "https://github.com/bevy-rust-gpu/bevy-pbr-rust", tag = "v0.4.0" } +# rust-gpu-sdf = { git = "https://github.com/bevy-rust-gpu/rust-gpu-sdf", features = ["spirv-std"], tag = "prerelease" } +# rust-gpu-bridge = { git = "https://github.com/bevy-rust-gpu/rust-gpu-bridge", features = ["spirv-std"], tag = "v0.5.0" } +# permutate-macro = { git = "https://github.com/bevy-rust-gpu/permutate-macro", tag = "v0.5.0" } diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/.gitignore b/rust-gpu/crates/shader/lib/perlin-rs-main/.gitignore new file mode 100644 index 0000000..642c714 --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/.gitignore @@ -0,0 +1,3 @@ +target +*.png +Cargo.lock diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/Cargo.toml b/rust-gpu/crates/shader/lib/perlin-rs-main/Cargo.toml new file mode 100644 index 0000000..8dd4ce1 --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "noise_perlin" +description = "Improved perlin noise in 2D and 3D" +version = "1.0.0" +license = "MIT" +edition = "2021" +homepage = "https://github.com/jorgecarleitao/perlin-rs" +repository = "https://github.com/jorgecarleitao/perlin-rs" + +[dev-dependencies] +image = "0.24" diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/LICENSE b/rust-gpu/crates/shader/lib/perlin-rs-main/LICENSE new file mode 100644 index 0000000..bee1aca --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/LICENSE @@ -0,0 +1,7 @@ +Copyright 2023 Jorge C. Leitao + +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. diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/README.md b/rust-gpu/crates/shader/lib/perlin-rs-main/README.md new file mode 100644 index 0000000..417ccf6 --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/README.md @@ -0,0 +1,5 @@ +# Perlin noise in Rust + +This is a fast implementation of Perlin noise in Rust. + +It has no dependencies, is `#![no_std]` and `#[forbid(unsafe_code)]`. diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/examples/noise.rs b/rust-gpu/crates/shader/lib/perlin-rs-main/examples/noise.rs new file mode 100644 index 0000000..8b6db61 --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/examples/noise.rs @@ -0,0 +1,34 @@ +use std::path::Path; + +use noise_perlin::perlin_2d; + +fn main() { + let width = 256; + let height = width; + + let mut bytes = vec![0u8; height * width]; + + let scale = 2.0; + let offset = 0.0; + + let constant = 2.0f32.sqrt() / 2.0; + (bytes.iter_mut().enumerate()).for_each(|(i, pixel)| { + let x = (i / width) as f32; + let x = x / width as f32; + let y = (i % height) as f32; + let y = y / height as f32; + + let mut v = perlin_2d(x * scale + offset, y * scale + offset); + v = v * constant + 0.5; + *pixel = (v * 255.0) as u8; + }); + + image::save_buffer( + &Path::new("image.png"), + &bytes, + width as u32, + height as u32, + image::ColorType::L8, + ) + .unwrap(); +} diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/examples/pink_noise.rs b/rust-gpu/crates/shader/lib/perlin-rs-main/examples/pink_noise.rs new file mode 100644 index 0000000..fb947f0 --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/examples/pink_noise.rs @@ -0,0 +1,57 @@ +use std::path::Path; + +use noise_perlin::perlin_2d; + +static SQRT_2_OVER_2: f32 = 0.70710678118; + +fn apply_noise( + width: usize, + height: usize, + frequency: f32, + amplitude: f32, + offset: f32, + values: &mut Vec, +) { + (values.iter_mut().enumerate()).for_each(|(i, entry)| { + let x = (i / width) as f32; + let x = x / width as f32; + let y = (i % height) as f32; + let y = y / height as f32; + + let mut v = perlin_2d(x * frequency + offset, y * frequency + offset); + v = v * SQRT_2_OVER_2 + 0.5; + *entry += v * amplitude; + }); +} + +fn main() { + let width = 512; + let height = width; + + // alpha of the pink noise, the scaling of amplitude with frequency + let alpha: f32 = 1.0; + + let mut values = vec![0.0f32; height * width]; + + for scale in 0..8u32 { + let frequency = 2.0f32.powf(scale as f32); + let amplitude = 1.0 / frequency.powf(alpha); + apply_noise(width, height, frequency, amplitude, 0.0, &mut values) + } + + let max = values.iter().cloned().fold(0. / 0., f32::max); + let min = values.iter().cloned().fold(0. / 0., f32::min); + let bytes = values + .into_iter() + .map(|x| ((x - min) / (max - min) * 255.0) as u8) + .collect::>(); + + image::save_buffer( + &Path::new("pink.png"), + &bytes, + width as u32, + height as u32, + image::ColorType::L8, + ) + .unwrap(); +} diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/src/lib.rs b/rust-gpu/crates/shader/lib/perlin-rs-main/src/lib.rs new file mode 100644 index 0000000..487a199 --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/src/lib.rs @@ -0,0 +1,49 @@ +//! Perlin noise in 2D and 3D. Translated from the reference Java implementation at +//! https://mrl.cs.nyu.edu/~perlin/noise/ and https://mrl.cs.nyu.edu/~perlin/paper445.pdf +#![no_std] +#[forbid(unsafe_code)] +mod perlin_2d; +mod perlin_3d; +pub use perlin_2d::perlin_2d; +pub use perlin_3d::perlin_3d; + +#[inline] +fn fade(t: f32) -> f32 { + debug_assert!(t <= 1.0); + t * t * t * (t * (t * 6.0 - 15.0) + 10.0) +} + +#[inline] +fn lerp(t: f32, a: f32, b: f32) -> f32 { + a + t * (b - a) +} + +// see https://mrl.cs.nyu.edu/~perlin/noise/ +const PERM: [usize; 512] = [ + 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, + 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, + 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, + 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, + 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, + 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, + 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, + 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, + 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, + 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, + 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, + 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, + 128, 195, 78, 66, 215, 61, 156, 180, // copy of the first part + 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, + 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, + 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, + 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, + 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, + 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, + 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, + 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, + 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, + 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, + 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, + 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, + 128, 195, 78, 66, 215, 61, 156, 180, +]; diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/src/perlin_2d.rs b/rust-gpu/crates/shader/lib/perlin-rs-main/src/perlin_2d.rs new file mode 100644 index 0000000..241605b --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/src/perlin_2d.rs @@ -0,0 +1,95 @@ +use super::*; + +#[inline] +fn grad_2d(hash: usize, x: f32, y: f32) -> f32 { + // in 2D, we only select from 4 different gradients. + // http://riven8192.blogspot.com/2010/08/calculate-perlinnoise-twice-as-fast.html + match hash % 4 { + 0 => x + y, // (1, 1) + 1 => -x + y, // (-1, 1) + 2 => x - y, // (1, -1) + 3 => -x - y, // (-1, -1) + _ => 0.0, // unreachable + } +} + +#[inline] +fn perlin_2d_grad(x: f32, y: f32, g00: usize, g10: usize, g01: usize, g11: usize) -> f32 { + // compute the gradients + // note: each corner has its own independent direction (derived from the permutation table) + // g00 represents the dot product of (x,y) with one of the directions assigned to the corner `(0,0)` (e.g. `(1,1)`) + let g00 = grad_2d(g00, x, y); // (x,y) - (0,0) + let g10 = grad_2d(g10, x - 1.0, y); // (x,y) - (1,0) + + let g01 = grad_2d(g01, x, y - 1.0); // (x,y) - (0,1) + let g11 = grad_2d(g11, x - 1.0, y - 1.0); // (x,y) - (1,1) + + // smoothed x (continuous second derivative) + let u = fade(x); + // smoothed y (continuous second derivative) + let v = fade(y); + + // g00 + f(x) * (g10 - g00) + f(y) * (g01 + f(x) * (g11 - g01) - (g00 + f(x) * (g10 - g00))) + lerp(v, lerp(u, g00, g10), lerp(u, g01, g11)) + // in particular + // x = 0 and y = 0 => g00 => 0 + // x = 1 and y = 0 => g10 => 0 + // x = 0 and y = 1 => g01 => 0 + // x = 1 and y = 1 => g11 => 0 + // i.e. noise at each corner equals to zero + // x = 0.5 and y = 0.5 => (g00+g10+g01+g11)/4 + // i.e. noise at the center equals to the average of the gradients +} + +/// Returns the evaluation of perlin noise at position (x, y) +/// This function does not allocate +/// It uses the improved implementation of perlin noise +/// whose reference implementation is available here: https://mrl.cs.nyu.edu/~perlin/noise/ +/// The modifications are: +/// * made it 2d, ignoring the z coordinate +/// * the grad computation was modified +pub fn perlin_2d(mut x: f32, mut y: f32) -> f32 { + let x0 = x as usize; + let y0 = y as usize; + + x -= x0 as f32; + y -= y0 as f32; + // at this point (x, y) is bounded to [0, 1] + debug_assert!((x >= 0.0) && (x <= 1.0) && (y >= 0.0) && (y <= 1.0)); + + let gx = x0 % 256; + let gy = y0 % 256; + + // derive a permutation from the indices. + // This behaves like a weak hash + // note that the +1's must be consistent with the relative position in the box + let a00 = gy + PERM[gx]; + let a10 = gy + PERM[gx + 1]; + + let g00 = PERM[a00]; + let g10 = PERM[a10]; + let g01 = PERM[1 + a00]; + let g11 = PERM[1 + a10]; + + perlin_2d_grad(x, y, g00, g10, g01, g11) +} + +#[cfg(test)] +mod tests { + #[test] + fn perlin() { + let result = super::perlin_2d(1.5, 1.5); + assert_eq!(result, 0.0); + } + + /// the middle point with all gradients point to (1,1) result in: + /// (g00+g10+g01+g11)/4 + /// = ((x + y) + (x-1 + y) + (x + y-1) + (x-1 + y-1))/4 + /// = (4x + 4y-4)/4 + /// = x + y - 1 = 0.5 + 0.5 - 1 = 0 + #[test] + fn grad() { + let result = super::perlin_2d_grad(0.5, 0.5, 0, 0, 0, 0); + assert_eq!(result, 0.0); + } +} diff --git a/rust-gpu/crates/shader/lib/perlin-rs-main/src/perlin_3d.rs b/rust-gpu/crates/shader/lib/perlin-rs-main/src/perlin_3d.rs new file mode 100644 index 0000000..1eb4c95 --- /dev/null +++ b/rust-gpu/crates/shader/lib/perlin-rs-main/src/perlin_3d.rs @@ -0,0 +1,138 @@ +use super::*; + +#[inline] +fn grad_3d(hash: usize, x: f32, y: f32, z: f32) -> f32 { + // based on + // http://riven8192.blogspot.com/2010/08/calculate-perlinnoise-twice-as-fast.html + // although note that the implementation in the link has a bug - the directions + // in section 3 of [SIGGRAPH 2002 paper](https://mrl.cs.nyu.edu/~perlin/paper445.pdf) + // only have 1,0,-1, whereas the link has a grad "x + x", which would correspond to (2,0,0) + // in the paper. + match hash % 16 { + // z = 0 + 0 => x + y, // (1,1,0) + 1 => -x + y, // (-1,1,0) + 2 => x - y, // (1,-1,0) + 3 => -x - y, // (-1,-1,0) + // y = 0 + 4 => x + z, // (1,0,1) + 5 => -x + z, // (-1,0,1) + 6 => x - z, // (1,0,-1) + 7 => -x - z, // (-1,0,-1) + // x = 0 + 8 => y + z, // (0,1,1) + 9 => -y + z, // (0,-1,1) + 10 => y - z, // (0,1,-1) + 11 => -y - z, // (0,-1,-1) + // repeat 4 to be multiple of 16 + 12 => x + y, // (1,1,0) + 13 => -x + y, // (-1,1,0) + 14 => -y + z, // (0,-1,1) + 15 => -y + -z, // (0,-1,-1) + _ => 0.0, // unreachable + } +} + +#[inline] +fn perlin_3d_grad( + x: f32, + y: f32, + z: f32, + h000: usize, + h001: usize, + h010: usize, + h011: usize, + h100: usize, + h101: usize, + h110: usize, + h111: usize, +) -> f32 { + // compute the gradients + // note: each corner has its own independent direction (derived from the permutation table) + // g000 represents the dot product of (x,y,z) with one of the directions assigned to the corner `(0,0,0)` (e.g. `(1,1,0)`) + let g000 = grad_3d(h000, x, y, z); + let g001 = grad_3d(h001, x, y, z - 1.0); + let g010 = grad_3d(h010, x, y - 1.0, z); + let g011 = grad_3d(h011, x, y - 1.0, z - 1.0); + let g100 = grad_3d(h100, x - 1.0, y, z); + let g101 = grad_3d(h101, x - 1.0, y, z - 1.0); + let g110 = grad_3d(h110, x - 1.0, y - 1.0, z); + let g111 = grad_3d(h111, x - 1.0, y - 1.0, z - 1.0); + + // smoothed (continuous second derivative) + let u = fade(x); + let v = fade(y); + let w = fade(z); + + // interpolate y over x + let l1 = lerp(v, lerp(u, g000, g100), lerp(u, g010, g110)); + let l2 = lerp(v, lerp(u, g001, g101), lerp(u, g011, g111)); + + // interpolate z over y + lerp(w, l1, l2) +} + +/// Returns the evaluation of perlin noise at position (x, y, z) +/// This function does not allocate +/// It uses the improved implementation of perlin noise +/// whose reference implementation is available here: https://mrl.cs.nyu.edu/~perlin/noise/ +/// The only modification was the simplification of the function `grad` to avoid some code branches (but does not change the end result). +pub fn perlin_3d(mut x: f32, mut y: f32, mut z: f32) -> f32 { + let x0 = x as usize; + let y0 = y as usize; + let z0 = z as usize; + + x -= x0 as f32; + y -= y0 as f32; + z -= z0 as f32; + // at this point (x, y, z) is bounded to [0, 1] + debug_assert!((x >= 0.0) && (x <= 1.0) && (y >= 0.0) && (y <= 1.0) && (z >= 0.0) && (z <= 1.0)); + + let gx = x0 % 256; + let gy = y0 % 256; + let gz = z0 % 256; + + // derive a permutation from the indices. + // This behaves like a weak hash + // note that the +1's must be consistent with the relative position in the box + let a0 = gy + PERM[gx]; + let b0 = gy + PERM[gx + 1]; + let a000 = gz + PERM[a0]; + let a010 = gz + PERM[a0 + 1]; + let a100 = gz + PERM[b0]; + let a110 = gz + PERM[b0 + 1]; + + // + 1 here means `gz+1` in a varibles => third index of the variable is increased as a result + let h000 = PERM[a000]; + let h001 = PERM[a000 + 1]; + let h010 = PERM[a010]; + let h011 = PERM[a010 + 1]; + let h100 = PERM[a100]; + let h101 = PERM[a100 + 1]; + let h110 = PERM[a110]; + let h111 = PERM[a110 + 1]; + + perlin_3d_grad(x, y, z, h000, h001, h010, h011, h100, h101, h110, h111) +} + +#[cfg(test)] +mod tests { + #[test] + fn perlin() { + let result = super::perlin_3d(1.5, 1.5, 1.5); + assert_eq!(result, -0.875); + } + + /// Given the mid point and all grads the same + /// Then the noise is zero + /// + /// This is because the mid point is always the average over every direction of every corner. + /// When the direction of every corner is the same, the average is zero. + #[test] + fn grad() { + let result = super::perlin_3d_grad(0.5, 0.5, 0.5, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(result, 0.0); + let result = super::perlin_3d_grad(0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1); + assert_eq!(result, 0.0); + } +} diff --git a/rust-gpu/crates/shader/src/lib.rs b/rust-gpu/crates/shader/src/lib.rs index 00b5965..ce03e78 100644 --- a/rust-gpu/crates/shader/src/lib.rs +++ b/rust-gpu/crates/shader/src/lib.rs @@ -1,455 +1,80 @@ #![no_std] #![feature(asm_experimental_arch)] -pub use bevy_pbr_rust; - -use rust_gpu_bridge::glam; - -use bevy_pbr_rust::prelude::{Globals, Mesh, TextureDepth2d, View}; -use permutate_macro::permutate; -use rust_gpu_bridge::{Mix, Mod, SmoothStep}; -use rust_gpu_sdf::{ - default, - prelude::{ - items::position::Position, AttrBoundError, AttrColor, AttrDistance, AttrNormal, - AttrSupport, AttrTangent, AttrUv, BoundError, Capsule, CartesianToPolar, Checker, Circle, - ErrorTerm, Extrude, FieldAttribute, FieldAttributes, FieldAttributesRegisterCons, - FieldAttributesRegistersCons, NormalTetrahedron, PolarToCartesian, ProxyColor, Raycast, - RaycastInput, SmoothSubtraction, Sphere, SphereTraceLipschitz, SupportFunction, Translate, - UvTangent, - }, - type_fields::{ - field::Field as TypeField, - t_funk::{ - hlist::{PushFront, ToTList}, - tlist::ToHList, - Pointed, Tagged, - }, - }, -}; use spirv_std::{ - arch::{ddx, ddy}, - glam::{Mat3, Vec2, Vec3, Vec4, Vec4Swizzles}, spirv, + glam::{UVec3, IVec2, Vec4}, Image, }; -#[allow(unused_imports)] -use spirv_std::num_traits::Float; - -#[spirv(vertex)] -pub fn vertex_warp( - #[spirv(uniform, descriptor_set = 0, binding = 0)] view: &View, - #[spirv(uniform, descriptor_set = 2, binding = 0)] mesh: &Mesh, - #[spirv(uniform, descriptor_set = 0, binding = 9)] globals: &Globals, - - in_position: Vec3, - in_normal: Vec3, - - #[spirv(position)] out_clip_position: &mut Vec4, - out_world_normal: &mut Vec3, -) { - let mut position_local = in_position.extend(1.0); - - position_local.x += position_local.x * position_local.z * globals.time.sin(); - position_local.y += position_local.y * position_local.z * globals.time.cos(); - position_local.z += position_local.z * globals.time.sin() * globals.time.cos(); - - let position_world = mesh.model * position_local; - let position_clip = view.view_proj * position_world; - - *out_clip_position = position_clip; - *out_world_normal = in_normal; +fn hash(value: u32) -> u32 { + let mut state = value; + state = state ^ 2747636419; + state = state * 2654435769; + state = state ^ state >> 16; + state = state * 2654435769; + state = state ^ state >> 16; + state = state * 2654435769; + return state; } -#[spirv(fragment)] -#[allow(unused_variables)] -pub fn fragment_normal( - #[spirv(frag_coord)] in_clip_position: Vec4, - in_world_normal: Vec3, - out_color: &mut Vec4, -) { - *out_color = in_world_normal.extend(1.0); +fn randomFloat(value: u32) -> f32 { + return (hash(value) as f32) / 4294967295.0; } -#[spirv(vertex)] -pub fn vertex_sdf_2d( - in_position: Vec3, +pub type Image_2D_SNORM = Image!(2D, format=rgba8_snorm, sampled=false); - #[spirv(position)] out_position: &mut Vec4, - out_clip_position: &mut Vec4, -) { - let position_local = in_position.extend(1.0); - *out_position = position_local; - *out_clip_position = position_local; +fn is_alive(location: IVec2, offset_x: i32, offset_y: i32, image: &Image_2D_SNORM) -> i32 { + let value= image.read(location + IVec2::new(offset_x, offset_y)); + return value.x as i32; } -pub trait TriangleWave { - fn triangle_wave(self) -> Self; -} - -impl TriangleWave for f32 { - fn triangle_wave(self) -> Self { - 1.0 - 2.0 * ((self / 2.0).round() - (self / 2.0)).abs() - } +fn count_alive(location: IVec2, image: &Image_2D_SNORM) -> i32 { + return is_alive(location, -1, -1, image) + + is_alive(location, -1, 0, image) + + is_alive(location, -1, 1, image) + + is_alive(location, 0, -1, image) + + is_alive(location, 0, 1, image) + + is_alive(location, 1, -1, image) + + is_alive(location, 1, 0, image) + + is_alive(location, 1, 1, image); } -#[spirv(fragment)] -#[allow(unused_variables)] -pub fn fragment_sdf_2d( - #[spirv(uniform, descriptor_set = 0, binding = 0)] view: &View, - #[spirv(uniform, descriptor_set = 0, binding = 1)] globals: &Globals, - in_clip_position: Vec4, - out_color: &mut Vec4, -) { - const COLOR_EXTERIOR: Vec3 = Vec3::new(0.8, 0.31, 0.1); - const COLOR_INTERIOR: Vec3 = Vec3::new(0.4, 0.67, 1.0); - const COLOR_BOUND: Vec3 = Vec3::new(0.0, 0.0, 0.0); - - let mut pos = in_clip_position; - let aspect = view.viewport.z / view.viewport.w; - pos.x *= aspect; - pos *= 4.0; - - //let sdf = Point::default(); - //let sdf = ChebyshevMetric::default(); - //let sdf = TaxicabMetric::default(); - - //let sdf = Circle::default(); - //let sdf = Square::default(); - //let sdf = Triangle::triangle(); - //let sdf = Quadrilateral::quadrilateral(); - //let sdf = Pentagon::pentagon(); - //let sdf = Hexagon::hexagon(); - //let sdf = Septagon::septagon(); - //let sdf = Octagon::octagon(); - //let sdf = Nonagon::nonagon(); - //let sdf = Decagon::decagon(); - //let sdf = Squircle::default(); - - /* - let sdf = Slice::>>::default().with( - (Slice::target, Rotate3d::rotation), - Quat::from_axis_angle( - Vec3::new(0.0, 1.0, 0.0).normalize(), - globals.time.modulo(core::f32::consts::TAU), - ), - ); - */ - - let sdf = Translate::< - Vec2, - PolarToCartesian>>>, - >::default() - .with(Translate::translation, Vec2::ZERO) - .with( - ( - Translate::target, - PolarToCartesian::target, - CartesianToPolar::target, - Translate::translation, - ), - Vec2::Y * 2.0, - ); - - //let sdf = Capsule::default(); - //let sdf = Isosurface::::default(); - //let sdf = Isosurface::::default(); - - /* - let sdf = - Isosurface::::default().with((Isosurface::target, Superellipse::n), 2.45); - */ - - let sdf = NormalTetrahedron::default() - .with(NormalTetrahedron::sdf, sdf) - .with(NormalTetrahedron::epsilon, 0.01); - - let (dist, norm) = - sdf.field_attributes::<(AttrDistance, AttrNormal)>(&pos.xy().into()); - let dist = *dist; - let norm = *norm; - - let norm_remapped = norm * 0.5 + 0.5; - - let col = if dist > 0.0 { - COLOR_EXTERIOR - } else { - COLOR_INTERIOR - }; - - let mut col = norm_remapped.extend(0.0); - - let sdf = BoundError { - target: SupportFunction { - target: sdf, - ..default() - }, - ..default() - }; - - let error_term = sdf.field_attribute::>(&pos.xy().into()); - - // Blue interior - col.z = -dist.signum(); - - // Boundary fade - col *= 1.0 - (-3.0 * dist.abs()).exp(); - - // Annulation - col *= 0.65 + 0.35 * (150.0 * dist).cos(); - - // White boundary - col = col.mix( - Vec3::splat(1.0), - Vec3::splat(1.0 - dist.abs().smooth_step(0.0, 0.01)), - ); - - // Visualize boundedness - col = COLOR_BOUND.mix( - col, - Vec3::splat(1.0 - error_term.error.abs().clamp(0.0, 1.0)), - ); - - *out_color = col.extend(1.0); -} -#[spirv(vertex)] -pub fn vertex_sdf_3d( - #[spirv(uniform, descriptor_set = 0, binding = 0)] view: &View, - #[spirv(uniform, descriptor_set = 2, binding = 0)] mesh: &Mesh, - in_position: Vec3, - - #[spirv(position)] out_position: &mut Vec4, - //out_clip_position: &mut Vec4, - out_world_position: &mut Vec4, +#[spirv(compute(threads(8,8)))] +pub fn init( + #[spirv(global_invocation_id)] id: UVec3, + #[spirv(num_workgroups)] num: UVec3, + #[spirv(descriptor_set = 0, binding = 0)] texture: &Image_2D_SNORM, ) { - let position_local = in_position.extend(1.0); - - let position_world = mesh.model * position_local; - let position_clip = view.view_proj * position_world; - *out_position = position_clip; - //*out_clip_position = position_clip; - *out_world_position = position_world; + let coord = IVec2::new(id.x as i32, id.y as i32); + let randomNumber = randomFloat(id.y * num.x + id.x); + let alive = randomNumber > 0.9; + let alive_f = alive as i32 as f32; + let pixel = Vec4::new(alive_f, alive_f, alive_f, 1.0); + unsafe { + texture.write(coord, pixel); + } } -#[permutate( - parameters = {}, - constants = {}, - types = { - Sdf - }, - permutations = [ - file("../../entry_points.json", ""), - env("RUST_GPU_SDF_FRAGMENT_3D_PERMUTATIONS", "") - ] -)] -#[spirv(fragment)] -pub fn fragment_sdf_3d( - #[spirv(uniform, descriptor_set = 0, binding = 0)] view: &View, - #[spirv(uniform, descriptor_set = 0, binding = 9)] globals: &Globals, - #[spirv(descriptor_set = 0, binding = 16)] depth_prepass_texture: &TextureDepth2d, - #[spirv(uniform, descriptor_set = 2, binding = 0)] mesh: &Mesh, - #[spirv(frag_coord)] in_frag_coord: Vec4, - #[spirv(front_facing)] in_is_front: bool, - //in_clip_position: Vec4, - in_world_position: Vec4, - out_color: &mut Vec4, -) { - const MAX_STEPS: u32 = 400; - - let camera = view.view.col(3); - let ray_delta = in_world_position - camera; - let ray_dist = ray_delta.length(); - let ray_direction = ray_delta.normalize(); - let object = mesh.model.col(3); +#[spirv(compute(threads(8,8)))] +pub fn update( + #[spirv(global_invocation_id)] id: UVec3, + #[spirv(num_workgroups)] num: UVec3, + #[spirv(descriptor_set = 0, binding = 0)] texture: &Image!(2D, format=rgba8_snorm, sampled=false), +){ - let inv_model_rot = Mat3::from_mat4(mesh.model).transpose(); + let coord = IVec2::new(id.x as i32, id.y as i32); + let n_alive = count_alive(coord, texture); + let alive = n_alive == 3 || n_alive == 2 && is_alive(coord, 0, 0, texture) == 1; + let alive_f = alive as i32 as f32; + let pixel = Vec4::new(alive_f, alive_f, alive_f, 1.0); - let mut start = 0.0; - let mut end = 1000.0; + unsafe { spirv_std::arch::workgroup_memory_barrier_with_group_sync() }; - // World depth - let depth = ray_dist; - - // Prepass depth - /* - let mut deproj_pos = view.inverse_projection - * in_clip_position - .xy() - .extend(depth_prepass_texture.read(in_frag_coord.xy().as_ivec2()).x) - .extend(1.0); - deproj_pos.z /= deproj_pos.w; - let depth = deproj_pos.xyz().length(); - */ - - if in_is_front { - start = depth; - } else { - end = depth; + unsafe { + texture.write(coord, pixel); } - /* - let sdf = Torus::default() - .with((Torus::core, Circle::radius), 0.75) - .with((Torus::shell, Circle::radius), 0.25); - */ - - //let sdf = Sphere::default(); - - /* - let sdf = Sweep::::default() - .with((Sweep::core, Circle::radius), 0.75) - .with((Sweep::shell, Square::extent), Vec2::ONE * 0.25); - */ - - //let sdf = Point::default(); - //let sdf = Octahedron::default(); - //let sdf = Cube::default(); - //let sdf = Plane::default(); - //let sdf = Capsule::::default(); - //let sdf = Isosurface::::default(); - /* - let sdf = Union::, Sphere>::default() - .with((Union::sdf_a, Extrude::depth), 0.5) - .with( - (Union::sdf_b, Sphere::radius), - (globals.time * 2.0).sin() + 1.0, - ); - */ - //let sdf = Extrude::::default().with(Extrude::depth, 0.5); - /* - let ofs = 1.75; - let sdf = SphereTraceLipschitz::< - 400, - NormalTetrahedron, Sphere>>, - >::default() - .with( - ( - SphereTraceLipschitz::target, - NormalTetrahedron::sdf, - SmoothSubtraction::k, - ), - 0.5, - ) - .with( - ( - SphereTraceLipschitz::target, - NormalTetrahedron::sdf, - SmoothSubtraction::sdf_a, - Extrude::depth, - ), - 0.5, - ) - .with( - ( - SphereTraceLipschitz::target, - NormalTetrahedron::sdf, - SmoothSubtraction::sdf_b, - Sphere::radius, - ), - (globals.time.sin() + ofs) / ofs, - ); - */ - //let sdf = ExtrudeInterior::::default().with(ExtrudeInterior::depth, 0.85); - - let sdf = ::default(); - - let dir = inv_model_rot * ray_direction.truncate(); - - let eye = inv_model_rot * (camera.truncate() - object.truncate()); - - let inverse_transpose_rot = Mat3::from_mat4(mesh.inverse_transpose_model); - - let frag_size = ddx(in_frag_coord.x / (view.viewport.z - 1.0)).abs() - + ddy(in_frag_coord.y / (view.viewport.w - 1.0)).abs(); - - let context = ( - inverse_transpose_rot, - frag_size, - RaycastInput { - start, - end, - eye, - dir, - }, - ); - - let (out,) = sdf.field_attributes_register_cons::<(Raycast,)>(&context); - let context = context.to_hlist().push_front(out).to_tlist(); - - // Context parameters - let context = context - .to_hlist() - .push_front(Position(eye + dir * out.closest_t)) - .to_tlist(); - - // Evaluate - let (normal,) = sdf.field_attributes_register_cons::<(AttrNormal,)>(&context); - let normal = *normal; - - // TODO: Convert into ops that take extra context params - let light = Vec3::new(-1.0, 1.0, 1.0) - .normalize() - .dot(inverse_transpose_rot * normal); - - let glow = (out.steps as f32 / MAX_STEPS as f32).powf(4.0) * MAX_STEPS as f32; - - // Scale antialias width in correspondence with screen resolution - // Roughly corresponds to 1px per K with a min bound of 2 - // i.e. 1K / 2K screens get 2px, 4K get 4px, and so on - let coverage_grad = (view.viewport.w / 540.0).max(2.0); - let coverage = - (out.closest_dist - frag_size * coverage_grad).smooth_step(frag_size * coverage_grad, 0.0); - - let (color,) = sdf.field_attributes_register_cons::<(AttrColor,)>(&context); - let col = color.xyz(); - - //let col = (inverse_transpose_rot * normal) * 0.5 + 0.5; - - let glow_col = col * Vec3::splat(glow); - let glow_col = glow_col * (1.0 - coverage); - - let col = col * Vec3::splat(light); - - let col = col * coverage; - - let col = col + glow_col; - - //let col_exterior = col * glow; - - //let col = col_exterior.mix(col, Vec3::splat(coverage)); - - *out_color = col.extend(coverage); - - // Type machine testing - /* - { - use rust_gpu_sdf::{ - field_type_machine::{ - EuclideanMetric, RayDirection, RayEnd, RayPosition, RayStart, RaymarchSteps, - SphereTraceLipschitz, - }, - prelude::Distance, - type_fields::type_machine::TypeMachine, - }; - - /* - (SphereTraceLipschitz::<400, EuclideanMetric>::default(),).run(( - Position(Vec3::ZERO), - Distance(0.0), - RaymarchSteps(0), - RayPosition(eye), - RayDirection(dir), - RayStart(start), - RayEnd(end), - EuclideanMetric::::default(), - )); - */ - - (EuclideanMetric::::default(),) - .run((Tagged::::point(Vec3::ZERO),)); - } - */ -} +} \ No newline at end of file diff --git a/rust-gpu/entrypoint.sh b/rust-gpu/entrypoint.sh new file mode 100644 index 0000000..dfb5150 --- /dev/null +++ b/rust-gpu/entrypoint.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -ex +source "$HOME/.cargo/env" + +cd /root/mnt/rust-gpu + + + +# the watches don't work on Windows + WSL2 + Docker +# https://github.com/microsoft/WSL/issues/4739 +# /root/.cargo/bin/cargo run --release -- "crates/shader" -w ./crates/shader/src -w ../bevy-app/crates/viewer/entry_points.json ../bevy-app/crates/viewer/assets/rust-gpu/shader.rust-gpu.msgpack + +set +x +export TS_FILE=/tmp/latest-timestamp +while true; do + LATEST_TS=$(find ../bevy-app/crates/viewer/entry_points.json ./crates/shader/ -type f -exec stat \{} --printf="%y\n" \; | sort -nr | head -n1) + OLD_TS=$(cat $TS_FILE||echo '') + if [ "$LATEST_TS" == "$OLD_TS" ]; then + sleep 2 + else + /root/.cargo/bin/cargo run --release -- "crates/shader" ../bevy-app/crates/viewer/assets/rust-gpu/shader.rust-gpu.msgpack + echo "$LATEST_TS" > $TS_FILE + fi +done \ No newline at end of file diff --git a/rust-gpu/rust-toolchain.toml b/rust-gpu/rust-toolchain.toml index 24320a7..8c8483a 100644 --- a/rust-gpu/rust-toolchain.toml +++ b/rust-gpu/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "nightly-2023-03-04" +channel = "nightly-2023-05-27" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] #[toolchain]