├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── assets ├── audio │ ├── box_join.ogg │ ├── finish.ogg │ ├── level1.ogg │ ├── level10.ogg │ ├── level11.ogg │ ├── level12.ogg │ ├── level2.ogg │ ├── level3.ogg │ ├── level4.ogg │ ├── level5.ogg │ ├── level6.ogg │ ├── level7.ogg │ ├── level8.ogg │ ├── level9.ogg │ ├── main_menu_background.ogg │ └── movement.ogg ├── fonts │ ├── raleway.ttf │ └── roboto.ttf └── images │ ├── avatar.png │ ├── box-default-2.png │ ├── box-default-3.png │ ├── button-on.png │ ├── button.png │ ├── buttons │ ├── back.png │ ├── button.png │ ├── credits-button.png │ ├── done-2.png │ ├── done.png │ ├── levels │ │ ├── back.png │ │ ├── level-1.png │ │ ├── level-10.png │ │ ├── level-11.png │ │ ├── level-12.png │ │ ├── level-2.png │ │ ├── level-3.png │ │ ├── level-4.png │ │ ├── level-5.png │ │ ├── level-6.png │ │ ├── level-7.png │ │ ├── level-8.png │ │ ├── level-9.png │ │ └── levels.png │ ├── next-level.png │ ├── next.png │ ├── play-button.png │ ├── prev.png │ ├── restart.png │ └── settings-button.png │ ├── choose-wisely.png │ ├── code.png │ ├── controls-2.png │ ├── controls.png │ ├── controls.psd │ ├── credits.png │ ├── enter-the-code.png │ ├── final.png │ ├── finish-arrow.png │ ├── finish-old.png │ ├── finish.png │ ├── finish.psd │ ├── overlay-down.png │ ├── overlay-gravity.png │ ├── overlay-left.png │ ├── overlay-right.png │ ├── overlay-undo.png │ ├── overlay-up.png │ ├── overlay-x2.png │ ├── overlay-x3.png │ ├── overlay-x4.png │ ├── overlay-x9.png │ ├── preview.png │ ├── robot-preview-0.png │ ├── robot-preview-1.png │ ├── robot-preview-2.png │ ├── robot-preview-3.png │ ├── robot-preview-4.png │ ├── robot-preview-5.png │ ├── robot-preview-6.png │ ├── robot-states-1.png │ ├── robot-states-2.png │ ├── robot-states-3.png │ ├── robot-states-4.png │ ├── robot-states-5.png │ ├── robot-states-6.png │ ├── robot-states-emissive.png │ ├── robot-states.psd │ ├── robot.png │ ├── title.png │ └── you-did-it.png ├── index.html ├── post-processing ├── Cargo.lock ├── Cargo.toml └── src │ ├── bloom_node.rs │ ├── color_material_custom.rs │ ├── lib.rs │ ├── lights.rs │ ├── main_pass_2d_node.rs │ ├── shaders │ ├── color_material_custom.wgsl │ ├── default.vert │ ├── downscaling.frag │ ├── tonemapping.frag │ └── upscaling.frag │ ├── tone_mapping_node.rs │ └── utils.rs └── src ├── core ├── audio.rs ├── camera.rs ├── material.rs ├── mod.rs ├── scene_builder │ ├── boundaries.rs │ ├── combobox.rs │ ├── door.rs │ ├── elevator.rs │ ├── mod.rs │ ├── player.rs │ ├── spawn_point.rs │ └── wall.rs └── scene_objects │ ├── collision_groups.rs │ ├── combobox.rs │ ├── door.rs │ ├── elevator.rs │ ├── mod.rs │ └── player.rs ├── game.rs ├── gui ├── buttons.rs ├── credits_menu.rs ├── game_menu.rs ├── level_completed_menu.rs ├── level_menu.rs ├── main_menu.rs └── mod.rs ├── levels ├── level1.rs ├── level10.rs ├── level11.rs ├── level12.rs ├── level2.rs ├── level3.rs ├── level4.rs ├── level5.rs ├── level6.rs ├── level7.rs ├── level8.rs ├── level9.rs └── mod.rs ├── main.rs ├── states.rs └── utils ├── direction.rs ├── fps.rs └── mod.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | 7 | env: 8 | CARGO_TERM_COLOR: always 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: self-hosted 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Installing wasm 18 | run: rustup target install wasm32-unknown-unknown 19 | - name: Installing wasm cli 20 | run: cargo install -f wasm-bindgen-cli 21 | - name: Build 22 | run: cargo build --target wasm32-unknown-unknown --release 23 | - name: Building wasm 24 | run: wasm-bindgen --out-dir ./out/ --target web ./target/wasm32-unknown-unknown/release/combobox-game.wasm 25 | - name: Push wasm build artifacts to git hub pages branch 26 | run: | 27 | git config --global user.name "${{ env.CI_COMMIT_AUTHOR }}" 28 | git config --global user.email "username@users.noreply.github.com" 29 | git clone https://github.com/${{ github.repository }} build 30 | cd build 31 | git checkout gh-pages 32 | del -r .\assets; cp -r ..\assets .\assets 33 | del -r .\index.html; cp ..\index.html . 34 | del -r .\out; cp -r ..\out .\out 35 | git add . 36 | git commit -m "Git hub pages update" 37 | git push 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/target/ 2 | target/ 3 | .idea/ 4 | out/ 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "combobox-game" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | bevy = { version="0.8.0", default-features=false, features=["bevy_ui", "bevy_text", "bevy_winit", "png", "filesystem_watcher"] } 10 | post-processing={ path="post-processing" } 11 | bevy_rapier2d = "0.16.1" 12 | rapier2d = "0.14.0" 13 | bevy_kira_audio = "0.12.0" 14 | 15 | [target.wasm32-unknown-unknown] 16 | runner = "wasm-server-runner" 17 | 18 | [profile.dev.package."*"] 19 | opt-level = 3 20 | 21 | [profile.dev] 22 | opt-level = 1 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Combobox 2 | 3 | Our game made for [Bevy Jam #2](https://itch.io/jam/bevy-jam-2)! 4 | 5 | P.S. Combobox game got **4th** /85 place! 6 | 7 | # Check out our current demo 8 | 9 | Demo can be found on [itches.io](https://combobox-game.itch.io/combobox) or on [github pages](https://comboboxgame.github.io/Combobox/) 10 | -------------------------------------------------------------------------------- /assets/audio/box_join.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/box_join.ogg -------------------------------------------------------------------------------- /assets/audio/finish.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/finish.ogg -------------------------------------------------------------------------------- /assets/audio/level1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level1.ogg -------------------------------------------------------------------------------- /assets/audio/level10.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level10.ogg -------------------------------------------------------------------------------- /assets/audio/level11.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level11.ogg -------------------------------------------------------------------------------- /assets/audio/level12.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level12.ogg -------------------------------------------------------------------------------- /assets/audio/level2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level2.ogg -------------------------------------------------------------------------------- /assets/audio/level3.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level3.ogg -------------------------------------------------------------------------------- /assets/audio/level4.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level4.ogg -------------------------------------------------------------------------------- /assets/audio/level5.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level5.ogg -------------------------------------------------------------------------------- /assets/audio/level6.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level6.ogg -------------------------------------------------------------------------------- /assets/audio/level7.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level7.ogg -------------------------------------------------------------------------------- /assets/audio/level8.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level8.ogg -------------------------------------------------------------------------------- /assets/audio/level9.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/level9.ogg -------------------------------------------------------------------------------- /assets/audio/main_menu_background.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/main_menu_background.ogg -------------------------------------------------------------------------------- /assets/audio/movement.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/audio/movement.ogg -------------------------------------------------------------------------------- /assets/fonts/raleway.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/fonts/raleway.ttf -------------------------------------------------------------------------------- /assets/fonts/roboto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/fonts/roboto.ttf -------------------------------------------------------------------------------- /assets/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/avatar.png -------------------------------------------------------------------------------- /assets/images/box-default-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/box-default-2.png -------------------------------------------------------------------------------- /assets/images/box-default-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/box-default-3.png -------------------------------------------------------------------------------- /assets/images/button-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/button-on.png -------------------------------------------------------------------------------- /assets/images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/button.png -------------------------------------------------------------------------------- /assets/images/buttons/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/back.png -------------------------------------------------------------------------------- /assets/images/buttons/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/button.png -------------------------------------------------------------------------------- /assets/images/buttons/credits-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/credits-button.png -------------------------------------------------------------------------------- /assets/images/buttons/done-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/done-2.png -------------------------------------------------------------------------------- /assets/images/buttons/done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/done.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/back.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-1.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-10.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-11.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-12.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-2.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-3.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-4.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-5.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-6.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-7.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-8.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/level-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/level-9.png -------------------------------------------------------------------------------- /assets/images/buttons/levels/levels.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/levels/levels.png -------------------------------------------------------------------------------- /assets/images/buttons/next-level.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/next-level.png -------------------------------------------------------------------------------- /assets/images/buttons/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/next.png -------------------------------------------------------------------------------- /assets/images/buttons/play-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/play-button.png -------------------------------------------------------------------------------- /assets/images/buttons/prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/prev.png -------------------------------------------------------------------------------- /assets/images/buttons/restart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/restart.png -------------------------------------------------------------------------------- /assets/images/buttons/settings-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/buttons/settings-button.png -------------------------------------------------------------------------------- /assets/images/choose-wisely.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/choose-wisely.png -------------------------------------------------------------------------------- /assets/images/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/code.png -------------------------------------------------------------------------------- /assets/images/controls-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/controls-2.png -------------------------------------------------------------------------------- /assets/images/controls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/controls.png -------------------------------------------------------------------------------- /assets/images/controls.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/controls.psd -------------------------------------------------------------------------------- /assets/images/credits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/credits.png -------------------------------------------------------------------------------- /assets/images/enter-the-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/enter-the-code.png -------------------------------------------------------------------------------- /assets/images/final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/final.png -------------------------------------------------------------------------------- /assets/images/finish-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/finish-arrow.png -------------------------------------------------------------------------------- /assets/images/finish-old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/finish-old.png -------------------------------------------------------------------------------- /assets/images/finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/finish.png -------------------------------------------------------------------------------- /assets/images/finish.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/finish.psd -------------------------------------------------------------------------------- /assets/images/overlay-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-down.png -------------------------------------------------------------------------------- /assets/images/overlay-gravity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-gravity.png -------------------------------------------------------------------------------- /assets/images/overlay-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-left.png -------------------------------------------------------------------------------- /assets/images/overlay-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-right.png -------------------------------------------------------------------------------- /assets/images/overlay-undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-undo.png -------------------------------------------------------------------------------- /assets/images/overlay-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-up.png -------------------------------------------------------------------------------- /assets/images/overlay-x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-x2.png -------------------------------------------------------------------------------- /assets/images/overlay-x3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-x3.png -------------------------------------------------------------------------------- /assets/images/overlay-x4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-x4.png -------------------------------------------------------------------------------- /assets/images/overlay-x9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/overlay-x9.png -------------------------------------------------------------------------------- /assets/images/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/preview.png -------------------------------------------------------------------------------- /assets/images/robot-preview-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-preview-0.png -------------------------------------------------------------------------------- /assets/images/robot-preview-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-preview-1.png -------------------------------------------------------------------------------- /assets/images/robot-preview-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-preview-2.png -------------------------------------------------------------------------------- /assets/images/robot-preview-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-preview-3.png -------------------------------------------------------------------------------- /assets/images/robot-preview-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-preview-4.png -------------------------------------------------------------------------------- /assets/images/robot-preview-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-preview-5.png -------------------------------------------------------------------------------- /assets/images/robot-preview-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-preview-6.png -------------------------------------------------------------------------------- /assets/images/robot-states-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-states-1.png -------------------------------------------------------------------------------- /assets/images/robot-states-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-states-2.png -------------------------------------------------------------------------------- /assets/images/robot-states-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-states-3.png -------------------------------------------------------------------------------- /assets/images/robot-states-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-states-4.png -------------------------------------------------------------------------------- /assets/images/robot-states-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-states-5.png -------------------------------------------------------------------------------- /assets/images/robot-states-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-states-6.png -------------------------------------------------------------------------------- /assets/images/robot-states-emissive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-states-emissive.png -------------------------------------------------------------------------------- /assets/images/robot-states.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot-states.psd -------------------------------------------------------------------------------- /assets/images/robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/robot.png -------------------------------------------------------------------------------- /assets/images/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/title.png -------------------------------------------------------------------------------- /assets/images/you-did-it.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ComboboxGame/Combobox/3c0cd0a4945fe061a7b5ad5d9ccab0d9199ad05d/assets/images/you-did-it.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 48 | 49 | 50 | 51 | 52 | 53 |

Combobox!

54 | 55 |
56 |
Start!
57 |
58 | 59 | 68 | 69 | -------------------------------------------------------------------------------- /post-processing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "post-processing" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | bevy = { version="0.8.0", default-features=false, features=["bevy_core_pipeline", "bevy_render", "bevy_asset", "bevy_sprite", "bevy_ui"] } 10 | wgpu = "0.13.1" 11 | bytemuck = "1.12.0" 12 | bitflags = "1.3.2" 13 | -------------------------------------------------------------------------------- /post-processing/src/color_material_custom.rs: -------------------------------------------------------------------------------- 1 | use bevy::app::{App, Plugin}; 2 | use bevy::asset::{Assets, Handle}; 3 | use bevy::math::Vec4; 4 | 5 | use bevy::reflect::TypeUuid; 6 | use bevy::render::mesh::MeshVertexBufferLayout; 7 | use bevy::render::{ 8 | color::Color, render_asset::RenderAssets, render_resource::*, texture::Image, 9 | }; 10 | 11 | use bevy::sprite::{ 12 | Material2d, Material2dKey, Material2dPlugin, 13 | }; 14 | use crate::{CUSTOM_MATERIAL, PointLightsUniform}; 15 | 16 | #[derive(Default)] 17 | pub struct ColorMaterialCustomPlugin; 18 | 19 | impl Plugin for ColorMaterialCustomPlugin { 20 | fn build(&self, app: &mut App) { 21 | app.add_plugin(Material2dPlugin::::default()); 22 | 23 | app.world 24 | .resource_mut::>() 25 | .set_untracked( 26 | Handle::::default(), 27 | ColorMaterialCustom { 28 | color: Color::rgb(1.0, 0.0, 1.0), 29 | ..Default::default() 30 | }, 31 | ); 32 | } 33 | } 34 | 35 | /// A [2d material](Material2d) that renders [2d meshes](crate::Mesh2dHandle) with a texture tinted by a uniform color 36 | #[derive(AsBindGroup, Debug, Clone, TypeUuid)] 37 | #[uuid = "e228a544-e3ca-4e1e-ba9d-4d8bc1ad8c19"] 38 | #[uniform(0, ColorMaterialCustomUniform)] 39 | pub struct ColorMaterialCustom { 40 | pub color: Color, 41 | pub lights: PointLightsUniform, 42 | #[texture(1)] 43 | #[sampler(2)] 44 | pub texture: Option>, 45 | 46 | #[texture(3)] 47 | #[sampler(4)] 48 | pub emissive: Option>, 49 | 50 | #[texture(5)] 51 | #[sampler(6)] 52 | pub overlay: Option>, 53 | } 54 | 55 | impl Default for ColorMaterialCustom { 56 | fn default() -> Self { 57 | ColorMaterialCustom { 58 | color: Color::WHITE, 59 | lights: PointLightsUniform::default(), 60 | texture: None, 61 | emissive: None, 62 | overlay: None, 63 | } 64 | } 65 | } 66 | 67 | impl From for ColorMaterialCustom { 68 | fn from(color: Color) -> Self { 69 | ColorMaterialCustom { 70 | color, 71 | ..Default::default() 72 | } 73 | } 74 | } 75 | 76 | impl From> for ColorMaterialCustom { 77 | fn from(texture: Handle) -> Self { 78 | ColorMaterialCustom { 79 | texture: Some(texture), 80 | ..Default::default() 81 | } 82 | } 83 | } 84 | 85 | impl From<(Handle, Option>, Option>)> for ColorMaterialCustom { 86 | fn from(texture: (Handle, Option>, Option>)) -> Self { 87 | ColorMaterialCustom { 88 | texture: Some(texture.0), 89 | emissive: texture.1, 90 | overlay: texture.2, 91 | ..Default::default() 92 | } 93 | } 94 | } 95 | 96 | /// The GPU representation of the uniform data of a [`ColorMaterialCustom`]. 97 | #[derive(Clone, Default, ShaderType)] 98 | pub struct ColorMaterialCustomUniform { 99 | pub color: Vec4, 100 | pub flags: u32, 101 | pub lights: PointLightsUniform, 102 | } 103 | 104 | // NOTE: These must match the bit flags in bevy_sprite/src/mesh2d/color_material.wgsl! 105 | bitflags::bitflags! { 106 | #[repr(transparent)] 107 | pub struct ColorMaterialFlagsCustom: u32 { 108 | const TEXTURE = (1 << 0); 109 | const EMISSIVE = (1 << 1); 110 | const OVERLAY = (1 << 2); 111 | const NONE = 0; 112 | const UNINITIALIZED = 0xFFFF; 113 | } 114 | } 115 | 116 | impl AsBindGroupShaderType for ColorMaterialCustom { 117 | fn as_bind_group_shader_type( 118 | &self, 119 | _images: &RenderAssets, 120 | ) -> ColorMaterialCustomUniform { 121 | let mut flags = ColorMaterialFlagsCustom::NONE; 122 | if self.texture.is_some() { 123 | flags |= ColorMaterialFlagsCustom::TEXTURE; 124 | } 125 | if self.emissive.is_some() { 126 | flags |= ColorMaterialFlagsCustom::EMISSIVE; 127 | } 128 | if self.overlay.is_some() { 129 | flags |= ColorMaterialFlagsCustom::OVERLAY; 130 | } 131 | 132 | ColorMaterialCustomUniform { 133 | color: self.color.as_linear_rgba_f32().into(), 134 | flags: flags.bits(), 135 | lights: self.lights.clone(), 136 | } 137 | } 138 | } 139 | 140 | impl Material2d for ColorMaterialCustom { 141 | fn fragment_shader() -> ShaderRef { 142 | CUSTOM_MATERIAL.typed().into() 143 | } 144 | 145 | fn specialize( 146 | descriptor: &mut RenderPipelineDescriptor, 147 | _layout: &MeshVertexBufferLayout, 148 | _key: Material2dKey, 149 | ) -> Result<(), SpecializedMeshPipelineError> { 150 | // HDR texture 151 | (*descriptor.fragment.as_mut().unwrap()).targets.clear(); 152 | (*descriptor.fragment.as_mut().unwrap()) 153 | .targets 154 | .push(Some(ColorTargetState { 155 | format: TextureFormat::Rg11b10Float, 156 | blend: Some(BlendState::ALPHA_BLENDING), 157 | write_mask: ColorWrites::ALL, 158 | })); 159 | descriptor.primitive.cull_mode = None; 160 | 161 | Ok(()) 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /post-processing/src/lib.rs: -------------------------------------------------------------------------------- 1 | use bevy::app::{App, CoreStage, Plugin}; 2 | use bevy::core_pipeline::core_2d::graph; 3 | use bevy::core_pipeline::core_2d::MainPass2dNode; 4 | use bevy::ecs::prelude::*; 5 | use bevy::prelude::{Assets, HandleUntyped, Msaa, Shader}; 6 | use bevy::reflect::TypeUuid; 7 | use bevy::render::{ 8 | render_graph::RenderGraph, 9 | RenderApp, RenderStage, 10 | }; 11 | use bevy::render::camera::ExtractedCamera; 12 | use bevy::render::render_resource::{Extent3d, Operations, ShaderStage, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages, TextureView, UniformBuffer}; 13 | use bevy::render::renderer::RenderDevice; 14 | use bevy::render::texture::TextureCache; 15 | use bevy::render::view::WindowSystem; 16 | use bevy::ui::draw_ui_graph; 17 | use bevy::utils::HashMap; 18 | pub use color_material_custom::ColorMaterialCustom; 19 | pub use lights::*; 20 | use wgpu::{Color, RenderPassColorAttachment}; 21 | 22 | use crate::bloom_node::*; 23 | use crate::color_material_custom::*; 24 | use crate::main_pass_2d_node::MainPass2dNodeCustom; 25 | use crate::tone_mapping_node::*; 26 | 27 | mod bloom_node; 28 | mod color_material_custom; 29 | mod main_pass_2d_node; 30 | mod tone_mapping_node; 31 | mod lights; 32 | mod utils; 33 | 34 | 35 | pub struct Core2dCustomPlugin; 36 | 37 | pub const CUSTOM_DEFAULT_VERT: HandleUntyped = 38 | HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 8454671400261990324); 39 | pub const CUSTOM_UPSCALING: HandleUntyped = 40 | HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 8678671400261345394); 41 | pub const CUSTOM_DOWNSCALING: HandleUntyped = 42 | HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 8214674567261990328); 43 | pub const CUSTOM_TONEMAPPING: HandleUntyped = 44 | HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 8994546787261990326); 45 | pub const CUSTOM_MATERIAL: HandleUntyped = 46 | HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 8213474567257890329); 47 | 48 | impl Plugin for Core2dCustomPlugin { 49 | fn build(&self, app: &mut App) { 50 | let mut assets = app.world.resource_mut::>(); 51 | assets.set_untracked( 52 | CUSTOM_DEFAULT_VERT, 53 | Shader::from_glsl(include_str!("shaders/default.vert"), ShaderStage::Vertex), 54 | ); 55 | assets.set_untracked( 56 | CUSTOM_UPSCALING, 57 | Shader::from_glsl( 58 | include_str!("shaders/upscaling.frag"), 59 | ShaderStage::Fragment, 60 | ), 61 | ); 62 | assets.set_untracked( 63 | CUSTOM_DOWNSCALING, 64 | Shader::from_glsl( 65 | include_str!("shaders/downscaling.frag"), 66 | ShaderStage::Fragment, 67 | ), 68 | ); 69 | assets.set_untracked( 70 | CUSTOM_TONEMAPPING, 71 | Shader::from_glsl( 72 | include_str!("shaders/tonemapping.frag"), 73 | ShaderStage::Fragment, 74 | ), 75 | ); 76 | assets.set_untracked( 77 | CUSTOM_MATERIAL, 78 | Shader::from_wgsl(include_str!("shaders/color_material_custom.wgsl")), 79 | ); 80 | 81 | app.add_plugin(ColorMaterialCustomPlugin); 82 | 83 | app.insert_resource(AmbientLight { color: bevy::prelude::Color::WHITE * 30.0 }); 84 | 85 | app.add_system_to_stage( 86 | CoreStage::Last, 87 | update_lights, 88 | ); 89 | 90 | let render_app = match app.get_sub_app_mut(RenderApp) { 91 | Ok(render_app) => render_app, 92 | Err(_) => return, 93 | }; 94 | 95 | render_app.init_resource::(); 96 | render_app.init_resource::(); 97 | 98 | render_app.add_system_to_stage( 99 | RenderStage::Prepare, 100 | prepare_view_targets_custom.after(WindowSystem::Prepare), 101 | ); 102 | 103 | render_app.add_system_to_stage( 104 | RenderStage::Prepare, 105 | prepare_bloom_targets.after(WindowSystem::Prepare), 106 | ); 107 | 108 | render_app.insert_resource(UniformBuffer::::default()); 109 | 110 | let pass_node_2d = MainPass2dNodeCustom::new(&mut render_app.world); 111 | let bloom_node = BloomNode::new(&mut render_app.world); 112 | let tone_mapping_node = ToneMappingNode::new(&mut render_app.world); 113 | 114 | let mut graph = render_app.world.resource_mut::(); 115 | let draw_2d_graph = graph 116 | .get_sub_graph_mut(bevy::core_pipeline::core_2d::graph::NAME) 117 | .unwrap(); 118 | 119 | draw_2d_graph.remove_node(graph::node::MAIN_PASS).unwrap(); 120 | 121 | draw_2d_graph.add_node(graph::node::MAIN_PASS, pass_node_2d); 122 | draw_2d_graph.add_node(BloomNode::NAME, bloom_node); 123 | draw_2d_graph.add_node(ToneMappingNode::NAME, tone_mapping_node); 124 | 125 | draw_2d_graph 126 | .add_slot_edge( 127 | draw_2d_graph.input_node().unwrap().id, 128 | graph::input::VIEW_ENTITY, 129 | graph::node::MAIN_PASS, 130 | MainPass2dNode::IN_VIEW, 131 | ) 132 | .unwrap(); 133 | 134 | draw_2d_graph 135 | .add_slot_edge( 136 | draw_2d_graph.input_node().unwrap().id, 137 | graph::input::VIEW_ENTITY, 138 | ToneMappingNode::NAME, 139 | ToneMappingNode::IN_VIEW, 140 | ) 141 | .unwrap(); 142 | 143 | draw_2d_graph 144 | .add_slot_edge( 145 | draw_2d_graph.input_node().unwrap().id, 146 | graph::input::VIEW_ENTITY, 147 | BloomNode::NAME, 148 | BloomNode::IN_VIEW, 149 | ) 150 | .unwrap(); 151 | 152 | draw_2d_graph 153 | .add_slot_edge( 154 | graph::node::MAIN_PASS, 155 | MainPass2dNodeCustom::OUT_TEXTURE, 156 | BloomNode::NAME, 157 | BloomNode::IN_TEXTURE, 158 | ) 159 | .unwrap(); 160 | 161 | draw_2d_graph 162 | .add_slot_edge( 163 | BloomNode::NAME, 164 | BloomNode::OUT_TEXTURE, 165 | ToneMappingNode::NAME, 166 | ToneMappingNode::IN_TEXTURE, 167 | ) 168 | .unwrap(); 169 | 170 | draw_2d_graph 171 | .add_node_edge(ToneMappingNode::NAME, draw_ui_graph::node::UI_PASS) 172 | .unwrap(); 173 | } 174 | } 175 | 176 | #[derive(Component)] 177 | pub struct ViewTargetCustom { 178 | pub view: TextureView, 179 | pub sampled_target: Option, 180 | } 181 | 182 | impl ViewTargetCustom { 183 | pub fn get_color_attachment(&self, ops: Operations) -> RenderPassColorAttachment { 184 | RenderPassColorAttachment { 185 | view: self.sampled_target.as_ref().unwrap_or(&self.view), 186 | resolve_target: if self.sampled_target.is_some() { 187 | Some(&self.view) 188 | } else { 189 | None 190 | }, 191 | ops, 192 | } 193 | } 194 | 195 | pub fn get_texture_view(&self) -> TextureView { 196 | self.view.clone() 197 | } 198 | } 199 | 200 | fn prepare_view_targets_custom( 201 | mut commands: Commands, 202 | msaa: Res, 203 | render_device: Res, 204 | mut texture_cache: ResMut, 205 | cameras: Query<(Entity, &ExtractedCamera)>, 206 | ) { 207 | let mut sampled_textures = HashMap::default(); 208 | let mut textures = HashMap::default(); 209 | 210 | for (entity, camera) in &cameras { 211 | if let Some(target_size) = camera.physical_target_size { 212 | let texture_view = textures 213 | .entry(camera.target.clone()) 214 | .or_insert_with(|| { 215 | texture_cache.get( 216 | &render_device, 217 | TextureDescriptor { 218 | label: Some("color_attachment_texture_custom"), 219 | size: Extent3d { 220 | width: target_size.x, 221 | height: target_size.y, 222 | depth_or_array_layers: 1, 223 | }, 224 | mip_level_count: 1, 225 | sample_count: 1, 226 | dimension: TextureDimension::D2, 227 | format: TextureFormat::Rg11b10Float, 228 | usage: TextureUsages::RENDER_ATTACHMENT 229 | | TextureUsages::TEXTURE_BINDING, 230 | }, 231 | ) 232 | }) 233 | .default_view 234 | .clone(); 235 | 236 | let sampled_target = if msaa.samples > 1 { 237 | let sampled_texture = sampled_textures 238 | .entry(camera.target.clone()) 239 | .or_insert_with(|| { 240 | texture_cache.get( 241 | &render_device, 242 | TextureDescriptor { 243 | label: Some("sampled_color_attachment_texture_custom"), 244 | size: Extent3d { 245 | width: target_size.x, 246 | height: target_size.y, 247 | depth_or_array_layers: 1, 248 | }, 249 | mip_level_count: 1, 250 | sample_count: msaa.samples, 251 | dimension: TextureDimension::D2, 252 | format: TextureFormat::Rg11b10Float, 253 | usage: TextureUsages::RENDER_ATTACHMENT 254 | | TextureUsages::TEXTURE_BINDING, 255 | }, 256 | ) 257 | }); 258 | Some(sampled_texture.default_view.clone()) 259 | } else { 260 | None 261 | }; 262 | commands.entity(entity).insert(ViewTargetCustom { 263 | view: texture_view.clone(), 264 | sampled_target, 265 | }); 266 | } 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /post-processing/src/lights.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bevy::render::render_resource::ShaderType; 3 | 4 | use crate::ColorMaterialCustom; 5 | 6 | #[derive(Component, Debug, Default)] 7 | pub struct PointLight2d { 8 | pub radius: f32, 9 | pub color: Color, 10 | } 11 | 12 | #[derive(Debug, Clone)] 13 | pub struct AmbientLight { 14 | pub color: Color, 15 | } 16 | 17 | #[derive(ShaderType, Clone, Debug)] 18 | pub struct PointLightsUniform { 19 | pub lights_num: u32, 20 | pub positions: [Vec4; 16], 21 | pub colors: [Vec4; 16], 22 | pub ambient: Vec4, 23 | } 24 | 25 | impl Default for PointLightsUniform { 26 | fn default() -> Self { 27 | Self { 28 | lights_num: 0, 29 | positions: [Vec4::ZERO; 16], 30 | colors: [Vec4::ZERO; 16], 31 | ambient: Vec4::new(30.0, 30.0, 30.0, 1.0), 32 | } 33 | } 34 | } 35 | 36 | pub fn update_lights( 37 | lights_query: Query<(&PointLight2d, &GlobalTransform)>, 38 | handles: Query<&Handle>, 39 | mut materials: ResMut>, 40 | ambient: Res, 41 | ) { 42 | let v: Vec4 = ambient.color.into(); 43 | if v.truncate().length() > 10.0 && !ambient.is_changed() { 44 | return; 45 | } 46 | 47 | 48 | let mut lights = PointLightsUniform::default(); 49 | 50 | lights.ambient = ambient.color.as_linear_rgba_f32().into(); 51 | 52 | for (point_light, transform) in lights_query.iter() { 53 | if point_light.radius < 0.01 { 54 | continue; 55 | } 56 | 57 | let i = lights.lights_num as usize; 58 | lights.positions[i] = Vec4::new(transform.translation().x, transform.translation().y, transform.translation().z, point_light.radius); 59 | lights.colors[i] = point_light.color.as_linear_rgba_f32().into(); 60 | lights.lights_num += 1; 61 | } 62 | 63 | for handle in handles.iter() { 64 | if let Some(material) = materials.get_mut(handle) { 65 | material.lights = lights.clone(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /post-processing/src/main_pass_2d_node.rs: -------------------------------------------------------------------------------- 1 | use bevy::core_pipeline::clear_color::ClearColorConfig; 2 | use bevy::core_pipeline::core_2d::{Transparent2d}; 3 | use bevy::prelude::*; 4 | use bevy::render::camera::ExtractedCamera; 5 | use bevy::render::render_graph::{ 6 | Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType, 7 | }; 8 | use bevy::render::render_phase::{DrawFunctions, RenderPhase, TrackedRenderPass}; 9 | use bevy::render::renderer::RenderContext; 10 | use bevy::render::view::{ExtractedView}; 11 | 12 | use wgpu::{LoadOp, Operations, RenderPassDescriptor}; 13 | 14 | use crate::ViewTargetCustom; 15 | 16 | pub struct MainPass2dNodeCustom { 17 | query: QueryState< 18 | ( 19 | &'static ExtractedCamera, 20 | &'static RenderPhase, 21 | &'static ViewTargetCustom, 22 | &'static Camera2d, 23 | ), 24 | With, 25 | >, 26 | } 27 | 28 | impl MainPass2dNodeCustom { 29 | pub const IN_VIEW: &'static str = "view"; 30 | pub const OUT_TEXTURE: &'static str = "texture"; 31 | 32 | pub fn new(world: &mut World) -> Self { 33 | Self { 34 | query: world.query_filtered(), 35 | } 36 | } 37 | } 38 | 39 | impl Node for MainPass2dNodeCustom { 40 | fn input(&self) -> Vec { 41 | vec![SlotInfo::new( 42 | MainPass2dNodeCustom::IN_VIEW, 43 | SlotType::Entity, 44 | )] 45 | } 46 | 47 | fn output(&self) -> Vec { 48 | vec![SlotInfo::new( 49 | MainPass2dNodeCustom::OUT_TEXTURE, 50 | SlotType::TextureView, 51 | )] 52 | } 53 | 54 | fn update(&mut self, world: &mut World) { 55 | self.query.update_archetypes(world); 56 | } 57 | 58 | fn run( 59 | &self, 60 | graph: &mut RenderGraphContext, 61 | render_context: &mut RenderContext, 62 | world: &World, 63 | ) -> Result<(), NodeRunError> { 64 | let view_entity = graph.get_input_entity(Self::IN_VIEW)?; 65 | 66 | if let Ok((camera, transparent_phase, target_custom, camera_2d)) = 67 | self.query.get_manual(world, view_entity) 68 | { 69 | let pass_descriptor = RenderPassDescriptor { 70 | label: Some("main_pass_2d_custom"), 71 | color_attachments: &[Some(target_custom.get_color_attachment(Operations { 72 | load: match camera_2d.clear_color { 73 | ClearColorConfig::Default => { 74 | LoadOp::Clear(world.resource::().0.into()) 75 | } 76 | ClearColorConfig::Custom(color) => LoadOp::Clear(color.into()), 77 | ClearColorConfig::None => LoadOp::Load, 78 | }, 79 | store: true, 80 | }))], 81 | depth_stencil_attachment: None, 82 | }; 83 | 84 | let draw_functions = world.resource::>(); 85 | 86 | let render_pass = render_context 87 | .command_encoder 88 | .begin_render_pass(&pass_descriptor); 89 | 90 | let mut draw_functions = draw_functions.write(); 91 | let mut tracked_pass = TrackedRenderPass::new(render_pass); 92 | if let Some(viewport) = camera.viewport.as_ref() { 93 | tracked_pass.set_camera_viewport(viewport); 94 | } 95 | for item in &transparent_phase.items { 96 | let draw_function = draw_functions.get_mut(item.draw_function).unwrap(); 97 | draw_function.draw(world, &mut tracked_pass, view_entity, item); 98 | } 99 | 100 | graph 101 | .set_output( 102 | MainPass2dNodeCustom::OUT_TEXTURE, 103 | target_custom.get_texture_view(), 104 | ) 105 | .unwrap(); 106 | } 107 | 108 | Ok(()) 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /post-processing/src/shaders/color_material_custom.wgsl: -------------------------------------------------------------------------------- 1 | #import bevy_sprite::mesh2d_types 2 | #import bevy_sprite::mesh2d_view_bindings 3 | 4 | 5 | let MAX_LIGHTS_NUM: i32 = 16; 6 | 7 | struct Lights { 8 | lights_num: u32, 9 | positions: array, MAX_LIGHTS_NUM>, 10 | colors: array, MAX_LIGHTS_NUM>, 11 | ambient: vec4, 12 | } 13 | 14 | struct ColorMaterial { 15 | color: vec4, 16 | // 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options. 17 | flags: u32, 18 | lights: Lights, 19 | }; 20 | 21 | let COLOR_MATERIAL_FLAGS_TEXTURE_BIT: u32 = 1u; 22 | let COLOR_MATERIAL_FLAGS_EMISSIVE_BIT: u32 = 2u; 23 | let COLOR_MATERIAL_FLAGS_OVERLAY_BIT: u32 = 4u; 24 | 25 | @group(1) @binding(0) 26 | var material: ColorMaterial; 27 | @group(1) @binding(1) 28 | var texture: texture_2d; 29 | @group(1) @binding(2) 30 | var texture_sampler: sampler; 31 | @group(1) @binding(3) 32 | var emissive: texture_2d; 33 | @group(1) @binding(4) 34 | var emissive_sampler: sampler; 35 | @group(1) @binding(5) 36 | var overlay: texture_2d; 37 | @group(1) @binding(6) 38 | var overlay_sampler: sampler; 39 | 40 | @group(2) @binding(0) 41 | var mesh: Mesh2d; 42 | 43 | struct FragmentInput { 44 | @builtin(front_facing) is_front: bool, 45 | #import bevy_sprite::mesh2d_vertex_output 46 | }; 47 | 48 | fn hsl2rgb(c: vec3) -> vec3 49 | { 50 | var x = c.x*6.0+vec3(0.0,4.0,2.0); 51 | var d = vec3(x.x % 6.0,x.y % 6.0,x.z % 6.0); 52 | var rgb = clamp(abs(d - 3.0) - 1.0, vec3(0.0), vec3(1.0)); 53 | return c.z + c.y * (rgb - 0.5)*(1.0 - abs(2.0*c.z - 1.0)); 54 | } 55 | 56 | @fragment 57 | fn fragment(in: FragmentInput) -> @location(0) vec4 { 58 | var output_color: vec4 = material.color; 59 | if ((material.flags & COLOR_MATERIAL_FLAGS_TEXTURE_BIT) != 0u) { 60 | var texture_color = textureSample(texture, texture_sampler, in.uv); 61 | if ((material.flags & COLOR_MATERIAL_FLAGS_EMISSIVE_BIT) != 0u) { 62 | let emissive = textureSample(emissive, emissive_sampler, in.uv); 63 | texture_color = texture_color + vec4(emissive.rgb * emissive.a, 0.0) * 5.0; 64 | } 65 | #ifdef VERTEX_COLORS 66 | output_color = output_color * texture_color * in.color; 67 | #else 68 | output_color = output_color * texture_color; 69 | #endif 70 | if ((material.flags & COLOR_MATERIAL_FLAGS_OVERLAY_BIT) != 0u) { 71 | let overlay = textureSample(overlay, overlay_sampler, in.uv); 72 | output_color = vec4(output_color.rgb * (1.0 - overlay.w) + overlay.rgb * overlay.w, output_color.w); 73 | } 74 | } 75 | 76 | if (output_color.a < 0.01) { 77 | output_color = vec4(output_color.rgb, 0.0); 78 | } 79 | 80 | var light = material.lights.ambient.rgb; 81 | 82 | for (var i:u32 = 0u; i < material.lights.lights_num; i++) { 83 | let radius = material.lights.positions[i].w; 84 | let dist = length(in.world_position.xy - material.lights.positions[i].xy); 85 | if (dist >= radius) { 86 | // continue; 87 | } 88 | //let intensity = sqrt(1.0 - dist * dist / (radius * radius)); 89 | let x = dist / radius; 90 | let intensity = exp(-x*x*4.0); 91 | light += intensity * material.lights.colors[i].rgb; 92 | } 93 | 94 | light = light / (1.0 + dot(light, vec3(0.33, 0.33, 0.33))); 95 | 96 | output_color = vec4(output_color.rgb * light, output_color.w); 97 | 98 | return output_color; 99 | } 100 | -------------------------------------------------------------------------------- /post-processing/src/shaders/default.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) in vec3 vertex; 4 | layout (location = 0) out vec3 uv; 5 | 6 | void main() { 7 | gl_Position = vec4(vertex.xy * 2 - 1, vertex.z, 1.0); 8 | uv = vec3(vertex.x, 1 - vertex.y, vertex.z); 9 | } 10 | -------------------------------------------------------------------------------- /post-processing/src/shaders/downscaling.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) in vec3 uv; 4 | layout (location = 0) out vec4 out_color; 5 | 6 | #ifdef MSAA 7 | #define TEXTURE texture2DMS 8 | #define SAMPLER sampler2DMS 9 | #else 10 | #define TEXTURE texture2D 11 | #define SAMPLER sampler2D 12 | #endif 13 | 14 | layout(binding = 0) uniform sampler default_sampler; 15 | layout(binding = 1) uniform TEXTURE color_texture; 16 | layout(binding = 3) uniform uvec4 step; 17 | 18 | vec4 quadratic_threshold(vec4 color, float threshold, vec3 curve) { 19 | float br = max(max(color.r, color.g), color.b); 20 | 21 | float rq = clamp(br - curve.x, 0.0, curve.y); 22 | rq = curve.z * rq * rq; 23 | 24 | return color * max(rq, br - threshold) / max(br, 0.0001); 25 | } 26 | 27 | vec4 sample_13(vec2 scale) { 28 | vec4 a = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2(-1.0, -1.0) * scale); 29 | vec4 b = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2( 0.0, -1.0) * scale); 30 | vec4 c = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2( 1.0, -1.0) * scale); 31 | vec4 d = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2(-0.5, -0.5) * scale); 32 | vec4 e = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2( 0.5, -0.5) * scale); 33 | vec4 f = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2(-1.0, 0.0) * scale); 34 | vec4 g = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2( 0.0, 0.0) * scale); 35 | vec4 h = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2( 1.0, 0.0) * scale); 36 | vec4 i = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2(-0.5, 0.5) * scale); 37 | vec4 j = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2( 0.5, 0.5) * scale); 38 | vec4 k = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2(-1.0, 1.0) * scale); 39 | vec4 l = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2( 0.0, 1.0) * scale); 40 | vec4 m = texture(sampler2D(color_texture, default_sampler), uv.xy + vec2( 1.0, 1.0) * scale); 41 | 42 | vec4 res = (d + e + i + j) * 0.5 43 | + (a + b + g + f) * 0.125 44 | + (b + c + h + g) * 0.125 45 | + (f + g + l + k) * 0.125 46 | + (g + h + m + l) * 0.125; 47 | 48 | return res * 0.25; 49 | } 50 | 51 | void main() { 52 | ivec2 texSize = textureSize(color_texture, 0); 53 | vec2 scale = 1.0 / vec2(texSize); 54 | out_color = sample_13(scale); 55 | 56 | if (step.x == 1) { 57 | float threshold = 1.8; 58 | float knee = 0.1; 59 | vec3 curve = vec3(threshold - knee, knee * 2.0, 0.25 / knee); 60 | 61 | out_color = quadratic_threshold(out_color, threshold, curve); 62 | out_color = max(out_color, vec4(0.00001)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /post-processing/src/shaders/tonemapping.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) in vec3 uv; 4 | layout (location = 0) out vec4 out_color; 5 | 6 | layout(binding = 0) uniform sampler default_sampler; 7 | layout(binding = 1) uniform texture2D color_texture; 8 | 9 | float gamma = 1.3; 10 | 11 | vec3 tonemapping(vec3 color) { 12 | float luma = dot(color, vec3(0.33, 0.33, 0.33)); 13 | color += smoothstep(0.6, 2.5, luma) * luma * 0.5; 14 | luma = dot(color, vec3(0.2126, 0.7152, 0.0722)); 15 | color /= (0.5 + luma); 16 | color = pow(color, vec3(1. / gamma)); 17 | return color; 18 | } 19 | 20 | void main() { 21 | ivec2 texSize = textureSize(color_texture, 0); 22 | 23 | vec4 color = texelFetch(sampler2D(color_texture, default_sampler), ivec2(uv.xy * texSize), 0).rgba; 24 | out_color.xyz = tonemapping(color.xyz); 25 | out_color.w = color.w; 26 | } 27 | -------------------------------------------------------------------------------- /post-processing/src/shaders/upscaling.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) in vec3 uv; 4 | layout (location = 0) out vec4 out_color; 5 | 6 | layout(binding = 0) uniform sampler default_sampler; 7 | layout(binding = 1) uniform texture2D first_texture; // smaller 8 | layout(binding = 2) uniform texture2D second_texture; // bigger 9 | layout(binding = 3) uniform uvec4 step; 10 | 11 | vec4 sample_tent(vec2 scale) { 12 | vec4 d = vec4(1.0, 1.0, -1.0, 0.0); 13 | 14 | vec4 s = texture(sampler2D(first_texture, default_sampler), uv.xy - d.xy * scale) 15 | + texture(sampler2D(first_texture, default_sampler), uv.xy - d.wy * scale) * 2.0 16 | + texture(sampler2D(first_texture, default_sampler), uv.xy - d.zy * scale) 17 | + texture(sampler2D(first_texture, default_sampler), uv.xy + d.zw * scale) * 2.0 18 | + texture(sampler2D(first_texture, default_sampler), uv.xy ) * 4.0 19 | + texture(sampler2D(first_texture, default_sampler), uv.xy + d.xw * scale) * 2.0 20 | + texture(sampler2D(first_texture, default_sampler), uv.xy + d.zy * scale) 21 | + texture(sampler2D(first_texture, default_sampler), uv.xy + d.wy * scale) * 2.0 22 | + texture(sampler2D(first_texture, default_sampler), uv.xy + d.xy * scale); 23 | 24 | return s / 16.0; 25 | } 26 | 27 | void main() { 28 | ivec2 texSize = textureSize(first_texture, 0); 29 | vec2 scale = 1.0 / vec2(texSize); 30 | 31 | vec4 up_sample = sample_tent(scale * 1.0); 32 | vec4 color = texture(sampler2D(second_texture, default_sampler), uv.xy); 33 | 34 | if (step.x == 1) { 35 | out_color = vec4(color.rgb * 1.0 + up_sample.rgb * 0.6, 1.0); 36 | } else { 37 | out_color = vec4(color.rgb + up_sample.rgb * 0.3, 1.0); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /post-processing/src/tone_mapping_node.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bevy::render::camera::ExtractedCamera; 3 | use bevy::render::mesh::PrimitiveTopology; 4 | use bevy::render::render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}; 5 | use bevy::render::render_phase::TrackedRenderPass; 6 | use bevy::render::render_resource::{ 7 | BindGroupLayout, BindGroupLayoutEntry, BindingType, BlendState, BufferVec, 8 | CachedRenderPipelineId, ColorTargetState, ColorWrites, FragmentState, FrontFace, 9 | MultisampleState, PipelineCache, PolygonMode, PrimitiveState, RenderPipelineDescriptor, 10 | Sampler, SamplerBindingType, ShaderStages, TextureFormat, TextureSampleType, 11 | TextureViewDimension, VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, 12 | }; 13 | use bevy::render::renderer::{RenderContext, RenderDevice, RenderQueue}; 14 | use bevy::render::texture::BevyDefault; 15 | use bevy::render::view::{ExtractedView, ViewTarget}; 16 | use wgpu::{ 17 | BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindingResource, 18 | Operations, RenderPassColorAttachment, RenderPassDescriptor, 19 | }; 20 | 21 | use crate::CUSTOM_DEFAULT_VERT; 22 | use crate::CUSTOM_TONEMAPPING; 23 | use crate::utils::{create_default_quad, create_default_sampler, ScreenVertex}; 24 | 25 | pub struct ToneMappingNode { 26 | query: QueryState< 27 | ( 28 | &'static ExtractedCamera, 29 | &'static ViewTarget, 30 | &'static Camera2d, 31 | ), 32 | With, 33 | >, 34 | screen_quad: BufferVec, 35 | sampler: Sampler, 36 | } 37 | 38 | impl ToneMappingNode { 39 | pub const NAME: &'static str = "tone_mapping"; 40 | pub const IN_VIEW: &'static str = "view"; 41 | pub const IN_TEXTURE: &'static str = "tone_mapping_in_texture"; 42 | 43 | pub fn new(world: &mut World) -> Self { 44 | let query = world.query_filtered(); 45 | let render_device = world.resource::(); 46 | let render_queue = world.resource::(); 47 | 48 | Self { 49 | query, 50 | sampler: create_default_sampler(render_device), 51 | screen_quad: create_default_quad(render_device, render_queue), 52 | } 53 | } 54 | } 55 | 56 | impl Node for ToneMappingNode { 57 | fn input(&self) -> Vec { 58 | vec![ 59 | SlotInfo::new(ToneMappingNode::IN_VIEW, SlotType::Entity), 60 | SlotInfo::new(ToneMappingNode::IN_TEXTURE, SlotType::TextureView), 61 | ] 62 | } 63 | 64 | fn update(&mut self, world: &mut World) { 65 | self.query.update_archetypes(world); 66 | } 67 | 68 | fn run( 69 | &self, 70 | graph: &mut RenderGraphContext, 71 | render_context: &mut RenderContext, 72 | world: &World, 73 | ) -> Result<(), NodeRunError> { 74 | let view_entity = graph.get_input_entity(Self::IN_VIEW)?; 75 | let input = graph.get_input_texture(Self::IN_TEXTURE)?; 76 | 77 | let (camera, target, _camera_2d) = 78 | if let Ok(result) = self.query.get_manual(world, view_entity) { 79 | result 80 | } else { 81 | return Ok(()); 82 | }; 83 | let pass_descriptor = RenderPassDescriptor { 84 | label: Some("tone_mapping_pass"), 85 | color_attachments: &[Some(RenderPassColorAttachment { 86 | view: &target.view, 87 | resolve_target: None, 88 | ops: Operations::default(), 89 | })], 90 | depth_stencil_attachment: None, 91 | }; 92 | 93 | let render_pass = render_context 94 | .command_encoder 95 | .begin_render_pass(&pass_descriptor); 96 | 97 | let render_device = world.resource::(); 98 | let pipeline_cache = world.resource::(); 99 | let pipeline = world.resource::(); 100 | 101 | let bind_group = render_device.create_bind_group(&BindGroupDescriptor { 102 | label: Some("final_pass_bind_group"), 103 | layout: &pipeline.layout, 104 | entries: &[ 105 | BindGroupEntry { 106 | binding: 0, 107 | resource: BindingResource::Sampler(&self.sampler), 108 | }, 109 | BindGroupEntry { 110 | binding: 1, 111 | resource: BindingResource::TextureView(input), 112 | }, 113 | ], 114 | }); 115 | 116 | if let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline.pipeline) { 117 | let mut tracked_pass = TrackedRenderPass::new(render_pass); 118 | if let Some(viewport) = camera.viewport.as_ref() { 119 | tracked_pass.set_camera_viewport(viewport); 120 | } 121 | tracked_pass.set_render_pipeline(pipeline); 122 | tracked_pass.set_bind_group(0, &bind_group, &[]); 123 | tracked_pass.set_vertex_buffer(0, self.screen_quad.buffer().unwrap().slice(..)); 124 | tracked_pass.draw(0..self.screen_quad.len() as u32, 0..1); 125 | } 126 | 127 | Ok(()) 128 | } 129 | } 130 | 131 | #[derive(Clone)] 132 | pub struct ToneMappingPipeline { 133 | pub layout: BindGroupLayout, 134 | pub pipeline: CachedRenderPipelineId, 135 | } 136 | 137 | impl FromWorld for ToneMappingPipeline { 138 | fn from_world(world: &mut World) -> Self { 139 | let render_device = world.resource::().clone(); 140 | let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { 141 | label: Some("tone_mapping_layout"), 142 | entries: &[ 143 | BindGroupLayoutEntry { 144 | binding: 0, 145 | visibility: ShaderStages::FRAGMENT, 146 | ty: BindingType::Sampler(SamplerBindingType::NonFiltering), 147 | count: None, 148 | }, 149 | BindGroupLayoutEntry { 150 | binding: 1, 151 | visibility: ShaderStages::FRAGMENT, 152 | ty: BindingType::Texture { 153 | multisampled: false, 154 | view_dimension: TextureViewDimension::D2, 155 | sample_type: TextureSampleType::Float { filterable: false }, 156 | }, 157 | count: None, 158 | }, 159 | ], 160 | }); 161 | 162 | let mut pipeline_cache = world.resource_mut::(); 163 | 164 | let pipeline = pipeline_cache.queue_render_pipeline(RenderPipelineDescriptor { 165 | label: Some("tone_mapping_pass".into()), 166 | vertex: VertexState { 167 | shader: CUSTOM_DEFAULT_VERT.typed(), 168 | entry_point: "main".into(), 169 | shader_defs: vec![], 170 | buffers: vec![VertexBufferLayout::from_vertex_formats( 171 | VertexStepMode::Vertex, 172 | vec![VertexFormat::Float32x3], 173 | )], 174 | }, 175 | fragment: Some(FragmentState { 176 | shader: CUSTOM_TONEMAPPING.typed(), 177 | shader_defs: vec![], 178 | entry_point: "main".into(), 179 | targets: vec![Some(ColorTargetState { 180 | format: TextureFormat::bevy_default(), 181 | blend: Some(BlendState::ALPHA_BLENDING), 182 | write_mask: ColorWrites::ALL, 183 | })], 184 | }), 185 | layout: Some(vec![layout.clone()]), 186 | primitive: PrimitiveState { 187 | front_face: FrontFace::Ccw, 188 | cull_mode: None, 189 | unclipped_depth: false, 190 | polygon_mode: PolygonMode::Fill, 191 | conservative: false, 192 | topology: PrimitiveTopology::TriangleList, 193 | strip_index_format: None, 194 | }, 195 | depth_stencil: None, 196 | multisample: MultisampleState { 197 | count: 1, 198 | mask: !0, 199 | alpha_to_coverage_enabled: false, 200 | }, 201 | }); 202 | 203 | Self { layout, pipeline } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /post-processing/src/utils.rs: -------------------------------------------------------------------------------- 1 | use bevy::core::{Pod, Zeroable}; 2 | use bevy::render::render_resource::{BufferUsages, BufferVec, FilterMode, Sampler}; 3 | use bevy::render::renderer::{RenderDevice, RenderQueue}; 4 | use wgpu::{AddressMode, SamplerDescriptor}; 5 | 6 | #[repr(C)] 7 | #[derive(Copy, Clone, Pod, Zeroable)] 8 | pub struct ScreenVertex { 9 | pub position: [f32; 3], 10 | } 11 | 12 | pub fn create_default_quad( 13 | render_device: &RenderDevice, 14 | render_queue: &RenderQueue, 15 | ) -> BufferVec { 16 | let mut screen_quad = BufferVec::new(BufferUsages::VERTEX); 17 | // Triangle 1 18 | screen_quad.push(ScreenVertex { 19 | position: [0.0, 0.0, 0.0], 20 | }); 21 | screen_quad.push(ScreenVertex { 22 | position: [0.0, 1.0, 0.0], 23 | }); 24 | screen_quad.push(ScreenVertex { 25 | position: [1.0, 1.0, 0.0], 26 | }); 27 | // Triangle 2 28 | screen_quad.push(ScreenVertex { 29 | position: [0.0, 0.0, 0.0], 30 | }); 31 | screen_quad.push(ScreenVertex { 32 | position: [1.0, 0.0, 0.0], 33 | }); 34 | screen_quad.push(ScreenVertex { 35 | position: [1.0, 1.0, 0.0], 36 | }); 37 | screen_quad.write_buffer(render_device, render_queue); 38 | return screen_quad; 39 | } 40 | 41 | pub fn create_default_sampler(render_device: &RenderDevice) -> Sampler { 42 | render_device.create_sampler(&SamplerDescriptor { 43 | label: Some("default_sampler"), 44 | mag_filter: FilterMode::Nearest, 45 | min_filter: FilterMode::Nearest, 46 | address_mode_u: AddressMode::ClampToEdge, 47 | address_mode_v: AddressMode::ClampToEdge, 48 | address_mode_w: AddressMode::ClampToEdge, 49 | ..Default::default() 50 | }) 51 | } 52 | 53 | pub fn create_linear_sampler(render_device: &RenderDevice) -> Sampler { 54 | render_device.create_sampler(&SamplerDescriptor { 55 | label: Some("linear_sampler"), 56 | mag_filter: FilterMode::Linear, 57 | min_filter: FilterMode::Linear, 58 | address_mode_u: AddressMode::ClampToEdge, 59 | address_mode_v: AddressMode::ClampToEdge, 60 | address_mode_w: AddressMode::ClampToEdge, 61 | ..Default::default() 62 | }) 63 | } 64 | -------------------------------------------------------------------------------- /src/core/audio.rs: -------------------------------------------------------------------------------- 1 | use std::{path::PathBuf, time::Duration}; 2 | 3 | use bevy::{ 4 | prelude::{ 5 | App, AssetServer, Assets, Commands, Entity, Handle, Local, Plugin, Query, Res, ResMut, SystemSet, 6 | }, 7 | utils::{HashMap, Instant}, 8 | }; 9 | use bevy_kira_audio::{Audio, AudioControl, AudioEasing, AudioInstance, AudioTween}; 10 | 11 | use crate::states::AudioState; 12 | 13 | use super::Player; 14 | 15 | pub struct BackgroundMusicHandle(Handle); 16 | 17 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] 18 | pub struct BackgroundMusic(pub Option); 19 | 20 | #[derive(Debug)] 21 | pub struct PlayerStatus { 22 | handle: Handle, 23 | start_time: Option, 24 | } 25 | 26 | pub struct AudioPlugin; 27 | 28 | impl Plugin for AudioPlugin { 29 | fn build(&self, app: &mut App) { 30 | app.add_system_set(SystemSet::on_enter(AudioState::Menu).with_system(setup_menu_music)); 31 | app.add_system(play_background_music); 32 | app.add_system(play_player_movement_sound); 33 | 34 | app.insert_resource(BackgroundMusic(Some( 35 | "audio/main_menu_background.ogg".to_string(), 36 | ))); 37 | } 38 | } 39 | 40 | fn setup_menu_music(mut background_music: ResMut) { 41 | background_music.0 = Some("audio/main_menu_background.ogg".to_string()); 42 | } 43 | 44 | fn play_background_music( 45 | mut commands: Commands, 46 | audio: Res