├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── pull_reqeust.yml │ └── rust.yml ├── .gitignore ├── .gitmodules ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── crates ├── vent-assets │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── image.rs │ │ ├── io │ │ ├── file.rs │ │ └── mod.rs │ │ ├── lib.rs │ │ └── model │ │ ├── loader.rs │ │ ├── mod.rs │ │ └── optimizer.rs ├── vent-ecs │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── archetype.rs │ │ ├── component │ │ ├── input_component.rs │ │ └── mod.rs │ │ ├── entity │ │ └── mod.rs │ │ ├── lib.rs │ │ └── world │ │ └── mod.rs ├── vent-editor │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── gui │ │ └── mod.rs │ │ ├── main.rs │ │ └── render │ │ ├── mod.rs │ │ └── runtime_renderer.rs ├── vent-logging │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── vent-math │ ├── Cargo.toml │ └── src │ │ ├── align16.rs │ │ ├── deref.rs │ │ ├── lib.rs │ │ ├── scalar │ │ ├── mat4.rs │ │ ├── mod.rs │ │ └── quat.rs │ │ └── vec │ │ ├── i32 │ │ ├── ivec2.rs │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── vec2.rs │ │ ├── vec3.rs │ │ └── vec4.rs ├── vent-rendering │ ├── Cargo.toml │ └── src │ │ ├── allocator.rs │ │ ├── buffer.rs │ │ ├── debug.rs │ │ ├── image.rs │ │ ├── instance.rs │ │ ├── lib.rs │ │ ├── mesh.rs │ │ ├── pipeline.rs │ │ ├── surface.rs │ │ └── vertex.rs ├── vent-runtime │ ├── Cargo.toml │ ├── README.md │ ├── assets │ │ ├── fonts │ │ │ ├── Arial.ttf │ │ │ └── OpenSans.ttf │ │ ├── models │ │ │ ├── basic │ │ │ │ └── cube.glb │ │ │ └── test │ │ │ │ └── Sponza-GLTF │ │ │ │ ├── 10381718147657362067.jpg │ │ │ │ ├── 10388182081421875623.jpg │ │ │ │ ├── 11474523244911310074.jpg │ │ │ │ ├── 11490520546946913238.jpg │ │ │ │ ├── 11872827283454512094.jpg │ │ │ │ ├── 11968150294050148237.jpg │ │ │ │ ├── 1219024358953944284.jpg │ │ │ │ ├── 12501374198249454378.jpg │ │ │ │ ├── 13196865903111448057.jpg │ │ │ │ ├── 13824894030729245199.jpg │ │ │ │ ├── 13982482287905699490.jpg │ │ │ │ ├── 14118779221266351425.jpg │ │ │ │ ├── 14170708867020035030.jpg │ │ │ │ ├── 14267839433702832875.jpg │ │ │ │ ├── 14650633544276105767.jpg │ │ │ │ ├── 15295713303328085182.jpg │ │ │ │ ├── 15722799267630235092.jpg │ │ │ │ ├── 16275776544635328252.png │ │ │ │ ├── 16299174074766089871.jpg │ │ │ │ ├── 16885566240357350108.jpg │ │ │ │ ├── 17556969131407844942.jpg │ │ │ │ ├── 17876391417123941155.jpg │ │ │ │ ├── 2051777328469649772.jpg │ │ │ │ ├── 2185409758123873465.jpg │ │ │ │ ├── 2299742237651021498.jpg │ │ │ │ ├── 2374361008830720677.jpg │ │ │ │ ├── 2411100444841994089.jpg │ │ │ │ ├── 2775690330959970771.jpg │ │ │ │ ├── 2969916736137545357.jpg │ │ │ │ ├── 332936164838540657.jpg │ │ │ │ ├── 3371964815757888145.jpg │ │ │ │ ├── 3455394979645218238.jpg │ │ │ │ ├── 3628158980083700836.jpg │ │ │ │ ├── 3827035219084910048.jpg │ │ │ │ ├── 4477655471536070370.jpg │ │ │ │ ├── 4601176305987539675.jpg │ │ │ │ ├── 466164707995436622.jpg │ │ │ │ ├── 4675343432951571524.jpg │ │ │ │ ├── 4871783166746854860.jpg │ │ │ │ ├── 4910669866631290573.jpg │ │ │ │ ├── 4975155472559461469.jpg │ │ │ │ ├── 5061699253647017043.png │ │ │ │ ├── 5792855332885324923.jpg │ │ │ │ ├── 5823059166183034438.jpg │ │ │ │ ├── 6047387724914829168.jpg │ │ │ │ ├── 6151467286084645207.jpg │ │ │ │ ├── 6593109234861095314.jpg │ │ │ │ ├── 6667038893015345571.jpg │ │ │ │ ├── 6772804448157695701.jpg │ │ │ │ ├── 7056944414013900257.jpg │ │ │ │ ├── 715093869573992647.jpg │ │ │ │ ├── 7268504077753552595.jpg │ │ │ │ ├── 7441062115984513793.jpg │ │ │ │ ├── 755318871556304029.jpg │ │ │ │ ├── 759203620573749278.jpg │ │ │ │ ├── 7645212358685992005.jpg │ │ │ │ ├── 7815564343179553343.jpg │ │ │ │ ├── 8006627369776289000.png │ │ │ │ ├── 8051790464816141987.jpg │ │ │ │ ├── 8114461559286000061.jpg │ │ │ │ ├── 8481240838833932244.jpg │ │ │ │ ├── 8503262930880235456.jpg │ │ │ │ ├── 8747919177698443163.jpg │ │ │ │ ├── 8750083169368950601.jpg │ │ │ │ ├── 8773302468495022225.jpg │ │ │ │ ├── 8783994986360286082.jpg │ │ │ │ ├── 9288698199695299068.jpg │ │ │ │ ├── 9916269861720640319.jpg │ │ │ │ ├── Sponza.bin │ │ │ │ ├── Sponza.gltf │ │ │ │ └── white.png │ │ ├── shaders │ │ │ └── app │ │ │ │ ├── 2D │ │ │ │ ├── gui.frag │ │ │ │ └── gui.vert │ │ │ │ └── 3D │ │ │ │ ├── light.frag │ │ │ │ ├── light.vert │ │ │ │ ├── shader.frag │ │ │ │ ├── shader.vert │ │ │ │ ├── skybox.frag │ │ │ │ └── skybox.vert │ │ └── textures │ │ │ └── skybox │ │ │ ├── back.jpg │ │ │ ├── bottom.jpg │ │ │ ├── front.jpg │ │ │ ├── left.jpg │ │ │ ├── right.jpg │ │ │ └── top.jpg │ ├── build.rs │ └── src │ │ ├── lib.rs │ │ ├── main.rs │ │ ├── project │ │ └── mod.rs │ │ ├── render │ │ ├── camera │ │ │ ├── camera_controller3d.rs │ │ │ └── mod.rs │ │ ├── d2 │ │ │ └── mod.rs │ │ ├── d3 │ │ │ ├── light_renderer.rs │ │ │ ├── mod.rs │ │ │ └── skybox_renderer.rs │ │ ├── gui │ │ │ ├── debug_gui.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── model.rs │ │ └── model_renderer.rs │ │ └── util │ │ ├── crash.rs │ │ ├── input_handler.rs │ │ ├── mod.rs │ │ └── version.rs ├── vent-sdk │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── utils │ │ ├── mod.rs │ │ └── stopwatch.rs ├── vent-ui │ ├── Cargo.toml │ └── src │ │ ├── font │ │ ├── ab_glyph.rs │ │ ├── loader.rs │ │ └── mod.rs │ │ ├── lib.rs │ │ ├── renderer.rs │ │ └── widgets │ │ ├── button.rs │ │ └── mod.rs └── vent-window │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── keyboard.rs │ ├── lib.rs │ ├── mouse.rs │ └── platform │ ├── mod.rs │ ├── wayland │ └── mod.rs │ └── windows │ └── mod.rs ├── docs └── logo.png └── test └── runtime-sandbox ├── Cargo.toml ├── project.vent └── src └── main.rs /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | - [ ] This Issue beining opend using the Latest version/commit available 11 | 12 | **Information (please complete the following information):** 13 | - OS: [e.g. Windows, Linux, Android...] 14 | - OS Version: [e.g. 10/11] 15 | - GPU: [e.g. AMD 7700XT] 16 | - GPU Driver: [e.g. Mesa 24.1.4] 17 | 18 | **Describe the bug** 19 | 20 | 21 | **To Reproduce** 22 | 23 | 24 | **Expected behavior** 25 | 26 | 27 | **Screenshots** 28 | 29 | 30 | **Additional context** 31 | 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 2 | 3 | version: 2 4 | updates: 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "daily" 9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Pull Request Checklist 2 | 3 | - [ ] I have tested all platforms that were changed 4 | - [ ] I have updated the documentation (if applicable) 5 | - [ ] I have added tests (if applicable) 6 | 7 | ## Pre-merge checklist 8 | 9 | Before merging, please make sure that the following commands have been run: 10 | 11 | - [ ] `cargo clippy --fix` 12 | - [ ] `cargo fmt` 13 | 14 | ## Description 15 | 16 | Please provide a clear and concise description of the changes you have made, including any relevant context and background information. 17 | 18 | ## Related Issues 19 | 20 | If this pull request is related to any issues, please list them here. 21 | -------------------------------------------------------------------------------- /.github/workflows/pull_reqeust.yml: -------------------------------------------------------------------------------- 1 | name: Pull Reqeust 2 | 3 | on: 4 | pull_request: 5 | branches: [ "master" ] 6 | types: 7 | - labeled 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | if: ${{ github.event.label.name == 'rust' }} 15 | name: Rust 16 | uses: ./.github/workflows/rust.yml 17 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: ["master"] 6 | pull_request: 7 | branches: ["master"] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build-linux: 14 | name: Linux Build 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout repository 18 | uses: actions/checkout@v4 19 | - name: Install packages 20 | run: sudo apt update && sudo apt install -y libxkbcommon-dev 21 | - name: Setup Glsl 22 | uses: humbletim/setup-vulkan-sdk@v1.2.1 23 | with: 24 | vulkan-query-version: 1.3.204.0 25 | vulkan-components: Glslang 26 | vulkan-use-cache: true 27 | - name: Setup Rust toolchain 28 | uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 29 | - name: Run test 30 | run: cargo test 31 | build-windows: 32 | name: Windows Build 33 | runs-on: windows-latest 34 | steps: 35 | - name: Checkout repository 36 | uses: actions/checkout@v4 37 | - name: Prepare Vulkan SDK 38 | uses: humbletim/setup-vulkan-sdk@v1.2.1 39 | with: 40 | vulkan-query-version: 1.3.204.0 41 | vulkan-components: Glslang 42 | vulkan-use-cache: true 43 | - name: Setup Rust toolchain 44 | uses: actions-rust-lang/setup-rust-toolchain@v1.12.0 45 | - name: Run test 46 | run: cargo test 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */target 2 | 3 | /.idea 4 | 5 | /.vscode 6 | 7 | *.spv 8 | 9 | 10 | # Added by cargo 11 | 12 | /target 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/.gitmodules -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | lilalexmed@proton.me. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to Vent Engine 2 | 3 | You're interested in contributing to Vent Engine?, This guide outlines the process for submitting code contributions and participating in the project. 4 | 5 | ## Getting Started 6 | 7 | - **Fork the Repository: Create a fork of the Vent Engine repository on GitHub.** 8 | - **Clone your Fork: Clone your forked repository to your local machine.** 9 | - **Create a Branch: Create a new branch for your contribution. Use a descriptive branch name that reflects your changes.** 10 | - **Install the Rust programming Language at [here](https://www.rust-lang.org/tools/install)** 11 | 12 | ## Making Changes 13 | 14 | - **[Install Dependencies](#install-dependencies): Make sure you have all the necessary dependencies installed to build and run Vent Engine** 15 | - **Code Style: Follow the existing code style conventions used in the project. This ensures consistent and maintainable code.** 16 | - **Write Clean Code: Write clear, concise, and well-documented code.** 17 | 18 | ## Submitting your Contribution 19 | 20 | - **Make sure your Code does Compile fine** 21 | - **Run `cargo fmt`** 22 | - **Fix any warnings your change produced when running `cargo check`.** 23 | - **Commit Changes: Commit your changes with informative commit messages that describe the purpose of your modifications.** 24 | - **Push your Branch: Push your branch to your forked repository on GitHub.** 25 | - **Create a Pull Request: Create a pull request from your branch to the main branch of the upstream Vent Engine repository.** 26 | 27 | ## Install Dependencies 28 | 29 | **For all Platforms you will need to install the [Vulkan SDK](https://vulkan.lunarg.com/sdk/home)** 30 | 31 | - [Windows](#windows) 32 | - [Linux](#linux) 33 | 34 | ### Windows 35 | 36 | - Windows SDK (Note: usually comes in Visual Studio Installer when installing Rust) 37 | 38 | ### Linux 39 | 40 | - Wayland (or XWayland) 41 | - xkbcommon (libxkbcommon) 42 | 43 | ## Additional Notes 44 | 45 | - Issues: Feel free to create issues on the GitHub repository for bugs, feature requests, or discussions. 46 | - Community: We encourage you to participate in the community discussions and help others using Vent Engine. 47 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "crates/*", 5 | "test/*"] 6 | 7 | [workspace.package] 8 | version = "0.1.0" 9 | edition = "2021" 10 | 11 | [profile.release] 12 | lto = true 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # Vent-Engine 4 | 5 | **A game engine written in Rust with the goal to be very fast & user-friendly** 6 | 7 | ![CI](https://github.com/Snowiiii/Vent-Engine/actions/workflows/rust.yml/badge.svg) 8 | ![Apache_2.0](https://img.shields.io/badge/license-Apache_2.0-blue.svg) 9 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/f9d502f771314c628eee53e1369c750a)](https://app.codacy.com/gh/Snowiiii/Vent-Engine/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) 10 | 11 |
12 | 13 | ### 🏆 Goals 14 | 15 | - **Built in Rust:** This engine leverages the power of Rust and avoids external language bindings as much as possible. 16 | - **Performance Optimization:** Vulkan is used for top-tier performance through native APIs. 17 | - **User-Friendly Design:** The engine prioritizes ease of use. 18 | - **Cross-Platform Support:** One goal of the engine is to support various platforms ([Platforms](#platforms)). 19 | 20 | ### 🏗 Current Status 21 | Vent-Engine is currently in heavy development, Here is how it currently looks: 22 | ![image](https://github.com/user-attachments/assets/fbcc183c-a189-4dc1-991c-caa8a22ad47e) 23 | **(27.07.2024)** 24 | 25 | ### How to run? 26 | This section explains how to compile and run the Vent Engine from source code. Since it's under heavy development, there are currently no pre-built releases available. 27 | 28 | #### Prerequisites: 29 | - **Rust compiler**: Download and install Rust from the official website: https://www.rust-lang.org/tools/install 30 | - **Vulkan-compatible GPU** The Vent Engine utilizes Vulkan for graphics rendering. You'll need a graphics card that supports Vulkan 31 | #### Steps: 32 | 1. **Clone the repository:** 33 | `git clone https://github.com/ventengine/Vent-Engine.git` 34 | 2. **Compile & Run:** 35 | `cargo run --bin vent-runtime` 36 | 37 | 38 | ### How to contribute? 39 | 40 | Contributions are welcome in any way, shape, or form. See [Contributing](CONTRIBUTING.md) to know how you can get started. 41 | 42 | ### 🎮 Platforms 43 | 44 | Vent-Engine Platform Support: 45 | 46 | | Platform | Runtime | Editor | 47 | | -------- | ------- | ------ | 48 | | Windows | ✅️ | **❓** | 49 | | MacOS | **❓** | **❓** | 50 | | Linux | ✅️ | **❓** | 51 | | Redox | **❓** | **❓** | 52 | | VR | **❓** | ❌ | 53 | | Android | **❓** | ❌ | 54 | | IOS | **❓** | ❌ | 55 | | WASM | **❓** | ❌ | 56 | 57 | - ✅: Works as intended 58 | - ❌ Will not be Supported 59 | - 😬: Mostly works but Unstable 60 | - ❓: Unknown status 61 | 62 | ### 📝 License 63 | 64 | Vent-Engine uses the [Apache 2.0 License](LICENSE) 65 | -------------------------------------------------------------------------------- /crates/vent-assets/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-assets" 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 | vent-sdk = { path = "../vent-sdk" } 10 | vent-rendering = { path = "../vent-rendering"} 11 | 12 | ordered-float = "4.3.0" 13 | 14 | image = "0.25" 15 | 16 | log = "0.4" 17 | 18 | ash = { version= "0.38", default-features = false } 19 | 20 | # model is development and we often need features/changes which are not published yet 21 | modelz = { git = "https://github.com/ventengine/Modelz.git" } 22 | 23 | -------------------------------------------------------------------------------- /crates/vent-assets/README.md: -------------------------------------------------------------------------------- 1 | ### Vent-Assets 2 | 3 | We using our [Modelz](https://github.com/ventengine/Modelz) Library for Loading Models 4 | 5 | ## Contributing 6 | 7 | See [Contributing](../../CONTRIBUTING.md) 8 | 9 | ## License 10 | 11 | Vent-Assets is licensed under the [Apache 2.0 License](../../LICENSE) 12 | -------------------------------------------------------------------------------- /crates/vent-assets/src/image.rs: -------------------------------------------------------------------------------- 1 | pub struct Image {} 2 | 3 | impl Image {} 4 | -------------------------------------------------------------------------------- /crates/vent-assets/src/io/file.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | env, 3 | path::{Path, PathBuf}, 4 | }; 5 | 6 | pub(crate) fn get_base_path() -> PathBuf { 7 | if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") { 8 | PathBuf::from(manifest_dir) 9 | } else { 10 | env::current_exe() 11 | .map(|path| path.parent().map(ToOwned::to_owned).unwrap()) 12 | .unwrap() 13 | } 14 | } 15 | 16 | /// I/O implementation for the local filesystem. 17 | /// 18 | /// This asset I/O is fully featured but it's not available on `android` and `wasm` targets. 19 | #[allow(dead_code)] 20 | pub struct FileAsset { 21 | root_path: PathBuf, 22 | } 23 | #[allow(dead_code)] 24 | impl FileAsset { 25 | pub fn new>(path: P) -> Self { 26 | let root_path = get_base_path().join(path.as_ref()); 27 | Self { root_path } 28 | } 29 | 30 | pub fn root_path(&self) -> &PathBuf { 31 | &self.root_path 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /crates/vent-assets/src/io/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use crate::image::Image; 4 | 5 | pub mod file; 6 | 7 | pub struct AssetsLoader { 8 | _image_cache: HashMap, 9 | } 10 | 11 | impl Default for AssetsLoader { 12 | fn default() -> Self { 13 | Self::new() 14 | } 15 | } 16 | 17 | impl AssetsLoader { 18 | pub fn new() -> Self { 19 | Self { 20 | _image_cache: HashMap::new(), 21 | } 22 | } 23 | 24 | // pub fn get_image(&mut self, device: &ash::Device, path: String) -> vk::Sampler { 25 | // let vk = info.to_vk(); 26 | // *self.sampler_cache.entry(info).or_insert({ 27 | 28 | // unsafe { device.create_sampler(&vk, None) }.unwrap() 29 | // }) 30 | // } 31 | } 32 | -------------------------------------------------------------------------------- /crates/vent-assets/src/lib.rs: -------------------------------------------------------------------------------- 1 | use ash::vk::{self}; 2 | use modelz::AlphaMode; 3 | use vent_rendering::{image::VulkanImage, mesh::Mesh3D}; 4 | 5 | mod image; 6 | pub mod io; 7 | pub mod model; 8 | 9 | pub trait Asset: Send + Sync + 'static {} 10 | 11 | /// A Full Model/Scene that can be Loaded from a 3D Model File 12 | /// This is done by Parsing all Essensial Informations like Vertices, Indices, Materials & More 13 | pub struct Model3D { 14 | pub pipelines: Vec, 15 | pub materials: Vec, 16 | 17 | pub descriptor_pool: vk::DescriptorPool, 18 | 19 | pub position: [f32; 3], // Default: 0.0, 0.0, 0.0 20 | pub rotation: [f32; 4], // Default: 0.0, 0.0, 0.0, 1.0 21 | pub scale: [f32; 3], // Default: 1.0, 1.0, 1.0 22 | } 23 | 24 | /// Often we must create new Pipelines for Materials/Meshes 25 | pub struct ModelPipeline { 26 | pub pipeline: vk::Pipeline, 27 | pub materials: Vec, 28 | } 29 | 30 | pub struct ModelMaterial { 31 | pub material_index: usize, 32 | // So every App is Specfic and you will need to create your own DescriptorSet's out of this 33 | // We only binding them 34 | pub meshes: Vec, 35 | } 36 | 37 | pub struct Material { 38 | pub diffuse_texture: VulkanImage, 39 | pub descriptor_set: Option>, 40 | pub base_color: [f32; 4], 41 | pub alpha_mode: AlphaMode, 42 | pub double_sided: bool, 43 | pub alpha_cut: f32, 44 | } 45 | -------------------------------------------------------------------------------- /crates/vent-assets/src/model/mod.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use ash::vk; 4 | use loader::ModelLoader; 5 | use vent_rendering::instance::VulkanInstance; 6 | use vent_sdk::utils::stopwatch::Stopwatch; 7 | 8 | use crate::Model3D; 9 | 10 | mod loader; 11 | mod optimizer; 12 | 13 | impl Model3D { 14 | #[inline] 15 | pub async fn load>( 16 | instance: &mut VulkanInstance, 17 | vertex_shader: P, 18 | fragment_shader: P, 19 | pipeline_layout: vk::PipelineLayout, 20 | path: P, 21 | ) -> Self { 22 | let sw = Stopwatch::new_and_start(); 23 | let model = modelz::Model3D::load(path.as_ref()).expect("Failed to Load 3D Model"); 24 | let model = ModelLoader::load( 25 | instance, 26 | vertex_shader.as_ref(), 27 | fragment_shader.as_ref(), 28 | pipeline_layout, 29 | model, 30 | ) 31 | .await; 32 | log::info!( 33 | "Model {} took {}ms to Load, {} Pipelines, {} Materials", 34 | path.as_ref().display(), 35 | sw.elapsed_ms(), 36 | model.pipelines.len(), 37 | model.materials.len(), 38 | ); 39 | model 40 | } 41 | 42 | /// So your ideal render loop would be 43 | /// 44 | /// For each pipeline 45 | /// Set pipeline 46 | /// For each material that uses pipeline 47 | /// Set material bind group 48 | /// For each primitive that uses material with pipeline 49 | /// Draw primitive 50 | pub fn draw( 51 | &self, 52 | device: &ash::Device, 53 | pipeline_layout: vk::PipelineLayout, 54 | command_buffer: vk::CommandBuffer, 55 | buffer_index: usize, 56 | with_descriptor_set: bool, 57 | ) { 58 | self.pipelines.iter().for_each(|pipeline| { 59 | unsafe { 60 | device.cmd_bind_pipeline( 61 | command_buffer, 62 | vk::PipelineBindPoint::GRAPHICS, 63 | pipeline.pipeline, 64 | ) 65 | } 66 | pipeline.materials.iter().for_each(|material| { 67 | if with_descriptor_set { 68 | let material = &self.materials[material.material_index]; 69 | if let Some(ds) = &material.descriptor_set { 70 | unsafe { 71 | device.cmd_bind_descriptor_sets( 72 | command_buffer, 73 | vk::PipelineBindPoint::GRAPHICS, 74 | pipeline_layout, 75 | 0, 76 | &ds[buffer_index..=buffer_index], 77 | &[], 78 | ) 79 | } 80 | } 81 | } 82 | material.meshes.iter().for_each(|mesh| { 83 | // rpass.push_debug_group("Bind Mesh"); 84 | mesh.bind(device, command_buffer); 85 | // rpass.pop_debug_group(); 86 | // rpass.insert_debug_marker("Draw!"); 87 | mesh.draw(device, command_buffer); 88 | }); 89 | }); 90 | }) 91 | } 92 | 93 | pub fn destroy(&mut self, device: &ash::Device) { 94 | self.materials.drain(..).for_each(|mut material| { 95 | material.diffuse_texture.destroy(device); 96 | }); 97 | self.pipelines.drain(..).for_each(|mut pipeline| { 98 | unsafe { device.destroy_pipeline(pipeline.pipeline, None) }; 99 | pipeline.materials.drain(..).for_each(|mut model_material| { 100 | model_material.meshes.drain(..).for_each(|mut mesh| { 101 | mesh.destroy(device); 102 | }); 103 | }); 104 | }); 105 | // We are getting an Validation error when we try to free an descriptor set, They will all automatily freed when the Descriptor pool is destroyed 106 | unsafe { device.destroy_descriptor_pool(self.descriptor_pool, None) }; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /crates/vent-assets/src/model/optimizer.rs: -------------------------------------------------------------------------------- 1 | use vent_rendering::vertex::Vertex3D; 2 | 3 | #[allow(dead_code)] 4 | pub fn optimize_vertices(_vertices: Vec) -> Vec { 5 | Vec::new() 6 | } 7 | -------------------------------------------------------------------------------- /crates/vent-ecs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-ecs" 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] -------------------------------------------------------------------------------- /crates/vent-ecs/README.md: -------------------------------------------------------------------------------- 1 | ### Vent-ECS 2 | 3 | Vent-ECS is a lightweight and 4 | flexible [Entity Component System](https://en.wikipedia.org/wiki/Entity_component_system) (ECS) library designed for 5 | game development in Rust. It allows game developers to create entities and components, and easily handle their 6 | relationships and interactions with each other. 7 | 8 | ### 🏆 Goals 9 | 10 | - Lightweight and fast 11 | - Flexible and customizable 12 | - Supports both single-threaded and multi-threaded systems 13 | - Designed to be used with the Vent Engine but can be used independently in other Rust projects 14 | 15 | ## Contributing 16 | 17 | See [Contributing](../../CONTRIBUTING.md) 18 | 19 | ## License 20 | 21 | Vent-ECS is licensed under the [Apache 2.0 License](../../LICENSE) 22 | -------------------------------------------------------------------------------- /crates/vent-ecs/src/archetype.rs: -------------------------------------------------------------------------------- 1 | use std::{any::Any, collections::HashMap}; 2 | 3 | use crate::{component::Component, entity::Entity}; 4 | 5 | pub struct Archetype { 6 | entities: Vec, 7 | component_data: HashMap>>, 8 | } 9 | 10 | impl Archetype { 11 | /// Creates a new empty archetype. 12 | pub fn new() -> Self { 13 | Archetype { 14 | entities: Vec::new(), 15 | component_data: HashMap::new(), 16 | } 17 | } 18 | 19 | /// Adds an entity to the archetype. 20 | pub fn add_entity(&mut self, entity: Entity) { 21 | self.entities.push(entity); 22 | } 23 | 24 | /// Removes an entity from the archetype. 25 | pub fn remove_entity(&mut self, entity: Entity) { 26 | if let Some(index) = self.entities.iter().position(|&e| e == entity) { 27 | self.entities.swap_remove(index); 28 | } 29 | } 30 | 31 | /// Adds a component to the archetype. 32 | pub fn add_component(&mut self, component_id: usize, component: T) { 33 | let component_data = self.component_data.entry(component_id).or_default(); 34 | component_data.push(Box::new(component)); 35 | } 36 | 37 | /// Removes a component from the archetype. 38 | pub fn remove_component(&mut self, component_id: usize, entity: Entity) { 39 | if let Some(component_data) = self.component_data.get_mut(&component_id) { 40 | if let Some(index) = self.entities.iter().position(|&e| e == entity) { 41 | component_data.swap_remove(index); 42 | } 43 | } 44 | } 45 | 46 | /// Retrieves a component from the archetype. 47 | pub fn get_component(&self, component_id: usize, entity: Entity) -> Option<&T> { 48 | if let Some(component_data) = self.component_data.get(&component_id) { 49 | if let Some(index) = self.entities.iter().position(|&e| e == entity) { 50 | if let Some(component) = component_data[index].downcast_ref::() { 51 | return Some(component); 52 | } 53 | } 54 | } 55 | None 56 | } 57 | 58 | /// Retrieves a mutable component from the archetype. 59 | pub fn get_component_mut( 60 | &mut self, 61 | component_id: usize, 62 | entity: Entity, 63 | ) -> Option<&mut T> { 64 | if let Some(component_data) = self.component_data.get_mut(&component_id) { 65 | if let Some(index) = self.entities.iter().position(|&e| e == entity) { 66 | if let Some(component) = component_data[index].downcast_mut::() { 67 | return Some(component); 68 | } 69 | } 70 | } 71 | None 72 | } 73 | 74 | /// Returns an iterator over the entities in the archetype. 75 | #[allow(dead_code)] 76 | pub fn iter_entities(&self) -> impl Iterator { 77 | self.entities.iter() 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /crates/vent-ecs/src/component/input_component.rs: -------------------------------------------------------------------------------- 1 | #[allow(dead_code)] 2 | pub trait InputComponent { 3 | // fn process_keyboard(&mut self, key: keyboard::Key, state: ElementState); 4 | 5 | fn process_mouse_motion(&mut self, mouse_dx: f64, mouse_dy: f64); 6 | } 7 | -------------------------------------------------------------------------------- /crates/vent-ecs/src/component/mod.rs: -------------------------------------------------------------------------------- 1 | use std::any::Any; 2 | 3 | mod input_component; 4 | 5 | /// The `Component` trait represents a component in an ECS. 6 | pub trait Component: Any + 'static {} 7 | 8 | // Soon ... 9 | -------------------------------------------------------------------------------- /crates/vent-ecs/src/entity/mod.rs: -------------------------------------------------------------------------------- 1 | /// The `Entity` type represents an entity in an ECS. 2 | pub type Entity = u32; 3 | 4 | // Soon ... 5 | -------------------------------------------------------------------------------- /crates/vent-ecs/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod archetype; 2 | pub mod component; 3 | pub mod entity; 4 | pub mod world; 5 | -------------------------------------------------------------------------------- /crates/vent-ecs/src/world/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | /// The `World` struct represents the game world. 4 | use crate::{archetype::Archetype, component::Component, entity::Entity}; 5 | 6 | pub struct World { 7 | entities: Vec, 8 | next_entity: Entity, 9 | archetypes: HashMap, Archetype>, 10 | component_ids: HashMap, 11 | } 12 | 13 | impl World { 14 | pub fn new() -> Self { 15 | World { 16 | entities: Vec::new(), 17 | next_entity: 0, 18 | archetypes: HashMap::new(), 19 | component_ids: HashMap::new(), 20 | } 21 | } 22 | 23 | /// Creates a new entity in the world and returns its entity ID. 24 | pub fn create_entity(&mut self) -> Entity { 25 | let entity = self.next_entity; 26 | self.next_entity += 1; 27 | self.entities.push(entity); 28 | entity 29 | } 30 | 31 | /// Deletes an entity from the world. 32 | pub fn delete_entity(&mut self, entity: Entity) -> Result<(), String> { 33 | if let Some(index) = self.entities.iter().position(|&e| e == entity) { 34 | self.entities.swap_remove(index); 35 | self.archetypes.values_mut().for_each(|archetype| { 36 | archetype.remove_entity(entity); 37 | }); 38 | Ok(()) 39 | } else { 40 | Err(format!("Entity with ID {} does not exist", entity)) 41 | } 42 | } 43 | 44 | /// Registers a component type in the world and returns its component ID. 45 | pub fn register_component(&mut self) -> usize { 46 | let component_name = std::any::type_name::().to_owned(); 47 | let component_id = self.component_ids.len(); 48 | self.component_ids.insert(component_name, component_id); 49 | component_id 50 | } 51 | 52 | /// Adds a component to an entity in the world. 53 | pub fn add_component( 54 | &mut self, 55 | entity: Entity, 56 | component: T, 57 | ) -> Result<(), String> { 58 | let component_id = self.component_ids.get(std::any::type_name::()); 59 | if let Some(&component_id) = component_id { 60 | let archetype_key = vec![component_id]; 61 | if let Some(archetype) = self.archetypes.get_mut(&archetype_key) { 62 | archetype.add_entity(entity); 63 | archetype.add_component(component_id, component); 64 | return Ok(()); 65 | } else { 66 | let mut archetype = Archetype::new(); 67 | archetype.add_entity(entity); 68 | archetype.add_component(component_id, component); 69 | self.archetypes.insert(archetype_key, archetype); 70 | return Ok(()); 71 | } 72 | } 73 | Err(format!( 74 | "Component type not registered: {}", 75 | std::any::type_name::() 76 | )) 77 | } 78 | 79 | /// Removes a component from an entity in the world. 80 | pub fn remove_component( 81 | &mut self, 82 | entity: Entity, 83 | ) -> Result<(), String> { 84 | let component_id = self.component_ids.get(std::any::type_name::()); 85 | if let Some(&component_id) = component_id { 86 | let archetype_key = vec![component_id]; 87 | if let Some(archetype) = self.archetypes.get_mut(&archetype_key) { 88 | archetype.remove_entity(entity); 89 | archetype.remove_component(component_id, entity); 90 | return Ok(()); 91 | } 92 | } 93 | Err(format!( 94 | "Component type not registered: {}", 95 | std::any::type_name::() 96 | )) 97 | } 98 | 99 | /// Retrieves a component by its component ID and entity ID. 100 | pub fn get_component(&self, entity: Entity) -> Result<&T, String> { 101 | let component_id = self.component_ids.get(std::any::type_name::()); 102 | if let Some(&component_id) = component_id { 103 | let archetype_key = vec![component_id]; 104 | if let Some(archetype) = self.archetypes.get(&archetype_key) { 105 | if let Some(component) = archetype.get_component::(component_id, entity) { 106 | return Ok(component); 107 | } 108 | } 109 | } 110 | Err(format!( 111 | "Component not found for entity ID {}: {}", 112 | entity, 113 | std::any::type_name::() 114 | )) 115 | } 116 | 117 | /// Retrieves a mutable component by its component ID and entity ID. 118 | pub fn get_component_mut( 119 | &mut self, 120 | entity: Entity, 121 | ) -> Result<&mut T, String> { 122 | let component_id = self.component_ids.get(std::any::type_name::()); 123 | if let Some(&component_id) = component_id { 124 | let archetype_key = vec![component_id]; 125 | if let Some(archetype) = self.archetypes.get_mut(&archetype_key) { 126 | if let Some(component) = archetype.get_component_mut::(component_id, entity) { 127 | return Ok(component); 128 | } 129 | } 130 | } 131 | Err(format!( 132 | "Component not found for entity ID {}: {}", 133 | entity, 134 | std::any::type_name::() 135 | )) 136 | } 137 | 138 | /// Returns an iterator over the entities in the world. 139 | pub fn iter_entities(&self) -> impl Iterator { 140 | self.entities.iter() 141 | } 142 | } 143 | 144 | impl Default for World { 145 | fn default() -> Self { 146 | Self::new() 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /crates/vent-editor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-editor" 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 | vent-runtime = { path = "../vent-runtime"} 10 | 11 | vent-rendering = { path = "../vent-rendering"} 12 | 13 | ash = { version= "0.38", default-features = false, features = ["loaded"] } 14 | 15 | pollster = "0.3.0" 16 | 17 | log = "0.4" 18 | 19 | # rfd = { version="0.12.1", default-features = false, features = ["xdg-portal"]} 20 | 21 | -------------------------------------------------------------------------------- /crates/vent-editor/README.md: -------------------------------------------------------------------------------- 1 | ### Vent-Editor 2 | 3 | The Vent-Editor is the tool which Allows developers to build 2D or 3D games in an simple GUI. And than later running the Games in the Vent-Runtime 4 | 5 | ## Contributing 6 | 7 | If you're interested in contributing to Vent-Editor, please fork the repository and submit a pull request. We welcome 8 | contributions of all kinds, including bug fixes, new features, and documentation improvements. 9 | 10 | ## License 11 | 12 | Vent-Editor is licensed under the [Apache 2.0 License](../../LICENSE) 13 | -------------------------------------------------------------------------------- /crates/vent-editor/src/gui/mod.rs: -------------------------------------------------------------------------------- 1 | use egui::epaint::ahash::{HashSet, HashSetExt}; 2 | use egui::{CentralPanel, Color32, Frame, RichText, TopBottomPanel, Ui, WidgetText}; 3 | use egui_dock::{DockArea, DockState, Node, NodeIndex, TabViewer}; 4 | use vent_runtime::render::gui::debug_gui::RenderData; 5 | use vent_runtime::render::gui::GUI; 6 | 7 | pub(crate) struct EditorViewer { 8 | open_tabs: HashSet, 9 | } 10 | 11 | impl TabViewer for EditorViewer { 12 | type Tab = String; 13 | 14 | #[allow(clippy::single_match)] 15 | fn ui(&mut self, ui: &mut Ui, tab: &mut Self::Tab) { 16 | match tab.as_str() { 17 | "Console" => self.view_console(ui), 18 | _ => {} 19 | } 20 | } 21 | 22 | fn title(&mut self, tab: &mut Self::Tab) -> WidgetText { 23 | tab.as_str().into() 24 | } 25 | 26 | fn on_close(&mut self, tab: &mut Self::Tab) -> bool { 27 | self.open_tabs.remove(tab); 28 | true 29 | } 30 | } 31 | 32 | impl EditorViewer { 33 | // TODO: 34 | fn view_console(&self, ui: &mut Ui) { 35 | ui.horizontal(|ui| { 36 | ui.label(RichText::new("[ERROR]: UwU Just a Joke, Its Rust :D").color(Color32::RED)); 37 | }); 38 | } 39 | 40 | fn view_tab_file(&self, ui: &mut Ui, _tree: &mut DockState) { 41 | for tab in &["New Project", "Open Project"] { 42 | if ui 43 | .selectable_label(self.open_tabs.contains(*tab), *tab) 44 | .clicked() 45 | { 46 | ui.close_menu(); 47 | todo!(); 48 | } 49 | } 50 | } 51 | } 52 | 53 | pub(crate) struct EditorGUI { 54 | tree: DockState, 55 | viewer: EditorViewer, 56 | } 57 | 58 | impl GUI for EditorGUI { 59 | fn update(&mut self, ctx: &egui::Context, _render_data: &RenderData) { 60 | TopBottomPanel::top("vent::MenuBar").show(ctx, |ui| { 61 | egui::menu::bar(ui, |ui| { 62 | ui.menu_button("File", |ui| { 63 | self.viewer.view_tab_file(ui, &mut self.tree); 64 | }) 65 | }) 66 | }); 67 | CentralPanel::default() 68 | .frame(Frame::central_panel(&ctx.style()).inner_margin(0.)) 69 | .show(ctx, |ui| { 70 | DockArea::new(&mut self.tree).show_inside(ui, &mut self.viewer); 71 | }); 72 | } 73 | } 74 | 75 | impl EditorGUI { 76 | pub fn new() -> Self { 77 | let mut state = DockState::new(vec!["Vent-Engine Placeholder".to_owned()]); 78 | let tree = state.main_surface_mut(); 79 | let [a, _] = tree.split_left(NodeIndex::root(), 0.3, vec!["Files".to_owned()]); 80 | let [_, _] = tree.split_below(a, 0.6, vec!["Console".to_owned()]); 81 | 82 | let mut open_tabs = HashSet::new(); 83 | 84 | tree.iter().for_each(|node| { 85 | if let Node::Leaf { tabs, .. } = node { 86 | tabs.iter().for_each(|tab| { 87 | open_tabs.insert(tab.clone()); 88 | }); 89 | } 90 | }); 91 | 92 | let viewer = EditorViewer { open_tabs }; 93 | 94 | Self { 95 | tree: state, 96 | viewer, 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /crates/vent-editor/src/main.rs: -------------------------------------------------------------------------------- 1 | // use crate::render::EditorRenderer; 2 | 3 | // use vent_common::util::crash::init_panic_hook; 4 | // use vent_common::window::VentWindow; 5 | // use vent_runtime::render::camera::{Camera, Camera3D}; 6 | 7 | // use winit::event::{Event, WindowEvent}; 8 | // use winit::window::WindowBuilder; 9 | 10 | // mod gui; 11 | // mod render; 12 | 13 | // fn main() { 14 | // init_panic_hook(); 15 | // #[cfg(not(target_arch = "wasm32"))] 16 | // { 17 | // SimpleLogger::new() 18 | // .with_level(log::LevelFilter::Info) 19 | // .init() 20 | // .unwrap(); 21 | // }; 22 | 23 | // let window_builder = WindowBuilder::new() 24 | // .with_title(format!("Vent-Editor v{}", env!("CARGO_PKG_VERSION"))) 25 | // .with_inner_size(winit::dpi::LogicalSize::new(1400.0, 800.0)); 26 | // // TODO 27 | // // .with_window_icon(Some(VentWindow::load_icon(path))); 28 | // let vent_window = VentWindow::new(window_builder); 29 | 30 | // let mut camera = Camera3D::new(); 31 | 32 | // let mut renderer = 33 | // EditorRenderer::new(&vent_window.window, &vent_window.event_loop, &mut camera); 34 | // vent_window 35 | // .event_loop 36 | // .run(move |event, elwt| { 37 | // match event { 38 | // Event::WindowEvent { 39 | // ref event, 40 | // window_id, 41 | // } if window_id == vent_window.window.id() => { 42 | // renderer.egui.progress_event(event); 43 | // match event { 44 | // WindowEvent::CloseRequested => elwt.exit(), 45 | // WindowEvent::Resized(physical_size) => { 46 | // renderer.resize(physical_size, &mut camera); 47 | // } 48 | // WindowEvent::RedrawRequested => { 49 | // renderer.render(&vent_window.window, &mut camera); 50 | // } 51 | // // WindowEvent::ScaleFactorChanged { new_inner_size, .. } => { 52 | // // // new_inner_size is &mut so w have to dereference it twice 53 | // // renderer.resize(new_inner_size, &mut camera); 54 | // // } 55 | // _ => {} 56 | // } 57 | // } 58 | // // ... 59 | // _ => {} 60 | // } 61 | // }) 62 | // .expect("Window Event Loop Error"); 63 | // } 64 | 65 | fn main() {} 66 | -------------------------------------------------------------------------------- /crates/vent-editor/src/render/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::gui::EditorGUI; 2 | use crate::render::runtime_renderer::EditorRuntimeRenderer; 3 | use ash::vk; 4 | use vent_rendering::instance::VulkanInstance; 5 | use vent_runtime::render::camera::Camera; 6 | use vent_runtime::render::gui::debug_gui::RenderData; 7 | use vent_runtime::render::gui::gui_renderer::EguiRenderer; 8 | use vent_runtime::render::Dimension; 9 | 10 | mod runtime_renderer; 11 | 12 | pub struct EditorRenderer { 13 | instance: VulkanInstance, 14 | pub egui: EguiRenderer, 15 | 16 | editor_runtime_renderer: EditorRuntimeRenderer, 17 | } 18 | 19 | impl EditorRenderer { 20 | pub fn new( 21 | window: &winit::window::Window, 22 | event_loop: &winit::event_loop::EventLoopWindowTarget<()>, 23 | camera: &mut dyn Camera, 24 | ) -> Self { 25 | let instance = VulkanInstance::new("Vent-Engine Editor", window); 26 | let egui = EguiRenderer::new().add_gui(Box::new(EditorGUI::new())); 27 | 28 | let editor_runtime_renderer = EditorRuntimeRenderer::new( 29 | &instance, 30 | Dimension::D3, 31 | // TODO 32 | event_loop, 33 | vk::Extent2D { 34 | width: 1, 35 | height: 1, 36 | }, // TODO 37 | camera, 38 | ); 39 | 40 | Self { 41 | instance, 42 | egui, 43 | editor_runtime_renderer, 44 | } 45 | } 46 | 47 | pub fn render(&mut self, window: &winit::window::Window, camera: &mut dyn Camera) { 48 | self.egui.render(&RenderData::default()); 49 | 50 | self.editor_runtime_renderer 51 | .render(&self.instance, window, camera); 52 | } 53 | 54 | pub fn resize(&mut self, new_size: &winit::dpi::PhysicalSize, camera: &mut dyn Camera) { 55 | // TODO 56 | self.editor_runtime_renderer 57 | .resize(&self.instance, new_size, camera); 58 | // egui does resize using Window Events 59 | } 60 | 61 | pub fn resize_current(&mut self, camera: &mut dyn Camera) { 62 | let size = winit::dpi::PhysicalSize { 63 | width: 1, 64 | height: 1, 65 | }; // TODO 66 | Self::resize(self, &size, camera) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /crates/vent-editor/src/render/runtime_renderer.rs: -------------------------------------------------------------------------------- 1 | use ash::vk; 2 | use vent_rendering::instance::VulkanInstance; 3 | use vent_runtime::render::Dimension; 4 | use vent_runtime::render::{camera::Camera, RawRuntimeRenderer}; 5 | 6 | pub struct EditorRuntimeRenderer { 7 | runtime_renderer: RawRuntimeRenderer, 8 | } 9 | 10 | impl EditorRuntimeRenderer { 11 | pub fn new( 12 | instance: &VulkanInstance, 13 | dimension: Dimension, 14 | event_loop: &winit::event_loop::EventLoopWindowTarget<()>, 15 | _extent: vk::Extent2D, 16 | camera: &mut dyn Camera, 17 | ) -> Self { 18 | let runtime_renderer = RawRuntimeRenderer::new(dimension, instance, event_loop, camera); 19 | Self { 20 | runtime_renderer, 21 | // extent, 22 | } 23 | } 24 | 25 | pub fn render( 26 | &mut self, 27 | instance: &VulkanInstance, 28 | window: &winit::window::Window, 29 | camera: &mut dyn Camera, 30 | ) { 31 | // TODO: Get new image 32 | self.runtime_renderer.render(instance, window, camera); 33 | } 34 | 35 | pub fn resize( 36 | &mut self, 37 | _instance: &VulkanInstance, 38 | _new_size: &winit::dpi::PhysicalSize, 39 | _camera: &mut dyn Camera, 40 | ) { 41 | 42 | // TODO 43 | // self.runtime_renderer.resize(config, device, queue, camera); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /crates/vent-logging/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-logging" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [dependencies] 7 | log = { version="0.4", features = ["std"] } 8 | colored = "2.1.0" 9 | 10 | [target.'cfg(target_family = "wasm")'.dependencies] 11 | web-sys = { version = "0.3.70", features = ["console"] } 12 | 13 | [target.'cfg(target_os = "android")'.dependencies] 14 | ndk-sys = "0.6" -------------------------------------------------------------------------------- /crates/vent-logging/src/lib.rs: -------------------------------------------------------------------------------- 1 | use colored::Colorize; 2 | use log::{Level, LevelFilter, Log}; 3 | 4 | /// 5 | /// Cross Platform Logger 6 | /// 7 | pub struct Logger {} 8 | 9 | impl Logger { 10 | pub fn init() { 11 | log::set_max_level(LevelFilter::Debug); 12 | log::set_boxed_logger(Box::new(Self {})).expect("failed to set boxed logger"); 13 | } 14 | } 15 | 16 | impl Log for Logger { 17 | fn enabled(&self, _metadata: &log::Metadata) -> bool { 18 | true // TODO 19 | } 20 | 21 | fn log(&self, record: &log::Record) { 22 | // Default 23 | #[cfg(not(any(target_arch = "wasm32", target_os = "android")))] 24 | { 25 | let level = match record.level() { 26 | Level::Error => format!("{:<5}", record.level().as_str().red()), 27 | Level::Warn => format!("{:<5}", record.level().as_str().yellow()), 28 | Level::Info => format!("{:<5}", record.level().as_str().cyan()), 29 | Level::Debug => format!("{:<5}", record.level().as_str().purple()), 30 | Level::Trace => format!("{:<5}", record.level().as_str().normal()), 31 | }; 32 | println!("{} {} {}", level, record.target(), record.args()) 33 | } 34 | // Wasm 35 | #[cfg(target_family = "wasm")] 36 | { 37 | match record.level() { 38 | Level::Error => web_sys::console::error_1(&format!("{}", record.args()).into()), 39 | Level::Warn => web_sys::console::warn_1(&format!("{}", record.args()).into()), 40 | Level::Info => web_sys::console::info_1(&format!("{}", record.args()).into()), 41 | Level::Debug => web_sys::console::debug_1(&format!("{}", record.args()).into()), 42 | Level::Trace => web_sys::console::trace_1(&format!("{}", record.args()).into()), 43 | } 44 | // TODO 45 | } 46 | // Android 47 | #[cfg(target_os = "android")] 48 | { 49 | use std::ffi::{c_int, CStr, CString}; 50 | let prio = match record.level() { 51 | Level::Error => ndk_sys::android_LogPriority::ANDROID_LOG_ERROR, 52 | Level::Warn => ndk_sys::android_LogPriority::ANDROID_LOG_WARN, 53 | Level::Info => ndk_sys::android_LogPriority::ANDROID_LOG_INFO, 54 | Level::Debug => ndk_sys::android_LogPriority::ANDROID_LOG_DEBUG, 55 | Level::Trace => ndk_sys::android_LogPriority::ANDROID_LOG_VERBOSE, 56 | }; 57 | unsafe { 58 | ndk_sys::__android_log_write( 59 | prio.0 as c_int, 60 | CStr::from("").as_ptr(), 61 | record.args().as_ptr(), 62 | ); 63 | } 64 | } 65 | } 66 | 67 | fn flush(&self) {} 68 | } 69 | -------------------------------------------------------------------------------- /crates/vent-math/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-math" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /crates/vent-math/src/align16.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone, Copy, Default, PartialEq, PartialOrd)] 2 | #[repr(C, align(16))] 3 | pub(crate) struct Align16(pub T); 4 | 5 | impl Align16 { 6 | #[allow(dead_code)] 7 | pub fn as_ptr(&self) -> *const T { 8 | &self.0 9 | } 10 | 11 | #[allow(dead_code)] 12 | pub fn as_mut_ptr(&mut self) -> *mut T { 13 | &mut self.0 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/vent-math/src/deref.rs: -------------------------------------------------------------------------------- 1 | #[repr(C)] 2 | pub struct Vec4 { 3 | pub x: T, 4 | pub y: T, 5 | pub z: T, 6 | pub w: T, 7 | } 8 | -------------------------------------------------------------------------------- /crates/vent-math/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod align16; 2 | pub mod deref; 3 | pub mod scalar; 4 | pub mod vec; 5 | -------------------------------------------------------------------------------- /crates/vent-math/src/scalar/mat4.rs: -------------------------------------------------------------------------------- 1 | use std::ops::{Add, Mul, MulAssign, Sub}; 2 | 3 | use crate::vec::{vec3::Vec3, vec4::Vec4}; 4 | 5 | use super::quat::Quat; 6 | 7 | #[derive(Clone, Copy)] 8 | #[repr(C)] 9 | pub struct Mat4 { 10 | pub x_axis: Vec4, 11 | pub y_axis: Vec4, 12 | pub z_axis: Vec4, 13 | pub w_axis: Vec4, 14 | } 15 | 16 | impl Mat4 { 17 | pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W); 18 | 19 | #[allow(clippy::too_many_arguments)] 20 | #[allow(dead_code)] 21 | #[must_use] 22 | const fn new( 23 | m00: f32, 24 | m01: f32, 25 | m02: f32, 26 | m03: f32, 27 | m10: f32, 28 | m11: f32, 29 | m12: f32, 30 | m13: f32, 31 | m20: f32, 32 | m21: f32, 33 | m22: f32, 34 | m23: f32, 35 | m30: f32, 36 | m31: f32, 37 | m32: f32, 38 | m33: f32, 39 | ) -> Self { 40 | Self { 41 | x_axis: Vec4::new(m00, m01, m02, m03), 42 | y_axis: Vec4::new(m10, m11, m12, m13), 43 | z_axis: Vec4::new(m20, m21, m22, m23), 44 | w_axis: Vec4::new(m30, m31, m32, m33), 45 | } 46 | } 47 | 48 | #[must_use] 49 | pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self { 50 | Self { 51 | x_axis, 52 | y_axis, 53 | z_axis, 54 | w_axis, 55 | } 56 | } 57 | 58 | #[inline] 59 | #[must_use] 60 | fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) { 61 | let (x, y, z, w) = rotation.into(); 62 | let x2 = x + x; 63 | let y2 = y + y; 64 | let z2 = z + z; 65 | let xx = x * x2; 66 | let xy = x * y2; 67 | let xz = x * z2; 68 | let yy = y * y2; 69 | let yz = y * z2; 70 | let zz = z * z2; 71 | let wx = w * x2; 72 | let wy = w * y2; 73 | let wz = w * z2; 74 | 75 | let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0); 76 | let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0); 77 | let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0); 78 | (x_axis, y_axis, z_axis) 79 | } 80 | 81 | #[inline] 82 | #[must_use] 83 | pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self { 84 | let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation); 85 | Self::from_cols( 86 | x_axis.mul(scale.x), 87 | y_axis.mul(scale.y), 88 | z_axis.mul(scale.z), 89 | Vec4::from((translation, 1.0)), 90 | ) 91 | } 92 | 93 | #[inline] 94 | pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { 95 | Self::look_to_rh(eye, center.sub(eye), up) 96 | } 97 | 98 | #[inline] 99 | #[must_use] 100 | pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { 101 | let f = dir.normalize(); 102 | let s = f.cross(up).normalize(); 103 | let u = s.cross(f); 104 | 105 | Self::from_cols( 106 | Vec4::new(s.x, u.x, -f.x, 0.0), 107 | Vec4::new(s.y, u.y, -f.y, 0.0), 108 | Vec4::new(s.z, u.z, -f.z, 0.0), 109 | Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0), 110 | ) 111 | } 112 | 113 | #[inline] 114 | #[must_use] 115 | pub fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self { 116 | let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos(); 117 | let h = cos_fov / sin_fov; 118 | let w = h / aspect_ratio; 119 | let r = z_far / (z_near - z_far); 120 | Self::from_cols( 121 | Vec4::new(w, 0.0, 0.0, 0.0), 122 | Vec4::new(0.0, h, 0.0, 0.0), 123 | Vec4::new(0.0, 0.0, r, -1.0), 124 | Vec4::new(0.0, 0.0, r * z_near, 0.0), 125 | ) 126 | } 127 | 128 | #[inline] 129 | #[must_use] 130 | pub fn orthographic_rh( 131 | left: f32, 132 | right: f32, 133 | bottom: f32, 134 | top: f32, 135 | near: f32, 136 | far: f32, 137 | ) -> Self { 138 | let rcp_width = 1.0 / (right - left); 139 | let rcp_height = 1.0 / (top - bottom); 140 | let r = 1.0 / (near - far); 141 | Self::from_cols( 142 | Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), 143 | Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), 144 | Vec4::new(0.0, 0.0, r, 0.0), 145 | Vec4::new( 146 | -(left + right) * rcp_width, 147 | -(top + bottom) * rcp_height, 148 | r * near, 149 | 1.0, 150 | ), 151 | ) 152 | } 153 | 154 | #[inline] 155 | #[must_use] 156 | pub fn mul_mat4(&self, rhs: &Self) -> Self { 157 | Self::from_cols( 158 | self.mul(rhs.x_axis), 159 | self.mul(rhs.y_axis), 160 | self.mul(rhs.z_axis), 161 | self.mul(rhs.w_axis), 162 | ) 163 | } 164 | 165 | #[inline] 166 | #[must_use] 167 | pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 { 168 | let mut res = self.x_axis.mul(rhs.xxxx()); 169 | res = res.add(self.y_axis.mul(rhs.yyyy())); 170 | res = res.add(self.z_axis.mul(rhs.zzzz())); 171 | res = res.add(self.w_axis.mul(rhs.wwww())); 172 | res 173 | } 174 | } 175 | 176 | impl Mul for Mat4 { 177 | type Output = Self; 178 | #[inline] 179 | fn mul(self, rhs: Self) -> Self::Output { 180 | self.mul_mat4(&rhs) 181 | } 182 | } 183 | 184 | impl MulAssign for Mat4 { 185 | #[inline] 186 | fn mul_assign(&mut self, rhs: Self) { 187 | *self = self.mul_mat4(&rhs); 188 | } 189 | } 190 | 191 | impl Mul for Mat4 { 192 | type Output = Vec4; 193 | #[inline] 194 | fn mul(self, rhs: Vec4) -> Self::Output { 195 | self.mul_vec4(rhs) 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /crates/vent-math/src/scalar/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mat4; 2 | pub mod quat; 3 | -------------------------------------------------------------------------------- /crates/vent-math/src/scalar/quat.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | arch::x86_64::__m128, 3 | ops::{Deref, DerefMut}, 4 | }; 5 | 6 | use crate::vec::{vec3::Vec3, vec4::Vec4}; 7 | 8 | #[repr(C)] 9 | union UnionCast { 10 | a: [f32; 4], 11 | v: Quat, 12 | } 13 | 14 | #[derive(Clone, Copy)] 15 | #[repr(transparent)] 16 | pub struct Quat(pub(crate) __m128); 17 | 18 | impl Quat { 19 | #[allow(dead_code)] 20 | const ZERO: Self = Self::from_array([0.0; 4]); 21 | 22 | pub const IDENTITY: Self = Self::new(0.0, 0.0, 0.0, 1.0); 23 | 24 | pub const NAN: Self = Self::from_array([f32::NAN; 4]); 25 | 26 | #[inline(always)] 27 | #[must_use] 28 | pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self { 29 | unsafe { UnionCast { a: [x, y, z, w] }.v } 30 | } 31 | 32 | #[inline] 33 | #[must_use] 34 | pub const fn from_array(a: [f32; 4]) -> Self { 35 | Self::new(a[0], a[1], a[2], a[3]) 36 | } 37 | 38 | #[inline] 39 | #[must_use] 40 | pub fn xyz(self) -> Vec3 { 41 | Vec3::new(self.x, self.y, self.z) 42 | } 43 | 44 | #[inline] 45 | #[must_use] 46 | pub fn from_scaled_axis(v: Vec3) -> Self { 47 | let length = v.length(); 48 | if length == 0.0 { 49 | Self::IDENTITY 50 | } else { 51 | Self::from_axis_angle(v / length, length) 52 | } 53 | } 54 | 55 | pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self { 56 | let (s, c) = (angle * 0.5).sin_cos(); 57 | let v = axis * s; 58 | Self::new(v.x, v.y, v.z, c) 59 | } 60 | } 61 | 62 | impl From for Vec4 { 63 | #[inline] 64 | fn from(q: Quat) -> Self { 65 | Self(q.0) 66 | } 67 | } 68 | 69 | impl From for (f32, f32, f32, f32) { 70 | #[inline] 71 | fn from(q: Quat) -> Self { 72 | Vec4::from(q).into() 73 | } 74 | } 75 | 76 | impl From for [f32; 4] { 77 | #[inline] 78 | fn from(q: Quat) -> Self { 79 | Vec4::from(q).into() 80 | } 81 | } 82 | 83 | impl From for __m128 { 84 | #[inline] 85 | fn from(q: Quat) -> Self { 86 | q.0 87 | } 88 | } 89 | 90 | impl Deref for Quat { 91 | type Target = crate::deref::Vec4; 92 | #[inline] 93 | fn deref(&self) -> &Self::Target { 94 | unsafe { &*(self as *const Self).cast() } 95 | } 96 | } 97 | 98 | impl DerefMut for Quat { 99 | #[inline] 100 | fn deref_mut(&mut self) -> &mut Self::Target { 101 | unsafe { &mut *(self as *mut Self).cast() } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /crates/vent-math/src/vec/i32/ivec2.rs: -------------------------------------------------------------------------------- 1 | use std::ops::{Mul, MulAssign}; 2 | 3 | #[repr(C)] 4 | pub struct IVec2 { 5 | pub x: i32, 6 | pub y: i32, 7 | } 8 | 9 | impl IVec2 { 10 | /// All zeroes. 11 | pub const ZERO: Self = Self::splat(0); 12 | 13 | /// All ones. 14 | pub const ONE: Self = Self::splat(1); 15 | 16 | /// All negative ones. 17 | pub const NEG_ONE: Self = Self::splat(-1); 18 | 19 | /// All `i32::MIN`. 20 | pub const MIN: Self = Self::splat(i32::MIN); 21 | 22 | /// All `i32::MAX`. 23 | pub const MAX: Self = Self::splat(i32::MAX); 24 | 25 | /// A unit vector pointing along the positive X axis. 26 | pub const X: Self = Self::new(1, 0); 27 | 28 | /// A unit vector pointing along the positive Y axis. 29 | pub const Y: Self = Self::new(0, 1); 30 | 31 | /// A unit vector pointing along the negative X axis. 32 | pub const NEG_X: Self = Self::new(-1, 0); 33 | 34 | /// A unit vector pointing along the negative Y axis. 35 | pub const NEG_Y: Self = Self::new(0, -1); 36 | 37 | /// The unit axes. 38 | pub const AXES: [Self; 2] = [Self::X, Self::Y]; 39 | 40 | /// Creates a new vector. 41 | #[inline(always)] 42 | #[must_use] 43 | pub const fn new(x: i32, y: i32) -> Self { 44 | Self { x, y } 45 | } 46 | 47 | /// Creates a vector with all elements set to `v`. 48 | #[inline] 49 | #[must_use] 50 | pub const fn splat(v: i32) -> Self { 51 | Self { x: v, y: v } 52 | } 53 | } 54 | 55 | impl Mul for IVec2 { 56 | type Output = Self; 57 | #[inline] 58 | fn mul(self, rhs: i32) -> Self { 59 | Self { 60 | x: self.x.mul(rhs), 61 | y: self.y.mul(rhs), 62 | } 63 | } 64 | } 65 | 66 | impl MulAssign for IVec2 { 67 | #[inline] 68 | fn mul_assign(&mut self, rhs: i32) { 69 | self.x.mul_assign(rhs); 70 | self.y.mul_assign(rhs); 71 | } 72 | } 73 | 74 | impl Mul for i32 { 75 | type Output = IVec2; 76 | #[inline] 77 | fn mul(self, rhs: IVec2) -> IVec2 { 78 | IVec2 { 79 | x: self.mul(rhs.x), 80 | y: self.mul(rhs.y), 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /crates/vent-math/src/vec/i32/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ivec2; 2 | -------------------------------------------------------------------------------- /crates/vent-math/src/vec/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod vec2; 2 | pub mod vec3; 3 | pub mod vec4; 4 | 5 | pub mod i32; 6 | -------------------------------------------------------------------------------- /crates/vent-math/src/vec/vec2.rs: -------------------------------------------------------------------------------- 1 | use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign}; 2 | 3 | #[derive(Clone, Copy, PartialEq)] 4 | #[repr(C)] 5 | pub struct Vec2 { 6 | pub x: f32, 7 | pub y: f32, 8 | } 9 | 10 | impl Vec2 { 11 | pub const ZERO: Self = Self::splat(0.0); 12 | 13 | pub const ONE: Self = Self::splat(1.0); 14 | 15 | pub const NEG_ONE: Self = Self::splat(-1.0); 16 | 17 | pub const MIN: Self = Self::splat(f32::MIN); 18 | 19 | pub const MAX: Self = Self::splat(f32::MAX); 20 | 21 | pub const NAN: Self = Self::splat(f32::NAN); 22 | 23 | pub const INFINITY: Self = Self::splat(f32::INFINITY); 24 | 25 | pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY); 26 | 27 | pub const X: Self = Self::new(1.0, 0.0); 28 | 29 | pub const Y: Self = Self::new(0.0, 1.0); 30 | 31 | pub const NEG_X: Self = Self::new(-1.0, 0.0); 32 | 33 | pub const NEG_Y: Self = Self::new(0.0, -1.0); 34 | 35 | pub const AXES: [Self; 2] = [Self::X, Self::Y]; 36 | 37 | #[inline(always)] 38 | #[must_use] 39 | pub const fn new(x: f32, y: f32) -> Self { 40 | Self { x, y } 41 | } 42 | 43 | #[inline] 44 | #[must_use] 45 | pub const fn splat(v: f32) -> Self { 46 | Self { x: v, y: v } 47 | } 48 | 49 | pub fn dot(self, rhs: Self) -> f32 { 50 | (self.x * rhs.x) + (self.y * rhs.y) 51 | } 52 | } 53 | 54 | impl Div for Vec2 { 55 | type Output = Self; 56 | #[inline] 57 | fn div(self, rhs: Self) -> Self { 58 | Self { 59 | x: self.x.div(rhs.x), 60 | y: self.y.div(rhs.y), 61 | } 62 | } 63 | } 64 | 65 | impl DivAssign for Vec2 { 66 | #[inline] 67 | fn div_assign(&mut self, rhs: Self) { 68 | self.x.div_assign(rhs.x); 69 | self.y.div_assign(rhs.y); 70 | } 71 | } 72 | 73 | impl Div for Vec2 { 74 | type Output = Self; 75 | #[inline] 76 | fn div(self, rhs: f32) -> Self { 77 | Self { 78 | x: self.x.div(rhs), 79 | y: self.y.div(rhs), 80 | } 81 | } 82 | } 83 | 84 | impl DivAssign for Vec2 { 85 | #[inline] 86 | fn div_assign(&mut self, rhs: f32) { 87 | self.x.div_assign(rhs); 88 | self.y.div_assign(rhs); 89 | } 90 | } 91 | 92 | impl Div for f32 { 93 | type Output = Vec2; 94 | #[inline] 95 | fn div(self, rhs: Vec2) -> Vec2 { 96 | Vec2 { 97 | x: self.div(rhs.x), 98 | y: self.div(rhs.y), 99 | } 100 | } 101 | } 102 | 103 | impl Mul for Vec2 { 104 | type Output = Self; 105 | #[inline] 106 | fn mul(self, rhs: Self) -> Self { 107 | Self { 108 | x: self.x.mul(rhs.x), 109 | y: self.y.mul(rhs.y), 110 | } 111 | } 112 | } 113 | 114 | impl MulAssign for Vec2 { 115 | #[inline] 116 | fn mul_assign(&mut self, rhs: Self) { 117 | self.x.mul_assign(rhs.x); 118 | self.y.mul_assign(rhs.y); 119 | } 120 | } 121 | 122 | impl Mul for Vec2 { 123 | type Output = Self; 124 | #[inline] 125 | fn mul(self, rhs: f32) -> Self { 126 | Self { 127 | x: self.x.mul(rhs), 128 | y: self.y.mul(rhs), 129 | } 130 | } 131 | } 132 | 133 | impl MulAssign for Vec2 { 134 | #[inline] 135 | fn mul_assign(&mut self, rhs: f32) { 136 | self.x.mul_assign(rhs); 137 | self.y.mul_assign(rhs); 138 | } 139 | } 140 | 141 | impl Mul for f32 { 142 | type Output = Vec2; 143 | #[inline] 144 | fn mul(self, rhs: Vec2) -> Vec2 { 145 | Vec2 { 146 | x: self.mul(rhs.x), 147 | y: self.mul(rhs.y), 148 | } 149 | } 150 | } 151 | 152 | impl Add for Vec2 { 153 | type Output = Self; 154 | #[inline] 155 | fn add(self, rhs: Self) -> Self { 156 | Self { 157 | x: self.x.add(rhs.x), 158 | y: self.y.add(rhs.y), 159 | } 160 | } 161 | } 162 | 163 | impl AddAssign for Vec2 { 164 | #[inline] 165 | fn add_assign(&mut self, rhs: Self) { 166 | self.x.add_assign(rhs.x); 167 | self.y.add_assign(rhs.y); 168 | } 169 | } 170 | 171 | impl Add for Vec2 { 172 | type Output = Self; 173 | #[inline] 174 | fn add(self, rhs: f32) -> Self { 175 | Self { 176 | x: self.x.add(rhs), 177 | y: self.y.add(rhs), 178 | } 179 | } 180 | } 181 | 182 | impl AddAssign for Vec2 { 183 | #[inline] 184 | fn add_assign(&mut self, rhs: f32) { 185 | self.x.add_assign(rhs); 186 | self.y.add_assign(rhs); 187 | } 188 | } 189 | 190 | impl Add for f32 { 191 | type Output = Vec2; 192 | #[inline] 193 | fn add(self, rhs: Vec2) -> Vec2 { 194 | Vec2 { 195 | x: self.add(rhs.x), 196 | y: self.add(rhs.y), 197 | } 198 | } 199 | } 200 | 201 | impl Sub for Vec2 { 202 | type Output = Self; 203 | #[inline] 204 | fn sub(self, rhs: Self) -> Self { 205 | Self { 206 | x: self.x.sub(rhs.x), 207 | y: self.y.sub(rhs.y), 208 | } 209 | } 210 | } 211 | 212 | impl SubAssign for Vec2 { 213 | #[inline] 214 | fn sub_assign(&mut self, rhs: Vec2) { 215 | self.x.sub_assign(rhs.x); 216 | self.y.sub_assign(rhs.y); 217 | } 218 | } 219 | 220 | impl Sub for Vec2 { 221 | type Output = Self; 222 | #[inline] 223 | fn sub(self, rhs: f32) -> Self { 224 | Self { 225 | x: self.x.sub(rhs), 226 | y: self.y.sub(rhs), 227 | } 228 | } 229 | } 230 | 231 | impl SubAssign for Vec2 { 232 | #[inline] 233 | fn sub_assign(&mut self, rhs: f32) { 234 | self.x.sub_assign(rhs); 235 | self.y.sub_assign(rhs); 236 | } 237 | } 238 | 239 | impl Sub for f32 { 240 | type Output = Vec2; 241 | #[inline] 242 | fn sub(self, rhs: Vec2) -> Vec2 { 243 | Vec2 { 244 | x: self.sub(rhs.x), 245 | y: self.sub(rhs.y), 246 | } 247 | } 248 | } 249 | 250 | impl Rem for Vec2 { 251 | type Output = Self; 252 | #[inline] 253 | fn rem(self, rhs: Self) -> Self { 254 | Self { 255 | x: self.x.rem(rhs.x), 256 | y: self.y.rem(rhs.y), 257 | } 258 | } 259 | } 260 | 261 | impl RemAssign for Vec2 { 262 | #[inline] 263 | fn rem_assign(&mut self, rhs: Self) { 264 | self.x.rem_assign(rhs.x); 265 | self.y.rem_assign(rhs.y); 266 | } 267 | } 268 | 269 | impl Rem for Vec2 { 270 | type Output = Self; 271 | #[inline] 272 | fn rem(self, rhs: f32) -> Self { 273 | Self { 274 | x: self.x.rem(rhs), 275 | y: self.y.rem(rhs), 276 | } 277 | } 278 | } 279 | 280 | impl RemAssign for Vec2 { 281 | #[inline] 282 | fn rem_assign(&mut self, rhs: f32) { 283 | self.x.rem_assign(rhs); 284 | self.y.rem_assign(rhs); 285 | } 286 | } 287 | 288 | impl Rem for f32 { 289 | type Output = Vec2; 290 | #[inline] 291 | fn rem(self, rhs: Vec2) -> Vec2 { 292 | Vec2 { 293 | x: self.rem(rhs.x), 294 | y: self.rem(rhs.y), 295 | } 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /crates/vent-math/src/vec/vec4.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | arch::x86_64::{__m128, _mm_add_ps, _mm_loadu_ps, _mm_mul_ps, _mm_set1_ps, _mm_store_ps}, 3 | ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign}, 4 | }; 5 | 6 | use crate::align16::Align16; 7 | 8 | use super::{vec2::Vec2, vec3::Vec3}; 9 | 10 | #[repr(C)] 11 | union UnionCast { 12 | a: [f32; 4], 13 | v: Vec4, 14 | } 15 | 16 | #[derive(Clone, Copy)] 17 | #[repr(transparent)] 18 | pub struct Vec4(pub(crate) __m128); 19 | 20 | impl Vec4 { 21 | pub const ZERO: Self = Self::splat(0.0); 22 | 23 | pub const ONE: Self = Self::splat(1.0); 24 | 25 | pub const NEG_ONE: Self = Self::splat(-1.0); 26 | 27 | pub const MIN: Self = Self::splat(f32::MIN); 28 | 29 | pub const MAX: Self = Self::splat(f32::MAX); 30 | 31 | pub const NAN: Self = Self::splat(f32::NAN); 32 | 33 | pub const INFINITY: Self = Self::splat(f32::INFINITY); 34 | 35 | pub const NEG_INFINITY: Self = Self::splat(f32::NEG_INFINITY); 36 | 37 | pub const X: Self = Self::new(1.0, 0.0, 0.0, 0.0); 38 | 39 | pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0); 40 | 41 | pub const Z: Self = Self::new(0.0, 0.0, 1.0, 0.0); 42 | 43 | pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0); 44 | 45 | pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0, 0.0); 46 | 47 | pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0); 48 | 49 | pub const NEG_Z: Self = Self::new(0.0, 0.0, -1.0, 0.0); 50 | 51 | pub const NEG_W: Self = Self::new(0.0, 0.0, 0.0, -1.0); 52 | 53 | pub const AXES: [Self; 4] = [Self::X, Self::Y, Self::Z, Self::W]; 54 | 55 | #[inline(always)] 56 | #[must_use] 57 | pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self { 58 | unsafe { UnionCast { a: [x, y, z, w] }.v } 59 | } 60 | 61 | #[inline] 62 | #[must_use] 63 | pub const fn from_array(a: [f32; 4]) -> Self { 64 | Self::new(a[0], a[1], a[2], a[3]) 65 | } 66 | 67 | #[inline] 68 | #[must_use] 69 | pub const fn splat(v: f32) -> Self { 70 | unsafe { UnionCast { a: [v; 4] }.v } 71 | } 72 | 73 | #[inline] 74 | #[must_use] 75 | pub fn xxxx(self) -> Self { 76 | Self::new(self.x, self.x, self.x, self.x) 77 | } 78 | #[inline] 79 | #[must_use] 80 | pub fn yyyy(self) -> Self { 81 | Self::new(self.y, self.y, self.y, self.y) 82 | } 83 | 84 | #[inline] 85 | #[must_use] 86 | pub fn zzzz(self) -> Self { 87 | Self::new(self.z, self.z, self.z, self.z) 88 | } 89 | 90 | #[inline] 91 | #[must_use] 92 | pub fn wwww(self) -> Self { 93 | Self::new(self.w, self.w, self.w, self.w) 94 | } 95 | } 96 | 97 | impl Add for Vec4 { 98 | type Output = Self; 99 | #[inline] 100 | fn add(self, rhs: Self) -> Self { 101 | Self(unsafe { _mm_add_ps(self.0, rhs.0) }) 102 | } 103 | } 104 | 105 | impl AddAssign for Vec4 { 106 | #[inline] 107 | fn add_assign(&mut self, rhs: Self) { 108 | self.0 = unsafe { _mm_add_ps(self.0, rhs.0) }; 109 | } 110 | } 111 | 112 | impl Mul for Vec4 { 113 | type Output = Self; 114 | #[inline] 115 | fn mul(self, rhs: Self) -> Self { 116 | Self(unsafe { _mm_mul_ps(self.0, rhs.0) }) 117 | } 118 | } 119 | 120 | impl MulAssign for Vec4 { 121 | #[inline] 122 | fn mul_assign(&mut self, rhs: Self) { 123 | self.0 = unsafe { _mm_mul_ps(self.0, rhs.0) }; 124 | } 125 | } 126 | 127 | impl Mul for Vec4 { 128 | type Output = Self; 129 | #[inline] 130 | fn mul(self, rhs: f32) -> Self { 131 | Self(unsafe { _mm_mul_ps(self.0, _mm_set1_ps(rhs)) }) 132 | } 133 | } 134 | 135 | impl MulAssign for Vec4 { 136 | #[inline] 137 | fn mul_assign(&mut self, rhs: f32) { 138 | self.0 = unsafe { _mm_mul_ps(self.0, _mm_set1_ps(rhs)) }; 139 | } 140 | } 141 | 142 | impl Mul for f32 { 143 | type Output = Vec4; 144 | #[inline] 145 | fn mul(self, rhs: Vec4) -> Vec4 { 146 | Vec4(unsafe { _mm_mul_ps(_mm_set1_ps(self), rhs.0) }) 147 | } 148 | } 149 | 150 | impl From for __m128 { 151 | #[inline(always)] 152 | fn from(t: Vec4) -> Self { 153 | t.0 154 | } 155 | } 156 | 157 | impl From<__m128> for Vec4 { 158 | #[inline(always)] 159 | fn from(t: __m128) -> Self { 160 | Self(t) 161 | } 162 | } 163 | 164 | impl From<[f32; 4]> for Vec4 { 165 | #[inline] 166 | fn from(a: [f32; 4]) -> Self { 167 | Self(unsafe { _mm_loadu_ps(a.as_ptr()) }) 168 | } 169 | } 170 | 171 | impl From for [f32; 4] { 172 | #[inline] 173 | fn from(v: Vec4) -> Self { 174 | use core::mem::MaybeUninit; 175 | let mut out: MaybeUninit> = MaybeUninit::uninit(); 176 | unsafe { 177 | _mm_store_ps(out.as_mut_ptr().cast(), v.0); 178 | out.assume_init().0 179 | } 180 | } 181 | } 182 | 183 | impl From<(f32, f32, f32, f32)> for Vec4 { 184 | #[inline] 185 | fn from(t: (f32, f32, f32, f32)) -> Self { 186 | Self::new(t.0, t.1, t.2, t.3) 187 | } 188 | } 189 | 190 | impl From for (f32, f32, f32, f32) { 191 | #[inline] 192 | fn from(v: Vec4) -> Self { 193 | use core::mem::MaybeUninit; 194 | let mut out: MaybeUninit> = MaybeUninit::uninit(); 195 | unsafe { 196 | _mm_store_ps(out.as_mut_ptr().cast(), v.0); 197 | out.assume_init().0 198 | } 199 | } 200 | } 201 | 202 | impl From<(Vec3, f32)> for Vec4 { 203 | #[inline] 204 | fn from((v, w): (Vec3, f32)) -> Self { 205 | Self::new(v.x, v.y, v.z, w) 206 | } 207 | } 208 | 209 | impl From<(f32, Vec3)> for Vec4 { 210 | #[inline] 211 | fn from((x, v): (f32, Vec3)) -> Self { 212 | Self::new(x, v.x, v.y, v.z) 213 | } 214 | } 215 | 216 | impl From<(Vec2, f32, f32)> for Vec4 { 217 | #[inline] 218 | fn from((v, z, w): (Vec2, f32, f32)) -> Self { 219 | Self::new(v.x, v.y, z, w) 220 | } 221 | } 222 | 223 | impl From<(Vec2, Vec2)> for Vec4 { 224 | #[inline] 225 | fn from((v, u): (Vec2, Vec2)) -> Self { 226 | Self::new(v.x, v.y, u.x, u.y) 227 | } 228 | } 229 | 230 | impl Deref for Vec4 { 231 | type Target = crate::deref::Vec4; 232 | #[inline] 233 | fn deref(&self) -> &Self::Target { 234 | unsafe { &*(self as *const Self).cast() } 235 | } 236 | } 237 | 238 | impl DerefMut for Vec4 { 239 | #[inline] 240 | fn deref_mut(&mut self) -> &mut Self::Target { 241 | unsafe { &mut *(self as *mut Self).cast() } 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /crates/vent-rendering/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-rendering" 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 | vent-window = { path= "../vent-window"} 10 | ash = { version= "0.38", default-features = false, features = ["loaded", "debug", "std"] } 11 | spirv = "0.3.0" 12 | 13 | ordered-float = "4.2.0" 14 | image = "0.25" 15 | 16 | raw-window-handle = "0.6" 17 | log = "0.4" 18 | 19 | [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] 20 | raw-window-metal = "1.0.0" 21 | -------------------------------------------------------------------------------- /crates/vent-rendering/src/allocator.rs: -------------------------------------------------------------------------------- 1 | use ash::vk; 2 | 3 | // TODO Write an own Efficent Vulkan Memory Allocator 4 | 5 | pub struct MemoryAllocator { 6 | memory_props: vk::PhysicalDeviceMemoryProperties, 7 | } 8 | 9 | impl MemoryAllocator { 10 | pub fn new(memory_props: vk::PhysicalDeviceMemoryProperties) -> Self { 11 | Self { memory_props } 12 | } 13 | 14 | /// Allocates memory for an Buffer and binds it 15 | pub fn allocate_buffer( 16 | &self, 17 | device: &ash::Device, 18 | buffer: vk::Buffer, 19 | flags: vk::MemoryPropertyFlags, 20 | ) -> vk::DeviceMemory { 21 | let memory_req = unsafe { device.get_buffer_memory_requirements(buffer) }; 22 | 23 | let memory_info = vk::MemoryAllocateInfo::default() 24 | .allocation_size(memory_req.size) 25 | .memory_type_index( 26 | self.find_memorytype_index(memory_req, flags) 27 | .expect("Failed to find Memory Index"), 28 | ); 29 | 30 | let memory = unsafe { device.allocate_memory(&memory_info, None) }.unwrap(); 31 | unsafe { 32 | device 33 | .bind_buffer_memory(buffer, memory, 0) 34 | .expect("Failed to bind Buffer memory"); 35 | } 36 | memory 37 | } 38 | 39 | /// Allocates memory for an Image and binds it 40 | pub fn allocate_image( 41 | &self, 42 | device: &ash::Device, 43 | image: vk::Image, 44 | flags: vk::MemoryPropertyFlags, 45 | ) -> vk::DeviceMemory { 46 | let memory_req = unsafe { device.get_image_memory_requirements(image) }; 47 | 48 | let memory_info = vk::MemoryAllocateInfo::default() 49 | .allocation_size(memory_req.size) 50 | .memory_type_index( 51 | self.find_memorytype_index(memory_req, flags) 52 | .expect("Failed to find Memory Index"), 53 | ); 54 | 55 | let memory = unsafe { device.allocate_memory(&memory_info, None) }.unwrap(); 56 | unsafe { 57 | device 58 | .bind_image_memory(image, memory, 0) 59 | .expect("Failed to bind Buffer memory"); 60 | } 61 | memory 62 | } 63 | 64 | fn find_memorytype_index( 65 | &self, 66 | memory_req: vk::MemoryRequirements, 67 | flags: vk::MemoryPropertyFlags, 68 | ) -> Option { 69 | self.memory_props.memory_types[..self.memory_props.memory_type_count as _] 70 | .iter() 71 | .enumerate() 72 | .find(|(index, memory_type)| { 73 | (1 << index) & memory_req.memory_type_bits != 0 74 | && memory_type.property_flags & flags == flags 75 | }) 76 | .map(|(index, _memory_type)| index as _) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /crates/vent-rendering/src/buffer.rs: -------------------------------------------------------------------------------- 1 | use std::{mem::align_of, os::raw::c_void}; 2 | 3 | use ash::vk; 4 | 5 | use crate::{ 6 | allocator::MemoryAllocator, begin_single_time_command, debug, end_single_time_command, 7 | instance::VulkanInstance, 8 | }; 9 | 10 | pub struct VulkanBuffer { 11 | pub buffer: vk::Buffer, 12 | pub buffer_memory: vk::DeviceMemory, 13 | } 14 | 15 | impl VulkanBuffer { 16 | // Size = (size_of::() * SIZE) 17 | /** 18 | * Allocates & Binds new uninitialized Memory based on Size and Usage 19 | */ 20 | pub fn new( 21 | instance: &VulkanInstance, 22 | size: vk::DeviceSize, 23 | usage: vk::BufferUsageFlags, 24 | flags: vk::MemoryPropertyFlags, 25 | name: Option<&str>, 26 | ) -> Self { 27 | let buffer_info = vk::BufferCreateInfo::default() 28 | .size(size) 29 | .usage(usage) 30 | .sharing_mode(vk::SharingMode::EXCLUSIVE); 31 | 32 | let buffer = unsafe { instance.device.create_buffer(&buffer_info, None) }.unwrap(); 33 | 34 | let buffer_memory = 35 | instance 36 | .memory_allocator 37 | .allocate_buffer(&instance.device, buffer, flags); 38 | 39 | if instance.validation { 40 | if let Some(name) = name { 41 | debug::set_object_name(&instance.debug_utils_device, buffer, name) 42 | } 43 | } 44 | 45 | Self { 46 | buffer, 47 | buffer_memory, 48 | } 49 | } 50 | 51 | /** 52 | * Allocates & Binds an Staging buffer for CPU and then uploading it to the GPU 53 | */ 54 | pub fn cpu_to_gpu( 55 | instance: &VulkanInstance, 56 | data: &[T], 57 | size: vk::DeviceSize, 58 | usage: vk::BufferUsageFlags, 59 | name: Option<&str>, 60 | ) -> Self { 61 | let buffer = VulkanBuffer::new( 62 | instance, 63 | size, 64 | usage | vk::BufferUsageFlags::TRANSFER_DST, 65 | vk::MemoryPropertyFlags::DEVICE_LOCAL, 66 | name, 67 | ); 68 | let mut staging_buf = VulkanBuffer::new( 69 | instance, 70 | size, 71 | vk::BufferUsageFlags::TRANSFER_SRC, 72 | vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT, 73 | name, 74 | ); 75 | 76 | let memory = staging_buf.map(&instance.device, size); 77 | 78 | unsafe { staging_buf.upload_data(memory, data, size) }; 79 | 80 | let command_buffer = 81 | begin_single_time_command(&instance.device, instance.global_command_pool); 82 | 83 | unsafe { 84 | let buffer_info = vk::BufferCopy::default().size(size); 85 | 86 | instance 87 | .device 88 | .cmd_copy_buffer(command_buffer, *staging_buf, *buffer, &[buffer_info]); 89 | } 90 | staging_buf.unmap(&instance.device); 91 | 92 | end_single_time_command( 93 | &instance.device, 94 | instance.global_command_pool, 95 | instance.graphics_queue, 96 | command_buffer, 97 | ); 98 | 99 | staging_buf.destroy(&instance.device); 100 | buffer 101 | } 102 | 103 | /** 104 | * Allocates new Image memory & binds them 105 | */ 106 | pub fn new_image( 107 | device: &ash::Device, 108 | allocator: &MemoryAllocator, 109 | image: vk::Image, 110 | ) -> vk::DeviceMemory { 111 | allocator.allocate_image(device, image, vk::MemoryPropertyFlags::DEVICE_LOCAL) 112 | } 113 | 114 | /** 115 | * Allocates & Binds new initialized Memory based on Size and Usage 116 | */ 117 | pub fn new_init( 118 | instance: &VulkanInstance, 119 | size: vk::DeviceSize, 120 | usage: vk::BufferUsageFlags, 121 | data: &[T], 122 | flags: vk::MemoryPropertyFlags, 123 | name: Option<&str>, 124 | ) -> Self { 125 | let buffer = Self::new(instance, size, usage, flags, name); 126 | let memory = buffer.map(&instance.device, size); 127 | unsafe { buffer.upload_data(memory, data, size) }; 128 | buffer.unmap(&instance.device); 129 | buffer 130 | } 131 | 132 | /// # Safety 133 | /// 134 | /// Do not give an bad memory pointer 135 | pub unsafe fn upload_data( 136 | &self, 137 | memory: *mut c_void, 138 | data: &[T], 139 | size: vk::DeviceSize, 140 | ) { 141 | let mut align = ash::util::Align::new(memory, align_of::() as _, size); 142 | align.copy_from_slice(data); 143 | } 144 | 145 | pub fn map(&self, device: &ash::Device, size: vk::DeviceSize) -> *mut c_void { 146 | unsafe { 147 | device 148 | .map_memory(self.buffer_memory, 0, size, vk::MemoryMapFlags::empty()) 149 | .unwrap() 150 | } 151 | } 152 | 153 | pub fn unmap(&self, device: &ash::Device) { 154 | unsafe { device.unmap_memory(self.buffer_memory) }; 155 | } 156 | 157 | pub fn destroy(&mut self, device: &ash::Device) { 158 | unsafe { 159 | device.destroy_buffer(self.buffer, None); 160 | device.free_memory(self.buffer_memory, None); // Free Memory after buffer destruction! 161 | } 162 | } 163 | } 164 | 165 | impl ::std::ops::Deref for VulkanBuffer { 166 | type Target = vk::Buffer; 167 | 168 | fn deref(&self) -> &Self::Target { 169 | &self.buffer 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /crates/vent-rendering/src/debug.rs: -------------------------------------------------------------------------------- 1 | use ash::ext::debug_utils; 2 | use ash::vk::Handle; 3 | use ash::{vk, Entry, Instance}; 4 | use std::borrow::Cow; 5 | use std::os::raw::c_void; 6 | use std::{ 7 | ffi::{CStr, CString}, 8 | os::raw::c_char, 9 | }; 10 | 11 | const REQUIRED_LAYERS: [&str; 1] = ["VK_LAYER_KHRONOS_validation"]; 12 | 13 | unsafe extern "system" fn vulkan_debug_callback( 14 | flag: vk::DebugUtilsMessageSeverityFlagsEXT, 15 | typ: vk::DebugUtilsMessageTypeFlagsEXT, 16 | p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT, 17 | _: *mut c_void, 18 | ) -> vk::Bool32 { 19 | use vk::DebugUtilsMessageSeverityFlagsEXT as Flag; 20 | let callback_data = *p_callback_data; 21 | 22 | let message = if callback_data.p_message.is_null() { 23 | Cow::from("") 24 | } else { 25 | CStr::from_ptr(callback_data.p_message).to_string_lossy() 26 | }; 27 | match flag { 28 | Flag::VERBOSE => log::debug!("{:?} - {:?}", typ, message), 29 | Flag::INFO => log::info!("{:?} - {:?}", typ, message), 30 | Flag::WARNING => log::warn!("{:?} - {:?}", typ, message), 31 | _ => log::error!("{:?} - {:?}", typ, message), 32 | } 33 | vk::FALSE 34 | } 35 | 36 | /// Get the pointers to the validation layers names. 37 | /// Also return the corresponding `CString` to avoid dangling pointers. 38 | pub fn get_layer_names_and_pointers() -> (Vec, Vec<*const c_char>) { 39 | let layer_names = REQUIRED_LAYERS 40 | .iter() 41 | .map(|name| CString::new(*name).unwrap()) 42 | .collect::>(); 43 | let layer_names_ptrs = layer_names 44 | .iter() 45 | .map(|name| name.as_ptr()) 46 | .collect::>(); 47 | (layer_names, layer_names_ptrs) 48 | } 49 | 50 | /// Check if the required validation set in `REQUIRED_LAYERS` 51 | /// are supported by the Vulkan instance. 52 | /// 53 | /// # Panics 54 | /// 55 | /// Panic if at least one on the layer is not supported. 56 | pub fn check_validation_layer_support(entry: &Entry) { 57 | for required in REQUIRED_LAYERS.iter() { 58 | let properties = unsafe { entry.enumerate_instance_layer_properties().unwrap() }; // TODO: Cache 59 | let layers = properties.iter().find(|layer| { 60 | let name = unsafe { CStr::from_ptr(layer.layer_name.as_ptr()) }; 61 | let name = name.to_str().expect("Failed to get layer name pointer"); 62 | required == &name 63 | }); 64 | 65 | if layers.is_none() { 66 | panic!("Layer not supported: {}", required); 67 | } 68 | } 69 | } 70 | pub fn set_object_name( 71 | debug_utils_device: &Option, 72 | handle: H, 73 | name: &str, 74 | ) { 75 | if let Some(debug_utils_device) = debug_utils_device { 76 | let object_name = CString::new(name).expect("Failed to convert &str to CString"); 77 | 78 | let debug_utils_object_name_info = vk::DebugUtilsObjectNameInfoEXT::default() 79 | .object_handle(handle) 80 | .object_name(&object_name); 81 | 82 | unsafe { 83 | debug_utils_device 84 | .set_debug_utils_object_name(&debug_utils_object_name_info) 85 | .expect("Failed to set debug object name") 86 | }; 87 | } 88 | } 89 | 90 | pub fn get_validation_features() -> vk::ValidationFeaturesEXT<'static> { 91 | vk::ValidationFeaturesEXT::default() 92 | .enabled_validation_features(&[ 93 | vk::ValidationFeatureEnableEXT::GPU_ASSISTED, 94 | // vk::ValidationFeatureEnableEXT::BEST_PRACTICES, Does hide real errors, so lets disable it for now 95 | vk::ValidationFeatureEnableEXT::SYNCHRONIZATION_VALIDATION, 96 | ]) 97 | .disabled_validation_features(&[]) // We need to give it an empty Array, If not we get an validation error 98 | } 99 | 100 | /// Setup the debug message if validation layers are enabled. 101 | #[must_use] 102 | pub fn setup_debug_messenger( 103 | entry: &Entry, 104 | instance: &Instance, 105 | device: &ash::Device, 106 | ) -> ( 107 | debug_utils::Instance, 108 | debug_utils::Device, 109 | vk::DebugUtilsMessengerEXT, 110 | ) { 111 | let create_info = vk::DebugUtilsMessengerCreateInfoEXT::default() 112 | .message_severity( 113 | vk::DebugUtilsMessageSeverityFlagsEXT::VERBOSE 114 | | vk::DebugUtilsMessageSeverityFlagsEXT::ERROR 115 | | vk::DebugUtilsMessageSeverityFlagsEXT::WARNING 116 | | vk::DebugUtilsMessageSeverityFlagsEXT::INFO, 117 | ) 118 | .message_type( 119 | vk::DebugUtilsMessageTypeFlagsEXT::GENERAL 120 | | vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE 121 | | vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION, 122 | ) 123 | .pfn_user_callback(Some(vulkan_debug_callback)); 124 | let debug_utils = debug_utils::Instance::new(entry, instance); 125 | let debug_utils_device = debug_utils::Device::new(instance, device); 126 | let debug_utils_messenger = unsafe { 127 | debug_utils 128 | .create_debug_utils_messenger(&create_info, None) 129 | .unwrap() 130 | }; 131 | 132 | (debug_utils, debug_utils_device, debug_utils_messenger) 133 | } 134 | -------------------------------------------------------------------------------- /crates/vent-rendering/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::os::raw::c_void; 2 | 3 | use ash::vk; 4 | use buffer::VulkanBuffer; 5 | use ordered_float::OrderedFloat; 6 | 7 | pub mod allocator; 8 | pub mod buffer; 9 | mod debug; 10 | pub mod image; 11 | pub mod instance; 12 | pub mod mesh; 13 | pub mod pipeline; 14 | mod surface; 15 | pub mod vertex; 16 | 17 | pub const DEFAULT_TEXTURE_FILTER: vk::Filter = vk::Filter::LINEAR; 18 | pub const DEFAULT_MIPMAP_MODE: vk::SamplerMipmapMode = vk::SamplerMipmapMode::LINEAR; 19 | 20 | const DEFAULT_FENCE_TIMEOUT: u64 = 100000000000; 21 | 22 | // Used for caching 23 | #[derive(PartialEq, Eq, Hash)] 24 | pub struct MaterialPipelineInfo { 25 | pub mode: vk::PrimitiveTopology, 26 | pub alpha_cut: Option>, // Default 0.5 27 | pub double_sided: bool, 28 | } 29 | 30 | pub enum Indices { 31 | U8(Vec), // TODO: Enable uin8 vulkan feature 32 | U16(Vec), 33 | U32(Vec), 34 | } 35 | 36 | impl Indices { 37 | /// Returns the number of indices. 38 | pub fn len(&self) -> usize { 39 | match self { 40 | Indices::U8(vec) => vec.len(), 41 | Indices::U16(vec) => vec.len(), 42 | Indices::U32(vec) => vec.len(), 43 | } 44 | } 45 | 46 | /// # Safety 47 | /// 48 | /// Do not give an bad memory pointer 49 | pub unsafe fn upload(&self, buffer: &VulkanBuffer, memory: *mut c_void, size: vk::DeviceSize) { 50 | match self { 51 | Indices::U8(vec) => buffer.upload_data(memory, vec, size), 52 | Indices::U16(vec) => buffer.upload_data(memory, vec, size), 53 | Indices::U32(vec) => buffer.upload_data(memory, vec, size), 54 | } 55 | } 56 | 57 | pub fn get_size(&self) -> usize { 58 | match self { 59 | Indices::U8(indices) => std::mem::size_of_val(&indices[..]), 60 | Indices::U16(indices) => std::mem::size_of_val(&indices[..]), 61 | Indices::U32(indices) => std::mem::size_of_val(&indices[..]), 62 | } 63 | } 64 | 65 | /// Returns `true` if there are no indices. 66 | pub fn is_empty(&self) -> bool { 67 | match self { 68 | Indices::U8(vec) => vec.is_empty(), 69 | Indices::U16(vec) => vec.is_empty(), 70 | Indices::U32(vec) => vec.is_empty(), 71 | } 72 | } 73 | 74 | pub fn vk_type(&self) -> vk::IndexType { 75 | match self { 76 | Indices::U8(_) => vk::IndexType::UINT8_KHR, 77 | Indices::U16(_) => vk::IndexType::UINT16, 78 | Indices::U32(_) => vk::IndexType::UINT32, 79 | } 80 | } 81 | } 82 | 83 | pub fn any_as_u8_slice(any: &T) -> &[u8] { 84 | let ptr = (any as *const T) as *const u8; 85 | unsafe { std::slice::from_raw_parts(ptr, std::mem::size_of::()) } 86 | } 87 | 88 | pub fn begin_single_time_command( 89 | device: &ash::Device, 90 | command_pool: vk::CommandPool, 91 | ) -> vk::CommandBuffer { 92 | let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::default() 93 | .command_buffer_count(1) 94 | .command_pool(command_pool) 95 | .level(vk::CommandBufferLevel::PRIMARY); 96 | 97 | let command_buffer = unsafe { 98 | device 99 | .allocate_command_buffers(&command_buffer_allocate_info) 100 | .expect("Failed to allocate Command Buffers!") 101 | }[0]; 102 | 103 | let command_buffer_begin_info = 104 | vk::CommandBufferBeginInfo::default().flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT); 105 | 106 | unsafe { 107 | device 108 | .begin_command_buffer(command_buffer, &command_buffer_begin_info) 109 | .expect("Failed to begin recording Command Buffer at beginning!"); 110 | } 111 | 112 | command_buffer 113 | } 114 | 115 | pub fn end_single_time_command( 116 | device: &ash::Device, 117 | command_pool: vk::CommandPool, 118 | submit_queue: vk::Queue, 119 | command_buffer: vk::CommandBuffer, 120 | ) { 121 | unsafe { 122 | device 123 | .end_command_buffer(command_buffer) 124 | .expect("Failed to record Command Buffer at Ending!"); 125 | } 126 | 127 | let buffers_to_submit = vk::CommandBufferSubmitInfo::default().command_buffer(command_buffer); 128 | 129 | let binding = [buffers_to_submit]; 130 | let submit_info = vk::SubmitInfo2::default().command_buffer_infos(&binding); 131 | 132 | unsafe { 133 | let fence = device 134 | .create_fence(&vk::FenceCreateInfo::default(), None) 135 | .unwrap(); 136 | 137 | device 138 | .queue_submit2(submit_queue, &[submit_info], fence) 139 | .expect("Failed to Queue Submit!"); 140 | device 141 | .wait_for_fences(&[fence], true, DEFAULT_FENCE_TIMEOUT) 142 | .expect("Failed to wait for Fence"); 143 | 144 | device.destroy_fence(fence, None); 145 | device.free_command_buffers(command_pool, &[command_buffer]); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /crates/vent-rendering/src/mesh.rs: -------------------------------------------------------------------------------- 1 | use ash::vk; 2 | 3 | use crate::{ 4 | begin_single_time_command, buffer::VulkanBuffer, end_single_time_command, 5 | instance::VulkanInstance, Indices, 6 | }; 7 | 8 | /// This is a simple mesh that consists of vertices and indices. It is useful when you need to hard-code 3D data into your application. 9 | /// 10 | /// By using this simple mesh, you can easily define custom shapes or provide default objects for your application. It is particularly handy when you want to avoid loading external model files and instead directly embed the 3D data within your code. 11 | /// 12 | /// Note that this simple mesh implementation does not support advanced features such as normal mapping, skeletal animation, or material properties. It serves as a basic foundation for representing 3D geometry and can be extended or customized according to your specific requirements. 13 | pub struct Mesh3D { 14 | vertex_buf: VulkanBuffer, 15 | index_buf: VulkanBuffer, 16 | index_type: vk::IndexType, 17 | index_count: u32, 18 | } 19 | 20 | impl Mesh3D { 21 | pub fn new( 22 | instance: &VulkanInstance, 23 | vertices: &[V], 24 | indices: Indices, 25 | name: Option<&str>, 26 | ) -> Self { 27 | let vertex_size = std::mem::size_of_val(vertices) as vk::DeviceSize; 28 | let index_size = indices.get_size() as vk::DeviceSize; 29 | 30 | let vertex_buf = VulkanBuffer::new( 31 | instance, 32 | vertex_size, 33 | vk::BufferUsageFlags::VERTEX_BUFFER | vk::BufferUsageFlags::TRANSFER_DST, 34 | vk::MemoryPropertyFlags::DEVICE_LOCAL, 35 | name, 36 | ); 37 | 38 | let index_buf = VulkanBuffer::new( 39 | instance, 40 | index_size, 41 | vk::BufferUsageFlags::INDEX_BUFFER | vk::BufferUsageFlags::TRANSFER_DST, 42 | vk::MemoryPropertyFlags::DEVICE_LOCAL, 43 | name, 44 | ); 45 | 46 | let mut staging_buf = VulkanBuffer::new( 47 | instance, 48 | vertex_size + index_size, 49 | vk::BufferUsageFlags::TRANSFER_SRC, 50 | vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT, 51 | name, 52 | ); 53 | 54 | let memory = staging_buf.map(&instance.device, vertex_size + index_size); 55 | 56 | // copy vertex buffer 57 | unsafe { staging_buf.upload_data(memory, vertices, vertex_size) }; 58 | // copy index buffer 59 | unsafe { 60 | indices.upload( 61 | &staging_buf, 62 | memory.wrapping_add(vertex_size as usize), 63 | index_size, 64 | ) 65 | }; 66 | 67 | let command_buffer = 68 | begin_single_time_command(&instance.device, instance.global_command_pool); 69 | 70 | unsafe { 71 | let buffer_info = vk::BufferCopy::default().size(vertex_size); 72 | 73 | instance.device.cmd_copy_buffer( 74 | command_buffer, 75 | *staging_buf, 76 | *vertex_buf, 77 | &[buffer_info], 78 | ); 79 | let buffer_info = vk::BufferCopy::default() 80 | .size(index_size) 81 | .src_offset(vertex_size); 82 | 83 | instance.device.cmd_copy_buffer( 84 | command_buffer, 85 | *staging_buf, 86 | *index_buf, 87 | &[buffer_info], 88 | ); 89 | }; 90 | staging_buf.unmap(&instance.device); 91 | 92 | end_single_time_command( 93 | &instance.device, 94 | instance.global_command_pool, 95 | instance.graphics_queue, 96 | command_buffer, 97 | ); 98 | 99 | staging_buf.destroy(&instance.device); 100 | 101 | Self { 102 | vertex_buf, 103 | index_buf, 104 | index_type: indices.vk_type(), 105 | index_count: indices.len() as u32, 106 | } 107 | } 108 | 109 | pub fn bind(&self, device: &ash::Device, command_buffer: vk::CommandBuffer) { 110 | unsafe { 111 | device.cmd_bind_vertex_buffers2( 112 | command_buffer, 113 | 0, 114 | &[*self.vertex_buf], 115 | &[0], 116 | None, 117 | None, 118 | ); 119 | device.cmd_bind_index_buffer(command_buffer, *self.index_buf, 0, self.index_type); 120 | } 121 | } 122 | 123 | pub fn draw(&self, device: &ash::Device, command_buffer: vk::CommandBuffer) { 124 | unsafe { device.cmd_draw_indexed(command_buffer, self.index_count, 1, 0, 0, 0) }; 125 | } 126 | 127 | pub fn destroy(&mut self, device: &ash::Device) { 128 | self.vertex_buf.destroy(device); 129 | self.index_buf.destroy(device); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /crates/vent-rendering/src/vertex.rs: -------------------------------------------------------------------------------- 1 | use std::mem::offset_of; 2 | 3 | use ash::vk; 4 | 5 | #[derive(Clone, Copy, PartialEq)] 6 | pub struct Vertex3D { 7 | pub position: [f32; 3], 8 | pub tex_coord: [f32; 2], 9 | pub normal: [f32; 3], 10 | } 11 | 12 | #[derive(Clone, Copy, PartialEq)] 13 | pub struct VertexPos3D { 14 | pub position: [f32; 3], 15 | } 16 | 17 | #[derive(Clone, Copy, PartialEq)] 18 | pub struct Vertex2D { 19 | pub position: [f32; 2], 20 | pub tex_coord: [f32; 2], 21 | pub color: u32, 22 | } 23 | 24 | impl Vertex3D { 25 | pub fn binding_description() -> vk::VertexInputBindingDescription { 26 | vk::VertexInputBindingDescription::default() 27 | .binding(0) 28 | .stride(std::mem::size_of::() as u32) 29 | .input_rate(vk::VertexInputRate::VERTEX) 30 | } 31 | pub fn input_descriptions() -> [vk::VertexInputAttributeDescription; 3] { 32 | [ 33 | // offset_of macro got stabilized in rust 1.77 34 | vk::VertexInputAttributeDescription::default() 35 | .location(0) 36 | .binding(0) 37 | .format(vk::Format::R32G32B32A32_SFLOAT) 38 | .offset(offset_of!(Self, position) as u32), 39 | vk::VertexInputAttributeDescription::default() 40 | .location(1) 41 | .binding(0) 42 | .format(vk::Format::R32G32_SFLOAT) 43 | .offset(offset_of!(Self, tex_coord) as u32), 44 | vk::VertexInputAttributeDescription::default() 45 | .location(2) 46 | .binding(0) 47 | .format(vk::Format::R32G32B32A32_SFLOAT) 48 | .offset(offset_of!(Self, normal) as u32), 49 | ] 50 | } 51 | } 52 | 53 | impl VertexPos3D { 54 | pub fn binding_description() -> vk::VertexInputBindingDescription { 55 | vk::VertexInputBindingDescription::default() 56 | .binding(0) 57 | .stride(std::mem::size_of::() as u32) 58 | .input_rate(vk::VertexInputRate::VERTEX) 59 | } 60 | pub fn input_descriptions() -> [vk::VertexInputAttributeDescription; 1] { 61 | [ 62 | // offset_of macro got stabilized in rust 1.77 63 | vk::VertexInputAttributeDescription::default() 64 | .location(0) 65 | .binding(0) 66 | .format(vk::Format::R32G32B32A32_SFLOAT) 67 | .offset(offset_of!(Self, position) as u32), 68 | ] 69 | } 70 | } 71 | 72 | impl Vertex2D { 73 | pub fn binding_description() -> vk::VertexInputBindingDescription { 74 | vk::VertexInputBindingDescription::default() 75 | .binding(0) 76 | .stride(std::mem::size_of::() as u32) 77 | .input_rate(vk::VertexInputRate::VERTEX) 78 | } 79 | pub fn input_descriptions() -> [vk::VertexInputAttributeDescription; 3] { 80 | [ 81 | // offset_of macro got stabilized in rust 1.77 82 | vk::VertexInputAttributeDescription::default() 83 | .location(0) 84 | .binding(0) 85 | .format(vk::Format::R32G32_SFLOAT) 86 | .offset(offset_of!(Self, position) as u32), 87 | vk::VertexInputAttributeDescription::default() 88 | .location(1) 89 | .binding(0) 90 | .format(vk::Format::R32G32_SFLOAT) 91 | .offset(offset_of!(Self, tex_coord) as u32), 92 | vk::VertexInputAttributeDescription::default() 93 | .location(2) 94 | .binding(0) 95 | .format(vk::Format::R8G8B8A8_UNORM) 96 | .offset(offset_of!(Self, color) as u32), 97 | ] 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /crates/vent-runtime/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-runtime" 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 | vent-rendering = { path = "../vent-rendering"} 10 | vent-ui = { path = "../vent-ui"} 11 | vent-assets = { path = "../vent-assets" } 12 | vent-ecs = { path = "../vent-ecs"} 13 | vent-window = { path = "../vent-window"} 14 | vent-logging = { path = "../vent-logging"} 15 | vent-math = { path = "../vent-math"} 16 | 17 | # Rendering 18 | ash = { version= "0.38", default-features = false } 19 | 20 | pollster = "0.3.0" 21 | log = "0.4" 22 | 23 | image = "0.25" 24 | 25 | sysinfo = "0.31" 26 | chrono = "0.4" 27 | 28 | # serde 29 | serde = { version = "1.0", features = ["derive"] } 30 | serde_json = "1.0" 31 | 32 | downcast-rs = "1.2.0" 33 | 34 | [target.'cfg(target_os = "android")'.dependencies] 35 | android_logger = "0.14" 36 | android-activity = { version = "0.6", features = [ "game-activity" ] } 37 | ndk = "0.9.0" 38 | -------------------------------------------------------------------------------- /crates/vent-runtime/README.md: -------------------------------------------------------------------------------- 1 | ### Vent-Runtime 2 | 3 | Vent-Runtime is a critical component of the Vent-Engine. It is responsible for loading all resources created using Vent-Editor dynamically and presenting them to the user in a standalone application. 4 | It is the final product of your development process and allows your users to see and experience the amazing things you have built using the Vent-Editor. 5 | 6 | ## Contributing 7 | 8 | See [Contributing](../../CONTRIBUTING.md) 9 | 10 | ## License 11 | 12 | Vent-Runtime is licensed under the [Apache 2.0 License](../../LICENSE) 13 | -------------------------------------------------------------------------------- /crates/vent-runtime/assets/fonts/Arial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/fonts/Arial.ttf -------------------------------------------------------------------------------- /crates/vent-runtime/assets/fonts/OpenSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/fonts/OpenSans.ttf -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/basic/cube.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/basic/cube.glb -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/10381718147657362067.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/10381718147657362067.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/10388182081421875623.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/10388182081421875623.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/11474523244911310074.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/11474523244911310074.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/11490520546946913238.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/11490520546946913238.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/11872827283454512094.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/11872827283454512094.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/11968150294050148237.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/11968150294050148237.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/1219024358953944284.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/1219024358953944284.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/12501374198249454378.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/12501374198249454378.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/13196865903111448057.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/13196865903111448057.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/13824894030729245199.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/13824894030729245199.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/13982482287905699490.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/13982482287905699490.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/14118779221266351425.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/14118779221266351425.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/14170708867020035030.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/14170708867020035030.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/14267839433702832875.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/14267839433702832875.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/14650633544276105767.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/14650633544276105767.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/15295713303328085182.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/15295713303328085182.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/15722799267630235092.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/15722799267630235092.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/16275776544635328252.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/16275776544635328252.png -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/16299174074766089871.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/16299174074766089871.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/16885566240357350108.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/16885566240357350108.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/17556969131407844942.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/17556969131407844942.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/17876391417123941155.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/17876391417123941155.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/2051777328469649772.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/2051777328469649772.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/2185409758123873465.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/2185409758123873465.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/2299742237651021498.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/2299742237651021498.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/2374361008830720677.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/2374361008830720677.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/2411100444841994089.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/2411100444841994089.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/2775690330959970771.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/2775690330959970771.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/2969916736137545357.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/2969916736137545357.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/332936164838540657.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/332936164838540657.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/3371964815757888145.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/3371964815757888145.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/3455394979645218238.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/3455394979645218238.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/3628158980083700836.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/3628158980083700836.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/3827035219084910048.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/3827035219084910048.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/4477655471536070370.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/4477655471536070370.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/4601176305987539675.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/4601176305987539675.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/466164707995436622.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/466164707995436622.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/4675343432951571524.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/4675343432951571524.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/4871783166746854860.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/4871783166746854860.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/4910669866631290573.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/4910669866631290573.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/4975155472559461469.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/4975155472559461469.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/5061699253647017043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/5061699253647017043.png -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/5792855332885324923.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/5792855332885324923.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/5823059166183034438.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/5823059166183034438.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/6047387724914829168.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/6047387724914829168.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/6151467286084645207.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/6151467286084645207.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/6593109234861095314.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/6593109234861095314.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/6667038893015345571.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/6667038893015345571.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/6772804448157695701.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/6772804448157695701.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/7056944414013900257.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/7056944414013900257.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/715093869573992647.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/715093869573992647.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/7268504077753552595.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/7268504077753552595.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/7441062115984513793.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/7441062115984513793.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/755318871556304029.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/755318871556304029.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/759203620573749278.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/759203620573749278.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/7645212358685992005.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/7645212358685992005.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/7815564343179553343.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/7815564343179553343.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8006627369776289000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8006627369776289000.png -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8051790464816141987.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8051790464816141987.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8114461559286000061.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8114461559286000061.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8481240838833932244.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8481240838833932244.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8503262930880235456.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8503262930880235456.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8747919177698443163.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8747919177698443163.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8750083169368950601.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8750083169368950601.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8773302468495022225.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8773302468495022225.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/8783994986360286082.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/8783994986360286082.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/9288698199695299068.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/9288698199695299068.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/9916269861720640319.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/9916269861720640319.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/Sponza.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/Sponza.bin -------------------------------------------------------------------------------- /crates/vent-runtime/assets/models/test/Sponza-GLTF/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/models/test/Sponza-GLTF/white.png -------------------------------------------------------------------------------- /crates/vent-runtime/assets/shaders/app/2D/gui.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | layout(location = 0) out vec4 outColor; 3 | layout(set = 0, binding = 0) uniform sampler2D sTexture; 4 | layout(location = 0) in struct { 5 | vec4 Color; 6 | vec2 UV; 7 | } In; 8 | void main() { 9 | outColor = In.Color * texture(sTexture, In.UV.st); 10 | } -------------------------------------------------------------------------------- /crates/vent-runtime/assets/shaders/app/2D/gui.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | layout(location = 0) in vec2 pos; 3 | layout(location = 1) in vec2 uv; 4 | layout(location = 2) in vec4 color; 5 | layout(push_constant) uniform uPushConstant { 6 | vec2 uScale; 7 | vec2 uTranslate; 8 | } pc; 9 | 10 | out gl_PerVertex { 11 | vec4 gl_Position; 12 | }; 13 | layout(location = 0) out struct { 14 | vec4 Color; 15 | vec2 UV; 16 | } Out; 17 | 18 | void main() { 19 | Out.Color = color; 20 | Out.UV = uv; 21 | gl_Position = vec4(pos * pc.uScale + pc.uTranslate , 0, 1); 22 | } -------------------------------------------------------------------------------- /crates/vent-runtime/assets/shaders/app/3D/light.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 color; 4 | 5 | layout(location = 0) out vec4 clip_position; 6 | 7 | void main() { 8 | clip_position = vec4(color, 1.0); 9 | } -------------------------------------------------------------------------------- /crates/vent-runtime/assets/shaders/app/3D/light.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(binding = 0) uniform Camera { 4 | mat4 projection; 5 | mat4 view; 6 | } camera; 7 | 8 | layout(binding = 1) uniform Light { 9 | vec3 position; 10 | vec3 color; 11 | } light; 12 | 13 | layout(location = 0) in vec3 in_position; 14 | 15 | layout(location = 0) out vec4 clip_position; 16 | layout(location = 1) out vec3 color; 17 | 18 | const float scale = 1.0; 19 | 20 | void main() { 21 | clip_position = camera.projection * camera.view * vec4(in_position * scale + light.position, 1.0); 22 | color = light.color; 23 | } -------------------------------------------------------------------------------- /crates/vent-runtime/assets/shaders/app/3D/shader.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (binding = 0) uniform sampler2D texture_diffuse; 4 | 5 | layout (binding = 1) uniform Material { 6 | vec4 base_color; 7 | int alpha_mode; 8 | float alpha_cutoff; 9 | } material; 10 | 11 | 12 | // layout (binding = 2) uniform Light { 13 | // vec3 position; 14 | // vec3 color; 15 | // } light; 16 | 17 | layout (location = 0) in vec2 tex_coord; 18 | layout (location = 1) in vec2 normal; 19 | layout (location = 2) in vec3 world_position; 20 | layout (location = 3) in vec3 position; 21 | layout (location = 4) in vec3 view_position; 22 | 23 | 24 | layout (location = 0) out vec4 fragColor; 25 | 26 | // We don't need (or want) much ambient light, so 0.1 is fine 27 | const float ambient_strength = 0.1; 28 | 29 | 30 | 31 | void main() { 32 | vec4 texture = texture(texture_diffuse, tex_coord) * material.base_color; 33 | 34 | if (material.alpha_mode == 2) { // ALPHA MASK 35 | if (texture.a < material.alpha_cutoff) { 36 | discard; 37 | } 38 | } else if (material.alpha_mode == 3) { // BLEND 39 | // todo 40 | } 41 | 42 | // Calculate the ambient color 43 | // vec3 ambient_color = light.color * ambient_strength; 44 | 45 | // // Calculate the light direction 46 | // vec3 light_dir = normalize(light.position - world_position); 47 | 48 | // // Calculate the view direction 49 | // vec3 view_dir = normalize(view_position.xyz - world_position); 50 | 51 | // // Calculate the half vector 52 | // vec3 half_dir = normalize(view_dir + light_dir); 53 | 54 | // // Calculate the diffuse color 55 | // float diffuse_strength = max(dot(world_position, light_dir), 0.0); 56 | // vec3 diffuse_color = light.color * diffuse_strength; 57 | 58 | // // Calculate the specular color 59 | // float specular_strength = pow(max(dot(world_position, half_dir), 0.0), 32.0); 60 | // vec3 specular_color = specular_strength * light.color; 61 | 62 | // // Calculate the final color 63 | // vec3 result = (ambient_color + diffuse_color + specular_color) * texture.xyz; 64 | 65 | fragColor = texture; // vec4(result, 1.0); 66 | } -------------------------------------------------------------------------------- /crates/vent-runtime/assets/shaders/app/3D/shader.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout(location = 0) in vec3 in_position; 4 | layout(location = 1) in vec2 in_tex_coord; 5 | layout(location = 2) in vec3 in_normal; 6 | 7 | layout(push_constant) uniform PushConsts { 8 | vec3 view_position; 9 | mat4 proj_view_trans; 10 | } camera; 11 | 12 | layout(location = 0) out vec2 tex_coord; 13 | layout(location = 1) out vec3 normal; 14 | layout(location = 2) out vec3 world_position; 15 | layout(location = 3) out vec4 position; 16 | layout(location = 4) out vec3 view_position; 17 | 18 | void main() { 19 | tex_coord = in_tex_coord; 20 | normal = in_normal; 21 | world_position = in_position; 22 | position = camera.proj_view_trans * vec4(in_position, 1.0); 23 | view_position = camera.view_position; 24 | 25 | gl_Position = position; 26 | } -------------------------------------------------------------------------------- /crates/vent-runtime/assets/shaders/app/3D/skybox.frag: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (binding = 0) uniform samplerCube samplerCubeMap; 4 | 5 | layout (location = 0) in vec3 inUVW; 6 | 7 | layout (location = 0) out vec4 outFragColor; 8 | 9 | void main() 10 | { 11 | outFragColor = texture(samplerCubeMap, inUVW); 12 | } -------------------------------------------------------------------------------- /crates/vent-runtime/assets/shaders/app/3D/skybox.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (location = 0) in vec3 inPos; 4 | 5 | layout(push_constant) uniform UBO 6 | { 7 | mat4 projection; 8 | mat4 model; 9 | } ubo; 10 | 11 | layout (location = 0) out vec3 outUVW; 12 | 13 | void main() 14 | { 15 | outUVW = inPos; 16 | // Convert cubemap coordinates into Vulkan coordinate space 17 | outUVW.x = -outUVW.x; 18 | // Remove translation from view matrix 19 | mat4 viewMat = mat4(mat3(ubo.model)); 20 | gl_Position = ubo.projection * viewMat * vec4(inPos.xyz, 1.0); 21 | } -------------------------------------------------------------------------------- /crates/vent-runtime/assets/textures/skybox/back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/textures/skybox/back.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/textures/skybox/bottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/textures/skybox/bottom.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/textures/skybox/front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/textures/skybox/front.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/textures/skybox/left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/textures/skybox/left.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/textures/skybox/right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/textures/skybox/right.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/assets/textures/skybox/top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/crates/vent-runtime/assets/textures/skybox/top.jpg -------------------------------------------------------------------------------- /crates/vent-runtime/build.rs: -------------------------------------------------------------------------------- 1 | use std::{env, fs::DirEntry, io::Result}; 2 | 3 | use std::{ 4 | env::var, 5 | fs, 6 | path::{Path, PathBuf}, 7 | process::{Command, Output}, 8 | }; 9 | 10 | fn main() { 11 | // This tells cargo to rerun this script if something in /assets/ changes. 12 | println!("cargo:rerun-if-changed=assets/*"); 13 | 14 | let out_dir = env::var("OUT_DIR").expect("Var: OUT_DIR Not found!"); 15 | copy_dir_all("assets/", out_dir).expect("Failed to copy to resource Folder"); 16 | 17 | if !should_skip_shader_compilation() { 18 | println!("Compiling shaders"); 19 | compile_shaders(&get_shader_source_dir_path()); 20 | } 21 | } 22 | 23 | fn copy_dir_all(src: impl AsRef, dst: impl AsRef) -> Result<()> { 24 | let src = src.as_ref(); 25 | let dst = dst.as_ref(); 26 | fs::create_dir_all(dst)?; 27 | for entry in fs::read_dir(src)? { 28 | let entry = entry?; 29 | let ty = entry.file_type()?; 30 | if ty.is_dir() { 31 | copy_dir_all(entry.path(), dst.join(entry.file_name()))?; 32 | } else { 33 | fs::copy(entry.path(), dst.join(entry.file_name()))?; 34 | } 35 | } 36 | Ok(()) 37 | } 38 | 39 | fn should_skip_shader_compilation() -> bool { 40 | var("SKIP_SHADER_COMPILATION") 41 | .map(|var| var.parse::().unwrap_or(false)) 42 | .unwrap_or(false) 43 | } 44 | 45 | fn compile_shaders(dir: &Path) { 46 | if dir.is_dir() { 47 | for entry in fs::read_dir(dir).unwrap() { 48 | let entry = entry.unwrap(); 49 | let path = entry.path(); 50 | if path.is_dir() { 51 | compile_shaders(&path); 52 | } else { 53 | compile_shader(&entry); 54 | } 55 | } 56 | } 57 | } 58 | 59 | fn compile_shader(file: &DirEntry) { 60 | if file.file_type().unwrap().is_file() { 61 | let path = file.path(); 62 | if let Some(ext) = path.extension() { 63 | if ext == "spv" || ext == "wgsl" { 64 | return; 65 | } 66 | } 67 | 68 | let name = path.file_name().unwrap().to_str().unwrap(); 69 | let output_name = format!("{}.spv", &name); 70 | println!("Found file {:?}.\nCompiling...", path.as_os_str()); 71 | 72 | let result = Command::new("glslangValidator") 73 | .current_dir(path.parent().expect("Shader File has not Parent!")) 74 | .env("--target-env", "vulkan1.3") 75 | .arg("-V") 76 | .arg(&path) 77 | .arg("-o") 78 | .arg(output_name) 79 | .output(); 80 | 81 | handle_program_result(result); 82 | } 83 | } 84 | 85 | fn get_shader_source_dir_path() -> PathBuf { 86 | let path = get_root_path().join("assets/shaders"); 87 | println!("Shader source directory: {:?}", path.as_os_str()); 88 | path 89 | } 90 | 91 | fn get_root_path() -> &'static Path { 92 | Path::new(env!("CARGO_MANIFEST_DIR")) 93 | } 94 | 95 | fn handle_program_result(result: Result) { 96 | match result { 97 | Ok(output) => { 98 | if output.status.success() { 99 | println!("Shader compilation succedeed."); 100 | print!( 101 | "stdout: {}", 102 | String::from_utf8(output.stdout) 103 | .unwrap_or("Failed to print program stdout".to_string()) 104 | ); 105 | } else { 106 | eprintln!("Shader compilation failed. Status: {}", output.status); 107 | eprint!( 108 | "stdout: {}", 109 | String::from_utf8(output.stdout) 110 | .unwrap_or("Failed to print program stdout".to_string()) 111 | ); 112 | eprint!( 113 | "stderr: {}", 114 | String::from_utf8(output.stderr) 115 | .unwrap_or("Failed to print program stderr".to_string()) 116 | ); 117 | eprintln!("Shader compilation failed. Status: {}", output.status); 118 | } 119 | } 120 | Err(error) => { 121 | eprintln!("Failed to compile shader. Cause: {}", error); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/lib.rs: -------------------------------------------------------------------------------- 1 | use project::VentApplicationProject; 2 | use render::{camera::camera_controller3d::CameraController3D, DefaultRuntimeRenderer}; 3 | 4 | use util::input_handler::InputHandler; 5 | use vent_window::{Window, WindowEvent}; 6 | 7 | pub mod project; 8 | pub mod render; 9 | pub mod util; 10 | 11 | #[derive(Default)] 12 | pub struct VentApplication { 13 | project: VentApplicationProject, 14 | } 15 | 16 | impl VentApplication { 17 | pub fn new(project: VentApplicationProject) -> Self { 18 | Self { project } 19 | } 20 | 21 | pub fn start(self) { 22 | let project = self.project; 23 | let app_window = Window::new(project.window_settings.clone()); 24 | 25 | // TODO 26 | let mut renderer = DefaultRuntimeRenderer::new(&project, &app_window); 27 | 28 | let mut input_handler = InputHandler::default(); 29 | 30 | let mut controller = CameraController3D::new(5.0, 1.0); 31 | let mut delta_time = 0.0; 32 | 33 | // TODO, Handle scale factor change 34 | app_window.poll(move |event| { 35 | controller.process_keyboard( 36 | renderer.camera.downcast_mut().expect("TODO"), 37 | &input_handler, 38 | delta_time, 39 | ); 40 | renderer.progress_event(&event); 41 | match event { 42 | WindowEvent::Close => {} // Closes automaticly 43 | WindowEvent::Key { key, state } => input_handler.set_key(key, state), 44 | WindowEvent::MouseButton { button, state } => { 45 | controller.process_mouse_input(&button, &state); 46 | } 47 | WindowEvent::Resize { 48 | new_width, 49 | new_height, 50 | } => { 51 | renderer.resize((new_width, new_height)); 52 | } 53 | WindowEvent::Draw => delta_time = renderer.render(), 54 | WindowEvent::MouseMotion { x, y } => controller.process_mouse_movement( 55 | renderer.camera.downcast_mut().expect("TODO"), 56 | x, 57 | y, 58 | delta_time, 59 | ), // Default, 60 | } 61 | }); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // This disables the Windows Console in release mode 2 | 3 | use vent_logging::Logger; 4 | use vent_runtime::{util::crash::init_panic_hook, VentApplication}; 5 | 6 | fn main() { 7 | init_panic_hook(); 8 | Logger::init(); 9 | let app = VentApplication::default(); 10 | app.start(); 11 | } 12 | 13 | #[cfg(target_os = "android")] 14 | use android_activity::{ 15 | input::{InputEvent, KeyAction, KeyEvent, KeyMapChar, MotionAction}, 16 | AndroidApp, InputStatus, MainEvent, PollEvent, 17 | }; 18 | 19 | #[cfg(target_os = "android")] 20 | #[no_mangle] 21 | fn android_main(app: AndroidApp) { 22 | VentApplication::default(); 23 | } 24 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/project/mod.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::fs::{File, OpenOptions}; 3 | use vent_window::WindowAttribs; 4 | 5 | use crate::{render::Dimension, util::version::Version}; 6 | 7 | /// Basic Project Information's 8 | #[derive(Serialize, Deserialize)] 9 | pub struct VentApplicationProject { 10 | // Name of the Application 11 | pub name: String, 12 | // Version of the Application 13 | pub version: Version, 14 | // Inital Window settings, can be changed later 15 | pub window_settings: WindowAttribs, 16 | // Inital Render settings, can be changed later 17 | pub render_settings: RenderSettings, 18 | } 19 | 20 | impl Default for VentApplicationProject { 21 | fn default() -> Self { 22 | VentApplicationProject { 23 | name: "Placeholder".to_string(), 24 | version: Version::new(1, 0, 0), 25 | window_settings: WindowAttribs::default().with_title("Placeholder".to_string()), 26 | render_settings: RenderSettings { 27 | dimension: Dimension::D3, 28 | vsync: false, 29 | }, 30 | } 31 | } 32 | } 33 | 34 | #[derive(Serialize, Deserialize)] 35 | pub struct RenderSettings { 36 | // Inital vsync setting, can be changed later 37 | pub dimension: Dimension, 38 | pub vsync: bool, 39 | } 40 | 41 | impl VentApplicationProject { 42 | // Deserialize the project data from a .vent file 43 | pub fn deserialize(&self, path: &str) -> Result<(), std::io::Error> { 44 | let path_str = format!("{}/project.vent", path); 45 | let file = OpenOptions::new() 46 | .write(true) 47 | .truncate(true) 48 | .create(true) 49 | .open(path_str)?; 50 | log::debug!("Saving {}", path); 51 | serde_json::to_writer(file, self)?; 52 | 53 | Ok(()) 54 | } 55 | 56 | // Serialize the project data from a .vent file 57 | pub fn serialize(path: &str) -> Result { 58 | let path_str = format!("{}/project.vent", path); 59 | log::debug!("Loading {}", path); 60 | let file = File::open(path_str)?; 61 | 62 | let project = serde_json::from_reader(file)?; 63 | 64 | Ok(project) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/camera/camera_controller3d.rs: -------------------------------------------------------------------------------- 1 | use vent_math::vec::{vec2::Vec2, vec3::Vec3}; 2 | use vent_window::keyboard::Key; 3 | 4 | use crate::util::input_handler::InputHandler; 5 | 6 | use super::Camera3D; 7 | 8 | pub struct CameraController3D { 9 | speed: f32, 10 | sensitivity_x: f32, 11 | sensitivity_y: f32, 12 | 13 | old_x: f64, 14 | old_y: f64, 15 | mouse_left_down: bool, 16 | } 17 | 18 | impl CameraController3D { 19 | #[inline] 20 | #[must_use] 21 | pub fn new(speed: f32, sensitivity: f32) -> Self { 22 | Self { 23 | speed, 24 | sensitivity_x: sensitivity, 25 | sensitivity_y: sensitivity, 26 | mouse_left_down: false, 27 | old_x: 0.0, 28 | old_y: 0.0, 29 | } 30 | } 31 | 32 | pub fn process_keyboard( 33 | &self, 34 | camera: &mut Camera3D, 35 | input_handler: &InputHandler, 36 | delta_time: f32, 37 | ) { 38 | let (sin_pitch, cos_pitch) = camera.rotation.x.sin_cos(); 39 | let (sin_yaw, cos_yaw) = camera.rotation.y.sin_cos(); 40 | let mut moved = false; 41 | 42 | if input_handler.is_pressed(Key::W) | input_handler.is_pressed(Key::Uparrow) { 43 | camera.position += Vec3::new(cos_pitch * cos_yaw, sin_pitch, -cos_pitch * sin_yaw) 44 | * self.speed 45 | * delta_time; 46 | moved = true; 47 | } 48 | if input_handler.is_pressed(Key::S) | input_handler.is_pressed(Key::Downarrow) { 49 | camera.position -= Vec3::new(cos_pitch * cos_yaw, sin_pitch, -cos_pitch * sin_yaw) 50 | * self.speed 51 | * delta_time; 52 | moved = true; 53 | } 54 | if input_handler.is_pressed(Key::A) | input_handler.is_pressed(Key::Leftarrow) { 55 | camera.position -= Vec3::new(sin_yaw, 0.0, cos_yaw) * self.speed * delta_time; 56 | moved = true; 57 | } 58 | if input_handler.is_pressed(Key::D) | input_handler.is_pressed(Key::Rightarrow) { 59 | camera.position += Vec3::new(sin_yaw, 0.0, cos_yaw) * self.speed * delta_time; 60 | moved = true; 61 | } 62 | if input_handler.is_pressed(Key::Space) { 63 | camera.position.y += self.speed * delta_time; 64 | moved = true; 65 | } 66 | if input_handler.is_pressed(Key::ShiftL) { 67 | camera.position.y -= self.speed * delta_time; 68 | moved = true; 69 | } 70 | if moved { 71 | camera.recreate_view(); 72 | } 73 | } 74 | 75 | pub fn process_mouse_input( 76 | &mut self, 77 | button: &vent_window::mouse::Button, 78 | state: &vent_window::mouse::ButtonState, 79 | ) { 80 | if button == &vent_window::mouse::Button::LEFT { 81 | self.mouse_left_down = state == &vent_window::mouse::ButtonState::Pressed; 82 | } 83 | } 84 | 85 | pub fn process_mouse_movement( 86 | &mut self, 87 | camera: &mut Camera3D, 88 | mouse_x: f64, 89 | mouse_y: f64, 90 | delta_time: f32, 91 | ) { 92 | if self.mouse_left_down { 93 | let deltaposition = 94 | Vec2::new((mouse_x - self.old_x) as f32, (mouse_y - self.old_y) as f32); 95 | self.old_x = mouse_x; 96 | self.old_y = mouse_y; 97 | 98 | let moveposition = 99 | deltaposition * Vec2::new(self.sensitivity_x, self.sensitivity_y) * delta_time; 100 | camera.rotation.x += moveposition.x.to_radians(); 101 | camera.rotation.y += moveposition.y.to_radians(); 102 | camera.recreate_direction(); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/camera/mod.rs: -------------------------------------------------------------------------------- 1 | use ash::vk; 2 | use downcast_rs::{impl_downcast, Downcast}; 3 | use vent_math::{ 4 | scalar::{mat4::Mat4, quat::Quat}, 5 | vec::{vec2::Vec2, vec3::Vec3}, 6 | }; 7 | use vent_rendering::{any_as_u8_slice, instance::VulkanInstance}; 8 | 9 | use super::{d3::Camera3DData, Dimension}; 10 | 11 | pub mod camera_controller3d; 12 | 13 | pub trait Camera: Downcast { 14 | fn new(aspect_ratio: f32) -> Self 15 | where 16 | Self: Sized; 17 | 18 | fn recreate_projection(&mut self, aspect_ratio: f32); 19 | } 20 | impl_downcast!(Camera); 21 | 22 | pub fn from_dimension(aspect_ratio: f32, dimension: &Dimension) -> Box { 23 | match dimension { 24 | Dimension::D2 => Box::new(Camera2D::new(aspect_ratio)), 25 | Dimension::D3 => Box::new(Camera3D::new(aspect_ratio)), 26 | } 27 | } 28 | 29 | #[allow(dead_code)] 30 | pub struct Camera2D { 31 | position: Vec2, 32 | } 33 | 34 | impl Camera for Camera2D { 35 | #[inline] 36 | #[must_use] 37 | fn new(_aspect_ratio: f32) -> Self 38 | where 39 | Self: Sized, 40 | { 41 | Self { 42 | position: Vec2::ZERO, 43 | } 44 | } 45 | 46 | fn recreate_projection(&mut self, _aspect_ratio: f32) { 47 | todo!() 48 | } 49 | } 50 | 51 | pub struct Camera3D { 52 | fovy: f32, 53 | znear: f32, 54 | zfar: f32, 55 | pub ubo: Camera3DData, 56 | pub projection: Mat4, 57 | pub view: Mat4, 58 | pub transformation: Mat4, 59 | 60 | pub position: Vec3, 61 | pub direction: Vec3, 62 | pub rotation: Quat, 63 | } 64 | 65 | impl Camera for Camera3D { 66 | #[inline] 67 | #[must_use] 68 | fn new(aspect_ratio: f32) -> Self 69 | where 70 | Self: Sized, 71 | { 72 | let mut cam = Self { 73 | fovy: 60.0, 74 | znear: 0.1, 75 | zfar: 10000.0, 76 | rotation: Quat::IDENTITY, 77 | position: Vec3::ZERO, 78 | ubo: Default::default(), 79 | projection: Mat4::IDENTITY, 80 | direction: Vec3::ZERO, 81 | view: Mat4::IDENTITY, 82 | transformation: Mat4::IDENTITY, 83 | }; 84 | // we should configure 85 | cam.recreate_projection(aspect_ratio); 86 | cam.recreate_direction(); 87 | cam.calc_matrix(); 88 | 89 | cam 90 | } 91 | 92 | // Only recreate when: 93 | // FOV is changed 94 | // Aspect ratio is changed 95 | // znear is changed 96 | // zfar is changed 97 | fn recreate_projection(&mut self, aspect_ratio: f32) { 98 | self.projection = 99 | Mat4::perspective_rh(self.fovy.to_radians(), aspect_ratio, self.znear, self.zfar); 100 | // Flip the cameras prospective upside down 101 | self.projection.y_axis.y *= -1.0; 102 | } 103 | } 104 | 105 | impl Camera3D { 106 | pub fn update_set() {} 107 | 108 | /// Call when position changed 109 | pub fn recreate_view(&mut self) { 110 | let view = Mat4::look_at_rh(self.position, self.position + self.direction, Vec3::Y); 111 | self.ubo.view_position = self.position; 112 | self.view = view; 113 | } 114 | 115 | pub fn calc_matrix(&mut self) { 116 | self.ubo.proj_view_trans = self.projection * self.view * self.transformation; 117 | } 118 | 119 | pub fn write( 120 | &self, 121 | instance: &VulkanInstance, 122 | layout: vk::PipelineLayout, 123 | command_buffer: vk::CommandBuffer, 124 | ) { 125 | unsafe { 126 | instance.device.cmd_push_constants( 127 | command_buffer, 128 | layout, 129 | vk::ShaderStageFlags::VERTEX, 130 | 0, 131 | any_as_u8_slice(&self.ubo), 132 | ) 133 | } 134 | } 135 | 136 | #[inline] 137 | /// Call when rotation changed 138 | pub fn recreate_direction(&mut self) { 139 | let (sin_yaw, cos_yaw) = self.rotation.x.sin_cos(); 140 | let (sin_pitch, cos_pitch) = self.rotation.y.sin_cos(); 141 | 142 | self.direction = Vec3::new(cos_pitch * cos_yaw, sin_pitch, cos_pitch * sin_yaw).normalize(); 143 | self.recreate_view() 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/d2/mod.rs: -------------------------------------------------------------------------------- 1 | use ash::vk; 2 | 3 | use super::{camera::Camera, Renderer}; 4 | 5 | #[allow(dead_code)] 6 | pub struct UBO2D {} 7 | 8 | pub struct Renderer2D {} 9 | 10 | impl Renderer for Renderer2D { 11 | fn init( 12 | _instance: &mut vent_rendering::instance::VulkanInstance, 13 | _camera: &mut dyn Camera, 14 | ) -> Self 15 | where 16 | Self: Sized, 17 | { 18 | todo!() 19 | } 20 | 21 | fn resize( 22 | &mut self, 23 | _instance: &mut vent_rendering::instance::VulkanInstance, 24 | _new_size: (u32, u32), 25 | _camera: &mut dyn Camera, 26 | ) { 27 | todo!() 28 | } 29 | 30 | fn render( 31 | &mut self, 32 | _instance: &vent_rendering::instance::VulkanInstance, 33 | _image_index: u32, 34 | _command_buffer: vk::CommandBuffer, 35 | _camera: &mut dyn Camera, 36 | ) { 37 | todo!() 38 | } 39 | 40 | fn destroy(&mut self, _instance: &vent_rendering::instance::VulkanInstance) { 41 | todo!() 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/d3/light_renderer.rs: -------------------------------------------------------------------------------- 1 | use ash::vk; 2 | use vent_assets::io::file::FileAsset; 3 | use vent_math::vec::vec3::Vec3; 4 | use vent_rendering::{ 5 | instance::VulkanInstance, mesh::Mesh3D, pipeline::VulkanPipeline, vertex::Vertex3D, 6 | }; 7 | 8 | #[allow(dead_code)] 9 | #[repr(C)] 10 | pub struct LightUBO { 11 | pub position: Vec3, 12 | pub color: Vec3, 13 | } 14 | 15 | pub struct LightRenderer { 16 | pipeline: VulkanPipeline, 17 | } 18 | 19 | #[allow(dead_code)] 20 | impl LightRenderer { 21 | pub fn new(instance: &VulkanInstance) -> Self { 22 | let vertex_shader = FileAsset::new("assets/shaders/app/3D/light.vert.spv"); 23 | let fragment_shader = FileAsset::new("assets/shaders/app/3D/light.frag.spv"); 24 | 25 | let desc_layout_bindings = [ 26 | vk::DescriptorSetLayoutBinding { 27 | binding: 0, 28 | descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, 29 | descriptor_count: 1, 30 | stage_flags: vk::ShaderStageFlags::VERTEX, 31 | ..Default::default() 32 | }, 33 | vk::DescriptorSetLayoutBinding { 34 | binding: 1, 35 | descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, 36 | descriptor_count: 1, 37 | stage_flags: vk::ShaderStageFlags::VERTEX, 38 | ..Default::default() 39 | }, 40 | ]; 41 | 42 | let pipeline = VulkanPipeline::create_simple_pipeline( 43 | instance, 44 | vertex_shader.root_path(), 45 | fragment_shader.root_path(), 46 | &[Vertex3D::binding_description()], 47 | &Vertex3D::input_descriptions(), 48 | instance.surface_resolution, 49 | &[], 50 | &desc_layout_bindings, 51 | ); 52 | 53 | Self { pipeline } 54 | } 55 | 56 | pub fn render( 57 | &self, 58 | instance: &VulkanInstance, 59 | command_buffer: vk::CommandBuffer, 60 | _buffer_index: usize, 61 | mesh: &Mesh3D, 62 | ) { 63 | unsafe { 64 | instance.device.cmd_bind_pipeline( 65 | command_buffer, 66 | vk::PipelineBindPoint::GRAPHICS, 67 | self.pipeline.pipeline, 68 | ) 69 | }; 70 | 71 | mesh.bind(&instance.device, command_buffer); 72 | mesh.draw(&instance.device, command_buffer); 73 | } 74 | 75 | pub fn destroy(&mut self, device: &ash::Device) { 76 | self.pipeline.destroy(device); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/d3/skybox_renderer.rs: -------------------------------------------------------------------------------- 1 | use std::mem::size_of; 2 | 3 | use ash::vk; 4 | use image::GenericImageView; 5 | use vent_assets::io::file::FileAsset; 6 | use vent_math::scalar::mat4::Mat4; 7 | use vent_rendering::{ 8 | any_as_u8_slice, 9 | image::{SkyBoxImages, VulkanImage}, 10 | instance::VulkanInstance, 11 | mesh::Mesh3D, 12 | pipeline::VulkanPipeline, 13 | vertex::VertexPos3D, 14 | }; 15 | 16 | use crate::render::{camera::Camera3D, d3::create_simple_cube}; 17 | 18 | #[allow(dead_code)] 19 | pub struct SkyBoxRenderer { 20 | pipeline: VulkanPipeline, 21 | image: VulkanImage, 22 | descriptor_pool: vk::DescriptorPool, 23 | push_constants: SkyBoxUBO, 24 | descriptor_sets: Vec, 25 | cube: Mesh3D, 26 | } 27 | 28 | #[repr(C)] 29 | pub struct SkyBoxUBO { 30 | pub projection: Mat4, 31 | pub model: Mat4, 32 | } 33 | 34 | impl SkyBoxRenderer { 35 | pub fn new(instance: &VulkanInstance, images: SkyBoxImages) -> Self { 36 | log::debug!("Creating skybox"); 37 | let vertex_shader = FileAsset::new("assets/shaders/app/3D/skybox.vert.spv"); 38 | let fragment_shader = FileAsset::new("assets/shaders/app/3D/skybox.frag.spv"); 39 | 40 | let desc_layout_bindings = [vk::DescriptorSetLayoutBinding { 41 | binding: 0, 42 | descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, 43 | descriptor_count: 1, 44 | stage_flags: vk::ShaderStageFlags::FRAGMENT, 45 | ..Default::default() 46 | }]; 47 | 48 | let push_constant_range = vk::PushConstantRange::default() 49 | .size(size_of::() as u32) 50 | .stage_flags(vk::ShaderStageFlags::VERTEX); 51 | 52 | let pipeline = VulkanPipeline::create_simple_pipeline( 53 | instance, 54 | vertex_shader.root_path(), 55 | fragment_shader.root_path(), 56 | &[VertexPos3D::binding_description()], 57 | &VertexPos3D::input_descriptions(), 58 | instance.surface_resolution, 59 | &[push_constant_range], 60 | &desc_layout_bindings, 61 | ); 62 | let cube = create_simple_cube(instance); 63 | let push_constants = SkyBoxUBO { 64 | projection: Mat4::IDENTITY, 65 | model: Mat4::IDENTITY, 66 | }; 67 | 68 | let descriptor_pool = 69 | Self::create_descriptor_pool(instance.swapchain_images.len() as u32, &instance.device); 70 | 71 | let descriptor_sets = VulkanInstance::allocate_descriptor_sets( 72 | &instance.device, 73 | descriptor_pool, 74 | pipeline.descriptor_set_layout, 75 | instance.swapchain_images.len(), 76 | ); 77 | 78 | let images = [ 79 | image::open(images.right).unwrap(), 80 | image::open(images.left).unwrap(), 81 | image::open(images.top).unwrap(), 82 | image::open(images.bottom).unwrap(), 83 | image::open(images.front).unwrap(), 84 | image::open(images.back).unwrap(), 85 | ]; 86 | let image_size = images[0].dimensions(); 87 | 88 | let image = VulkanImage::load_cubemap( 89 | instance, 90 | images, 91 | vk::Extent2D { 92 | width: image_size.0, 93 | height: image_size.1, 94 | }, 95 | ); 96 | 97 | for &descriptor_set in descriptor_sets.iter() { 98 | let diffuse_texture = ℑ 99 | 100 | let image_info = vk::DescriptorImageInfo::default() 101 | .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL) 102 | .image_view(diffuse_texture.image_view) 103 | .sampler(diffuse_texture.sampler); 104 | 105 | let desc_sets = [vk::WriteDescriptorSet { 106 | dst_set: descriptor_set, 107 | dst_binding: 0, // From DescriptorSetLayoutBinding 108 | descriptor_count: 1, 109 | descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, 110 | p_image_info: &image_info, 111 | ..Default::default() 112 | }]; 113 | 114 | unsafe { 115 | instance.device.update_descriptor_sets(&desc_sets, &[]); 116 | } 117 | } 118 | 119 | Self { 120 | pipeline, 121 | cube, 122 | image, 123 | push_constants, 124 | descriptor_pool, 125 | descriptor_sets, 126 | } 127 | } 128 | 129 | pub fn create_descriptor_pool( 130 | swapchain_count: u32, 131 | device: &ash::Device, 132 | ) -> vk::DescriptorPool { 133 | let pool_sizes = [vk::DescriptorPoolSize { 134 | ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, 135 | descriptor_count: 2 * swapchain_count, 136 | }]; 137 | 138 | let create_info = vk::DescriptorPoolCreateInfo::default() 139 | .pool_sizes(&pool_sizes) 140 | .max_sets(2 * swapchain_count); 141 | 142 | unsafe { device.create_descriptor_pool(&create_info, None) }.unwrap() 143 | } 144 | #[allow(dead_code)] 145 | pub fn draw( 146 | &mut self, 147 | device: &ash::Device, 148 | command_buffer: vk::CommandBuffer, 149 | camera: &Camera3D, 150 | buffer_index: usize, 151 | ) { 152 | self.push_constants = SkyBoxUBO { 153 | projection: camera.projection, 154 | model: camera.view, 155 | }; 156 | unsafe { 157 | device.cmd_push_constants( 158 | command_buffer, 159 | self.pipeline.pipeline_layout, 160 | vk::ShaderStageFlags::VERTEX, 161 | 0, 162 | any_as_u8_slice(&self.push_constants), 163 | ); 164 | device.cmd_bind_pipeline( 165 | command_buffer, 166 | vk::PipelineBindPoint::GRAPHICS, 167 | self.pipeline.pipeline, 168 | ); 169 | device.cmd_bind_descriptor_sets( 170 | command_buffer, 171 | vk::PipelineBindPoint::GRAPHICS, 172 | self.pipeline.pipeline_layout, 173 | 0, 174 | &self.descriptor_sets[buffer_index..=buffer_index], 175 | &[], 176 | ) 177 | }; 178 | self.cube.bind(device, command_buffer); 179 | self.cube.draw(device, command_buffer); 180 | } 181 | 182 | pub fn destroy(&mut self, device: &ash::Device) { 183 | self.pipeline.destroy(device); 184 | self.cube.destroy(device); 185 | self.image.destroy(device); 186 | unsafe { 187 | device.destroy_descriptor_pool(self.descriptor_pool, None); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/gui/debug_gui.rs: -------------------------------------------------------------------------------- 1 | use ash::vk; 2 | 3 | pub struct RenderData { 4 | pub fps: u32, 5 | pub frame_time: f32, 6 | } 7 | 8 | impl Default for RenderData { 9 | fn default() -> Self { 10 | Self { 11 | fps: 1, 12 | frame_time: 1.0, 13 | } 14 | } 15 | } 16 | 17 | pub struct DebugGUI { 18 | _properties: vk::PhysicalDeviceProperties, 19 | } 20 | 21 | impl DebugGUI { 22 | pub const fn new(_properties: vk::PhysicalDeviceProperties) -> Self { 23 | Self { _properties } 24 | } 25 | } 26 | 27 | // impl GUI for DebugGUI { 28 | // fn update(&mut self, render_data: &RenderData) {} 29 | // // fn update(&mut self, ctx: &egui::Context, render_data: &RenderData) { 30 | // // egui::Window::new("Debug").show(ctx, |ui| { 31 | // // ui.label(format!("FPS: {}", render_data.fps)); 32 | // // ui.label(format!("Frame Time: {}ms", render_data.frame_time)); 33 | 34 | // // ui.label(format!("Device: {:?}", self.properties.device_name)); 35 | // // ui.label(format!("Device Type: {:?}", self.properties.device_type)); 36 | // // ui.label(format!( 37 | // // "Driver: {}, API Version: {}", 38 | // // self.properties.driver_version, self.properties.api_version 39 | // // )); 40 | // // }); 41 | // // } 42 | // } 43 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/gui/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod debug_gui; 2 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/model.rs: -------------------------------------------------------------------------------- 1 | use vent_math::scalar::{mat4::Mat4, quat::Quat}; 2 | 3 | pub struct Entity3D { 4 | pub model: vent_assets::Model3D, 5 | pub transformation_matrix: Mat4, 6 | } 7 | 8 | impl Entity3D { 9 | pub fn new(model: vent_assets::Model3D) -> Self { 10 | Self { 11 | transformation_matrix: Self::calc_trans_matrix(&model), 12 | model, 13 | } 14 | } 15 | 16 | pub fn calc_trans_matrix(model: &vent_assets::Model3D) -> Mat4 { 17 | let rotation_quat = Quat::from_scaled_axis(Quat::from_array(model.rotation).xyz()); 18 | Mat4::from_scale_rotation_translation( 19 | model.scale.into(), 20 | rotation_quat, 21 | model.position.into(), 22 | ) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/render/model_renderer.rs: -------------------------------------------------------------------------------- 1 | use ash::vk::{self}; 2 | use std::collections::HashMap; 3 | use vent_ecs::entity::Entity; 4 | use vent_rendering::instance::VulkanInstance; 5 | 6 | use super::{camera::Camera3D, model::Entity3D}; 7 | 8 | #[derive(Default)] 9 | pub struct ModelRenderer3D { 10 | map: HashMap, 11 | } 12 | 13 | #[allow(dead_code)] 14 | impl ModelRenderer3D { 15 | #[inline] 16 | pub fn insert(&mut self, entity: Entity, mesh: Entity3D) { 17 | self.map.insert(entity, mesh); 18 | } 19 | 20 | #[inline] 21 | pub fn remove(&mut self, entity: Entity) { 22 | self.map.remove(&entity); 23 | } 24 | 25 | #[inline] 26 | #[must_use] 27 | pub fn get(&self, entity: Entity) -> Option<&Entity3D> { 28 | self.map.get(&entity) 29 | } 30 | 31 | #[inline] 32 | #[must_use] 33 | pub fn get_mut(&mut self, entity: Entity) -> Option<&mut Entity3D> { 34 | self.map.get_mut(&entity) 35 | } 36 | 37 | #[inline] 38 | #[must_use] 39 | pub fn iter(&self) -> std::collections::hash_map::Iter { 40 | self.map.iter() 41 | } 42 | 43 | #[inline] 44 | #[must_use] 45 | pub fn iter_mut(&mut self) -> std::collections::hash_map::IterMut { 46 | self.map.iter_mut() 47 | } 48 | 49 | pub fn record_buffer( 50 | &self, 51 | instance: &VulkanInstance, 52 | command_buffer: vk::CommandBuffer, 53 | buffer_index: usize, 54 | pipeline_layout: vk::PipelineLayout, 55 | camera: &mut Camera3D, 56 | ) { 57 | for model in self.map.values() { 58 | camera.transformation = Entity3D::calc_trans_matrix(&model.model); 59 | camera.calc_matrix(); 60 | camera.write(instance, pipeline_layout, command_buffer); 61 | 62 | model.model.draw( 63 | &instance.device, 64 | pipeline_layout, 65 | command_buffer, 66 | buffer_index, 67 | true, 68 | ); 69 | } 70 | } 71 | 72 | pub fn destroy_all(&mut self, device: &ash::Device) { 73 | for model in self.map.values_mut() { 74 | model.model.destroy(device) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/util/crash.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, Local}; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::panic::{self, PanicHookInfo}; 5 | use sysinfo::System; 6 | 7 | // Crash Handler 8 | 9 | #[inline] 10 | pub fn init_panic_hook() { 11 | panic::set_hook(Box::new(panic_handler)); 12 | } 13 | 14 | fn panic_handler(pi: &PanicHookInfo) { 15 | eprintln!("Crash: {}", pi); 16 | log_crash(pi).expect("Failed to Log Crash File"); 17 | // show_error_dialog(pi); 18 | } 19 | 20 | fn log_crash(pi: &PanicHookInfo) -> std::io::Result<()> { 21 | let timestamp: DateTime = Local::now(); 22 | 23 | let sys = System::new_all(); 24 | // let drivers = get_driver_information(); // Implement this function to retrieve driver information 25 | 26 | // Generate log file name based on timestamp 27 | let log_file_name = format!("crash/crash_log_{}.log", timestamp.format("%Y%m%d%H%M%S")); 28 | 29 | // Create and write crash information to the log file 30 | 31 | let mut f = File::create(log_file_name)?; 32 | let mut perms = f.metadata()?.permissions(); 33 | perms.set_readonly(true); 34 | f.set_permissions(perms)?; 35 | 36 | writeln!(&mut f, "--Crash Log--")?; 37 | writeln!( 38 | &mut f, 39 | "System kernel version: {:?}", 40 | sysinfo::System::kernel_version() 41 | )?; 42 | writeln!( 43 | &mut f, 44 | "System OS version: {:?}", 45 | sysinfo::System::os_version() 46 | )?; 47 | writeln!( 48 | &mut f, 49 | "System host name: {:?}", 50 | sysinfo::System::host_name() 51 | )?; 52 | 53 | writeln!( 54 | &mut f, 55 | "System Core Count: {:?}", 56 | sys.physical_core_count() 57 | )?; 58 | writeln!( 59 | &mut f, 60 | "System Total Memory: {:?}", 61 | sys.total_memory() 62 | )?; 63 | 64 | // writeln!(&mut f, "Driver Information: {}", drivers)?; 65 | writeln!(&mut f, "Crash Info: {:?}", format!("{:?}", pi))?; 66 | Ok(()) 67 | } 68 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/util/input_handler.rs: -------------------------------------------------------------------------------- 1 | use vent_window::keyboard::{Key, KeyState}; 2 | 3 | #[derive(Default)] 4 | pub struct InputHandler { 5 | pressed_keys: Vec, 6 | } 7 | 8 | impl InputHandler { 9 | pub fn set_key(&mut self, key: Key, state: KeyState) { 10 | if state == KeyState::Pressed { 11 | self.press_key(key) 12 | } else if state == KeyState::Released { 13 | self.release_key(key) 14 | } 15 | } 16 | 17 | pub fn press_key(&mut self, key: Key) { 18 | self.pressed_keys.push(key); 19 | } 20 | 21 | pub fn is_pressed(&self, key: Key) -> bool { 22 | self.pressed_keys.contains(&key) 23 | } 24 | 25 | pub fn release_key(&mut self, key: Key) { 26 | let index = self.pressed_keys.iter().position(|x| *x == key); 27 | // We check because there might be invalid keys 28 | if let Some(index) = index { 29 | self.pressed_keys.remove(index); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod crash; 2 | pub mod input_handler; 3 | pub mod version; 4 | -------------------------------------------------------------------------------- /crates/vent-runtime/src/util/version.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] 4 | pub struct Version { 5 | pub major: u32, 6 | pub minor: u32, 7 | pub patch: u32, 8 | } 9 | 10 | impl Version { 11 | pub const fn new(major: u32, minor: u32, patch: u32) -> Self { 12 | Version { 13 | major, 14 | minor, 15 | patch, 16 | } 17 | } 18 | 19 | pub fn parse(&self) -> u32 { 20 | ((self.major) << 22) | ((self.minor) << 12) | (self.patch) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/vent-sdk/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-sdk" 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 | -------------------------------------------------------------------------------- /crates/vent-sdk/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod utils; 2 | -------------------------------------------------------------------------------- /crates/vent-sdk/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod stopwatch; 2 | -------------------------------------------------------------------------------- /crates/vent-sdk/src/utils/stopwatch.rs: -------------------------------------------------------------------------------- 1 | use std::time::{Duration, Instant}; 2 | 3 | pub struct Stopwatch { 4 | start: Option, 5 | elapsed: Duration, 6 | } 7 | 8 | impl Stopwatch { 9 | pub const fn new() -> Self { 10 | Self { 11 | start: None, 12 | elapsed: Duration::ZERO, 13 | } 14 | } 15 | 16 | pub fn new_and_start() -> Self { 17 | let mut sw = Self::new(); 18 | sw.start(); 19 | sw 20 | } 21 | 22 | pub fn start(&mut self) { 23 | self.start = Some(Instant::now()); 24 | } 25 | 26 | pub fn stop(&mut self) { 27 | self.start = None; 28 | } 29 | 30 | pub fn elapsed(&self) -> Duration { 31 | match self.start { 32 | Some(t1) => t1.elapsed() + self.elapsed, 33 | None => self.elapsed, 34 | } 35 | } 36 | 37 | pub fn elapsed_ms(&self) -> u64 { 38 | let dur = self.elapsed(); 39 | dur.as_secs() * 1000 + dur.subsec_millis() as u64 40 | } 41 | } 42 | 43 | impl Default for Stopwatch { 44 | fn default() -> Self { 45 | Self::new() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /crates/vent-ui/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-ui" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | [dependencies] 7 | vent-assets = { path = "../vent-assets"} 8 | vent-rendering = { path = "../vent-rendering"} 9 | vent-math = { path = "../vent-math"} 10 | ash = { version= "0.38", default-features = false } 11 | 12 | log = "0.4" 13 | 14 | ab_glyph = { version = "0.2.28" } 15 | # cosmic-text = "0.12" 16 | image = "0.25" 17 | 18 | -------------------------------------------------------------------------------- /crates/vent-ui/src/font/ab_glyph.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, path::Path}; 2 | 3 | use ab_glyph::{point, Font, FontVec, Glyph, PxScale, ScaleFont}; 4 | use ash::vk::{self}; 5 | use image::{DynamicImage, Rgba}; 6 | use vent_math::vec::vec2::Vec2; 7 | use vent_rendering::{image::VulkanImage, instance::VulkanInstance}; 8 | 9 | use super::Character; 10 | 11 | pub struct AbGlyphLoader {} 12 | 13 | pub const CHARACTERS_SIZE: u32 = 256; // UTF-8 14 | 15 | impl AbGlyphLoader { 16 | // Loads an new Font 17 | pub fn load

( 18 | path: P, 19 | descriptor_set_layout: vk::DescriptorSetLayout, 20 | descriptor_pool: vk::DescriptorPool, 21 | instance: &mut VulkanInstance, 22 | ) -> super::Font 23 | where 24 | P: AsRef, 25 | { 26 | log::debug!(target: "ui","Loading new Font using Ab-Glyph"); 27 | let font = FontVec::try_from_vec(std::fs::read(path).unwrap()).unwrap(); 28 | let scale = PxScale::from(48.0); 29 | let scaled_font = font.as_scaled(scale); 30 | 31 | let mut characters = Vec::with_capacity(CHARACTERS_SIZE as usize); 32 | let mut glyphs = Vec::new(); 33 | let position = point(20.0, 20.0); 34 | let max_width = 9999_f32; 35 | 36 | let v_advance = scaled_font.height() + scaled_font.line_gap(); 37 | let mut caret = position + point(0.0, scaled_font.ascent()); 38 | let mut last_glyph: Option = None; 39 | for charr in 0..CHARACTERS_SIZE { 40 | let char = char::from_u32(charr).unwrap(); 41 | 42 | if char.is_control() { 43 | if char == '\n' { 44 | caret = point(position.x, caret.y + v_advance); 45 | last_glyph = None; 46 | } 47 | continue; 48 | } 49 | let mut glyph = scaled_font.scaled_glyph(char); 50 | if let Some(previous) = last_glyph.take() { 51 | caret.x += scaled_font.kern(previous.id, glyph.id); 52 | } 53 | glyph.position = caret; 54 | 55 | last_glyph = Some(glyph.clone()); 56 | caret.x += scaled_font.h_advance(glyph.id); 57 | 58 | if !char.is_whitespace() && caret.x > position.x + max_width { 59 | caret = point(position.x, caret.y + v_advance); 60 | glyph.position = caret; 61 | last_glyph = None; 62 | } 63 | 64 | let character = Character { 65 | size: Vec2::new(scaled_font.h_advance(glyph.id), v_advance), 66 | bearing: Vec2::new( 67 | scaled_font.h_side_bearing(glyph.id), 68 | scaled_font.v_side_bearing(glyph.id), 69 | ), 70 | v_advance, 71 | }; 72 | glyphs.push(glyph); 73 | characters.push(character); 74 | } 75 | log::debug!("Loaded Charaters: {}", characters.len()); 76 | 77 | let outlined: Vec<_> = glyphs 78 | .into_iter() 79 | // Note: not all layout glyphs have outlines (e.g. " ") 80 | .filter_map(|g| font.outline_glyph(g)) 81 | .collect(); 82 | 83 | let Some(all_px_bounds) = outlined 84 | .iter() 85 | .map(|g| g.px_bounds()) 86 | .reduce(|mut b, next| { 87 | b.min.x = b.min.x.min(next.min.x); 88 | b.max.x = b.max.x.max(next.max.x); 89 | b.min.y = b.min.y.min(next.min.y); 90 | b.max.y = b.max.y.max(next.max.y); 91 | b 92 | }) 93 | else { 94 | panic!("No outlined glyphs?"); 95 | }; 96 | let mut image = 97 | DynamicImage::new_rgba8(all_px_bounds.width() as _, all_px_bounds.height() as _) 98 | .to_rgba8(); 99 | const COLOUR: (u8, u8, u8) = (255, 255, 255); 100 | // Loop through the glyphs in the text, positing each one on a line 101 | for glyph in outlined { 102 | let bounds = glyph.px_bounds(); 103 | // calc top/left ords in "image space" 104 | // image-x=0 means the *left most pixel*, equivalent to 105 | // px_bounds.min.x which *may be non-zero* (and similarly with y) 106 | // so `- px_bounds.min` converts the left-most/top-most to 0 107 | let img_left = bounds.min.x as u32 - all_px_bounds.min.x as u32; 108 | let img_top = bounds.min.y as u32 - all_px_bounds.min.y as u32; 109 | // Draw the glyph into the image per-pixel by using the draw closure 110 | glyph.draw(|x, y, v| { 111 | // Offset the position by the glyph bounding box 112 | let px = image.get_pixel_mut(img_left + x, img_top + y); 113 | // Turn the coverage into an alpha value (blended with any previous) 114 | *px = Rgba([ 115 | COLOUR.0, 116 | COLOUR.1, 117 | COLOUR.2, 118 | px.0[3].saturating_add((v * 255.0) as u8), 119 | ]); 120 | }); 121 | } 122 | // image.save("test.png").unwrap(); 123 | 124 | // let image_size = Extent2D { 125 | // width: all_px_bounds.width() as u32, 126 | // height: all_px_bounds.height() as u32, 127 | // }; 128 | 129 | let dimensions = image.dimensions(); 130 | let mut texture = 131 | VulkanImage::from_image(instance, DynamicImage::ImageRgba8(image), false, None, None); 132 | 133 | // TODO: store everything in an Texture Atlas 134 | let descriptor_sets = VulkanInstance::allocate_descriptor_sets( 135 | &instance.device, 136 | descriptor_pool, 137 | descriptor_set_layout, 138 | instance.swapchain_images.len(), 139 | ); 140 | 141 | for &descriptor_set in descriptor_sets.iter() { 142 | let image_info = vk::DescriptorImageInfo::default() 143 | .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL) 144 | .image_view(texture.image_view) 145 | .sampler(texture.sampler); 146 | 147 | let desc_sets = [vk::WriteDescriptorSet { 148 | dst_set: descriptor_set, 149 | dst_binding: 0, // From DescriptorSetLayoutBinding 150 | descriptor_count: 1, 151 | descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, 152 | p_image_info: &image_info, 153 | ..Default::default() 154 | }]; 155 | unsafe { 156 | instance.device.update_descriptor_sets(&desc_sets, &[]); 157 | } 158 | } 159 | texture.destroy(&instance.device); 160 | super::Font { 161 | font_atlas: descriptor_sets, 162 | characters, 163 | buffer_cache: HashMap::new(), 164 | atlas_width: dimensions.0, 165 | atlas_height: dimensions.1, 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /crates/vent-ui/src/font/loader.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, path::Path}; 2 | 3 | use ab_glyph::{point, Font, FontVec, Glyph, PxScale, ScaleFont}; 4 | use ash::vk::{self}; 5 | use image::{DynamicImage, Rgba}; 6 | use vent_math::vec::vec2::Vec2; 7 | use vent_rendering::{image::VulkanImage, instance::VulkanInstance}; 8 | 9 | pub struct AbGlyphLoader {} 10 | 11 | pub const CHARACTERS_SIZE: u32 = 256; // UTF-8 12 | 13 | impl AbGlyphLoader { 14 | // Loads an new Font 15 | pub fn load

( 16 | path: P, 17 | descriptor_set_layout: vk::DescriptorSetLayout, 18 | descriptor_pool: vk::DescriptorPool, 19 | instance: &mut VulkanInstance, 20 | ) -> super::Font 21 | where 22 | P: AsRef, 23 | { 24 | log::debug!(target: "ui","Loading new Font using Ab-Glyph"); 25 | let font = FontVec::try_from_vec(std::fs::read(path).unwrap()).unwrap(); 26 | let scale = PxScale::from(48.0); 27 | let scaled_font = font.as_scaled(scale); 28 | 29 | let mut characters = Vec::with_capacity(CHARACTERS_SIZE as usize); 30 | let mut glyphs = Vec::new(); 31 | let position = point(20.0, 20.0); 32 | let max_width = 9999_f32; 33 | 34 | let v_advance = scaled_font.height() + scaled_font.line_gap(); 35 | let mut caret = position + point(0.0, scaled_font.ascent()); 36 | let mut last_glyph: Option = None; 37 | for charr in 0..CHARACTERS_SIZE { 38 | let char = char::from_u32(charr).unwrap(); 39 | 40 | if char.is_control() { 41 | if char.is_whitespace() { 42 | caret = point(position.x, caret.y + v_advance); 43 | last_glyph = None; 44 | } 45 | continue; 46 | } 47 | let mut glyph = scaled_font.scaled_glyph(char); 48 | if let Some(previous) = last_glyph.take() { 49 | caret.x += scaled_font.kern(previous.id, glyph.id); 50 | } 51 | glyph.position = caret; 52 | 53 | last_glyph = Some(glyph.clone()); 54 | caret.x += scaled_font.h_advance(glyph.id); 55 | 56 | if !char.is_whitespace() && caret.x > position.x + max_width { 57 | caret = point(position.x, caret.y + v_advance); 58 | glyph.position = caret; 59 | last_glyph = None; 60 | } 61 | 62 | let character = Character { 63 | size: Vec2::new(scaled_font.h_advance(glyph.id), v_advance), 64 | bearing: Vec2::new( 65 | scaled_font.h_side_bearing(glyph.id), 66 | scaled_font.v_side_bearing(glyph.id), 67 | ), 68 | v_advance, 69 | }; 70 | glyphs.push(glyph); 71 | characters.push(character); 72 | } 73 | log::debug!("Loaded Charaters: {}", characters.len()); 74 | 75 | let outlined: Vec<_> = glyphs 76 | .into_iter() 77 | // Note: not all layout glyphs have outlines (e.g. " ") 78 | .filter_map(|g| font.outline_glyph(g)) 79 | .collect(); 80 | 81 | let Some(all_px_bounds) = outlined 82 | .iter() 83 | .map(|g| g.px_bounds()) 84 | .reduce(|mut b, next| { 85 | b.min.x = b.min.x.min(next.min.x); 86 | b.max.x = b.max.x.max(next.max.x); 87 | b.min.y = b.min.y.min(next.min.y); 88 | b.max.y = b.max.y.max(next.max.y); 89 | b 90 | }) 91 | else { 92 | panic!("No outlined glyphs?"); 93 | }; 94 | let mut image = 95 | DynamicImage::new_rgba8(all_px_bounds.width() as _, all_px_bounds.height() as _) 96 | .to_rgba8(); 97 | const COLOUR: (u8, u8, u8) = (255, 255, 255); 98 | // Loop through the glyphs in the text, positing each one on a line 99 | for glyph in outlined { 100 | let bounds = glyph.px_bounds(); 101 | // calc top/left ords in "image space" 102 | // image-x=0 means the *left most pixel*, equivalent to 103 | // px_bounds.min.x which *may be non-zero* (and similarly with y) 104 | // so `- px_bounds.min` converts the left-most/top-most to 0 105 | let img_left = bounds.min.x as u32 - all_px_bounds.min.x as u32; 106 | let img_top = bounds.min.y as u32 - all_px_bounds.min.y as u32; 107 | // Draw the glyph into the image per-pixel by using the draw closure 108 | glyph.draw(|x, y, v| { 109 | // Offset the position by the glyph bounding box 110 | let px = image.get_pixel_mut(img_left + x, img_top + y); 111 | // Turn the coverage into an alpha value (blended with any previous) 112 | *px = Rgba([ 113 | COLOUR.0, 114 | COLOUR.1, 115 | COLOUR.2, 116 | px.0[3].saturating_add((v * 255.0) as u8), 117 | ]); 118 | }); 119 | } 120 | // image.save("test.png").unwrap(); 121 | 122 | // let image_size = Extent2D { 123 | // width: all_px_bounds.width() as u32, 124 | // height: all_px_bounds.height() as u32, 125 | // }; 126 | 127 | let dimensions = image.dimensions(); 128 | let sampler = vk::SamplerCreateInfo::default() 129 | .max_lod(1.0); 130 | let texture = 131 | VulkanImage::from_image(instance, DynamicImage::ImageRgba8(image), false, Some(sampler), Some("Font Atlas")); 132 | 133 | // TODO: store everything in an Texture Atlas 134 | let descriptor_sets = VulkanInstance::allocate_descriptor_sets( 135 | &instance.device, 136 | descriptor_pool, 137 | descriptor_set_layout, 138 | instance.swapchain_images.len(), 139 | ); 140 | 141 | for &descriptor_set in descriptor_sets.iter() { 142 | let image_info = vk::DescriptorImageInfo::default() 143 | .image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL) 144 | .image_view(texture.image_view) 145 | .sampler(texture.sampler); 146 | 147 | let desc_sets = [vk::WriteDescriptorSet { 148 | dst_set: descriptor_set, 149 | dst_binding: 0, // From DescriptorSetLayoutBinding 150 | descriptor_count: 1, 151 | descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, 152 | p_image_info: &image_info, 153 | ..Default::default() 154 | }]; 155 | unsafe { 156 | instance.device.update_descriptor_sets(&desc_sets, &[]); 157 | } 158 | } 159 | super::Font { 160 | font_atlas: descriptor_sets, 161 | characters, 162 | font_texture: texture, 163 | buffer_cache: HashMap::new(), 164 | atlas_width: dimensions.0, 165 | atlas_height: dimensions.1, 166 | scale_in_pixels: 1 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /crates/vent-ui/src/font/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use ash::vk; 4 | use vent_math::vec::vec2::Vec2; 5 | use vent_rendering::{buffer::VulkanBuffer, instance::VulkanInstance, vertex::Vertex2D}; 6 | 7 | pub mod ab_glyph; 8 | 9 | pub struct Character { 10 | size: Vec2, 11 | bearing: Vec2, 12 | v_advance: f32, 13 | } 14 | 15 | #[allow(dead_code)] 16 | pub struct Font { 17 | buffer_cache: HashMap, 18 | font_atlas: Vec, 19 | atlas_width: u32, 20 | atlas_height: u32, 21 | characters: Vec, 22 | } 23 | 24 | impl Font { 25 | // Bind Pipeline before 26 | #[allow(clippy::too_many_arguments)] 27 | pub fn render_text( 28 | &mut self, 29 | instance: &VulkanInstance, 30 | command_buffer: vk::CommandBuffer, 31 | pipeline_layout: vk::PipelineLayout, 32 | buffer_index: usize, 33 | text: String, 34 | x: f32, 35 | y: f32, 36 | scale: f32, 37 | color: u32, 38 | ) { 39 | unsafe { 40 | instance.device.cmd_bind_descriptor_sets( 41 | command_buffer, 42 | vk::PipelineBindPoint::GRAPHICS, 43 | pipeline_layout, 44 | 0, 45 | &self.font_atlas[buffer_index..=buffer_index], 46 | &[], 47 | ) 48 | }; 49 | 50 | let characters = &self.characters; 51 | 52 | if !self.buffer_cache.contains_key(&text) { 53 | // Todo, Support changing colors for same text 54 | let mut batched_vertices = Vec::new(); 55 | // Loop through each character in the text 56 | let mut current_x = x; 57 | for character in text.chars() { 58 | let character_index = character as usize; 59 | 60 | // Check if the character is within the loaded characters 61 | if character_index < characters.len() { 62 | let character = &characters[character_index]; 63 | 64 | let xpos = current_x + character.bearing.x * scale; 65 | let ypos = y - (character.size.y - character.bearing.y) * scale; 66 | let width = character.size.x * scale; 67 | let height = character.size.y * scale; 68 | 69 | let vertices: [Vertex2D; 6] = [ 70 | Vertex2D { 71 | position: [xpos, ypos + height], 72 | tex_coord: [0.0, 0.0], 73 | color, 74 | }, 75 | Vertex2D { 76 | position: [xpos, ypos], 77 | tex_coord: [0.0, 1.0], 78 | color, 79 | }, 80 | Vertex2D { 81 | position: [xpos + width, ypos], 82 | tex_coord: [1.0, 1.0], 83 | color, 84 | }, 85 | Vertex2D { 86 | position: [xpos, ypos + height], 87 | tex_coord: [0.0, 0.0], 88 | color, 89 | }, 90 | Vertex2D { 91 | position: [xpos + width, ypos], 92 | tex_coord: [1.0, 1.0], 93 | color, 94 | }, 95 | Vertex2D { 96 | position: [xpos + width, ypos + height], 97 | tex_coord: [1.0, 0.0], 98 | color, 99 | }, 100 | ]; 101 | for vertex in vertices { 102 | batched_vertices.push(vertex); 103 | } 104 | current_x += character.v_advance * scale; 105 | } else { 106 | log::warn!("Text Character is too big {}", character_index) 107 | } 108 | } 109 | Self::create_buffer( 110 | &mut self.buffer_cache, 111 | instance, 112 | text.clone(), 113 | &batched_vertices, 114 | ); 115 | } 116 | let (vertex_count, buffer) = &self.buffer_cache[&text]; 117 | 118 | let render_area = vk::Rect2D::default() 119 | .offset(vk::Offset2D::default()) 120 | .extent(instance.surface_resolution); 121 | 122 | unsafe { 123 | instance 124 | .device 125 | .cmd_set_scissor(command_buffer, 0, &[render_area]); 126 | instance.device.cmd_bind_vertex_buffers2( 127 | command_buffer, 128 | 0, 129 | &[**buffer], 130 | &[0], 131 | None, 132 | None, 133 | ); 134 | instance 135 | .device 136 | .cmd_draw(command_buffer, *vertex_count, 1, 0, 0) 137 | } 138 | 139 | // Update offset for the next character 140 | } 141 | 142 | fn create_buffer( 143 | buffer_cache: &mut HashMap, 144 | instance: &VulkanInstance, 145 | text: String, 146 | vertices: &[Vertex2D], 147 | ) { 148 | let vertex_size = std::mem::size_of_val(vertices) as vk::DeviceSize; 149 | 150 | let vulkan_buffer = VulkanBuffer::cpu_to_gpu( 151 | instance, 152 | vertices, 153 | vertex_size, 154 | vk::BufferUsageFlags::VERTEX_BUFFER, 155 | Some("Font Buffer"), 156 | ); 157 | buffer_cache.insert(text, (vertices.len() as u32, vulkan_buffer)); 158 | } 159 | 160 | pub fn destroy(&mut self, device: &ash::Device) { 161 | for mut buffer in self.buffer_cache.drain() { 162 | buffer.1 .1.destroy(device); 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /crates/vent-ui/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod font; 2 | pub mod renderer; 3 | pub mod widgets; 4 | 5 | pub trait GUI { 6 | fn update(&mut self); 7 | } 8 | -------------------------------------------------------------------------------- /crates/vent-ui/src/renderer.rs: -------------------------------------------------------------------------------- 1 | use std::{mem::size_of, path::PathBuf}; 2 | 3 | use ash::vk::{self}; 4 | use vent_assets::io::file::FileAsset; 5 | use vent_math::vec::vec2::Vec2; 6 | use vent_rendering::{ 7 | any_as_u8_slice, instance::VulkanInstance, pipeline::VulkanPipeline, vertex::Vertex2D, 8 | }; 9 | 10 | use crate::font::{ab_glyph::AbGlyphLoader, Font}; 11 | 12 | use super::GUI; 13 | 14 | #[allow(dead_code)] 15 | pub struct GuiRenderer { 16 | descriptor_pool: vk::DescriptorPool, 17 | pipeline: VulkanPipeline, 18 | 19 | // Font 20 | push_constant: PushConstant, 21 | font: Option, 22 | 23 | guis: Vec>, 24 | } 25 | 26 | #[repr(C)] 27 | pub struct PushConstant { 28 | scale: Vec2, 29 | translate: Vec2, 30 | } 31 | 32 | impl GuiRenderer { 33 | pub const DEFAULT_TEXTURE_FILTER: vk::Filter = vk::Filter::LINEAR; 34 | 35 | pub fn new(instance: &mut VulkanInstance) -> Self { 36 | log::debug!(target: "ui", "initialising UI Renderer"); 37 | 38 | let pipeline = Self::create_pipeline(instance); 39 | 40 | let push_constant = PushConstant { 41 | scale: Vec2::ONE, 42 | translate: Vec2::ZERO, 43 | }; 44 | 45 | let descriptor_pool = Self::create_descriptor_pool( 46 | 1, // 1 Font 47 | instance.swapchain_images.len() as u32, 48 | &instance.device, 49 | ); 50 | 51 | let mut renderer = Self { 52 | descriptor_pool, 53 | pipeline, 54 | push_constant, 55 | font: None, 56 | guis: Vec::new(), 57 | }; 58 | let path = FileAsset::new("assets/fonts/Arial.ttf"); 59 | // Load default font 60 | renderer.load_font(instance, path.root_path()); 61 | renderer 62 | } 63 | 64 | fn create_pipeline(instance: &VulkanInstance) -> VulkanPipeline { 65 | let vertex_shader = FileAsset::new("assets/shaders/app/2D/gui.vert.spv"); 66 | let fragment_shader = FileAsset::new("assets/shaders/app/2D/gui.frag.spv"); 67 | 68 | let desc_layout_bindings = [ 69 | // Fragment 70 | vk::DescriptorSetLayoutBinding { 71 | binding: 0, 72 | descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, 73 | descriptor_count: 1, 74 | stage_flags: vk::ShaderStageFlags::FRAGMENT, 75 | ..Default::default() 76 | }, 77 | ]; 78 | 79 | let push_constant_range = vk::PushConstantRange::default() 80 | .size(size_of::() as u32) 81 | .stage_flags(vk::ShaderStageFlags::VERTEX); 82 | 83 | VulkanPipeline::create_simple_pipeline( 84 | instance, 85 | vertex_shader.root_path(), 86 | fragment_shader.root_path(), 87 | &[Vertex2D::binding_description()], 88 | &Vertex2D::input_descriptions(), 89 | instance.surface_resolution, 90 | &[push_constant_range], 91 | &desc_layout_bindings, 92 | ) 93 | } 94 | 95 | pub fn create_descriptor_pool( 96 | material_count: u32, 97 | swapchain_count: u32, 98 | device: &ash::Device, 99 | ) -> vk::DescriptorPool { 100 | let pool_sizes = [vk::DescriptorPoolSize { 101 | ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, 102 | descriptor_count: material_count * swapchain_count, 103 | }]; 104 | 105 | let create_info = vk::DescriptorPoolCreateInfo::default() 106 | .pool_sizes(&pool_sizes) 107 | .max_sets(material_count * swapchain_count); 108 | 109 | unsafe { device.create_descriptor_pool(&create_info, None) }.unwrap() 110 | } 111 | 112 | #[allow(clippy::too_many_arguments)] 113 | pub fn render_text( 114 | &mut self, 115 | instance: &VulkanInstance, 116 | command_buffer: vk::CommandBuffer, 117 | buffer_index: usize, 118 | text: String, 119 | x: f32, 120 | y: f32, 121 | scale: f32, 122 | color: u32, 123 | ) { 124 | if let Some(font) = &mut self.font { 125 | unsafe { 126 | instance.device.cmd_bind_pipeline( 127 | command_buffer, 128 | vk::PipelineBindPoint::GRAPHICS, 129 | self.pipeline.pipeline, 130 | ) 131 | }; 132 | let viewport = vk::Viewport::default() 133 | .width(instance.surface_resolution.width as f32) 134 | .height(instance.surface_resolution.height as f32) 135 | .max_depth(1.0); 136 | unsafe { 137 | instance 138 | .device 139 | .cmd_set_viewport(command_buffer, 0, &[viewport]); 140 | } 141 | let p_scale = Vec2::new(2.0, 2.0); 142 | let translate = Vec2::new(-1.0 - 0.0 * p_scale.x, -1.0 - 0.0 * p_scale.y); 143 | 144 | self.push_constant = PushConstant { 145 | scale: p_scale, 146 | translate, 147 | }; 148 | 149 | unsafe { 150 | instance.device.cmd_push_constants( 151 | command_buffer, 152 | self.pipeline.pipeline_layout, 153 | vk::ShaderStageFlags::VERTEX, 154 | 0, 155 | any_as_u8_slice(&self.push_constant), 156 | ) 157 | } 158 | font.render_text( 159 | instance, 160 | command_buffer, 161 | self.pipeline.pipeline_layout, 162 | buffer_index, 163 | text, 164 | x, 165 | y, 166 | scale, 167 | color, 168 | ); 169 | } 170 | } 171 | 172 | pub fn load_font(&mut self, instance: &mut VulkanInstance, path: &PathBuf) { 173 | self.font = Some(AbGlyphLoader::load( 174 | path, 175 | self.pipeline.descriptor_set_layout, 176 | self.descriptor_pool, 177 | instance, 178 | )); 179 | } 180 | 181 | pub fn render(&mut self) { 182 | for gui in self.guis.iter_mut() { 183 | gui.update() 184 | } 185 | } 186 | 187 | pub fn add_gui(mut self, gui: Box) -> Self { 188 | self.guis.push(gui); 189 | self 190 | } 191 | 192 | #[inline] 193 | #[allow(dead_code)] 194 | pub fn register_texture(&mut self) {} 195 | 196 | pub fn destroy(&mut self, device: &ash::Device) { 197 | unsafe { 198 | if let Some(font) = &mut self.font { 199 | font.destroy(device); 200 | self.font = None 201 | } 202 | self.pipeline.destroy(device); 203 | device.destroy_descriptor_pool(self.descriptor_pool, None); 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /crates/vent-ui/src/widgets/button.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /crates/vent-ui/src/widgets/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod button; 2 | -------------------------------------------------------------------------------- /crates/vent-window/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vent-window" 3 | version.workspace = true 4 | edition.workspace = true 5 | 6 | targets = [ 7 | # Windows 8 | "i686-pc-windows-msvc", 9 | "x86_64-pc-windows-msvc", 10 | # Unix Wayland 11 | "i686-unknown-linux-gnu", 12 | "x86_64-unknown-linux-gnu", 13 | ] 14 | 15 | [features] 16 | 17 | [dependencies] 18 | log = "0.4" 19 | raw-window-handle = { version = "0.6", features = [ 20 | "std", 21 | ]} 22 | 23 | # serde 24 | serde = { version = "1.0", features = ["derive"] } 25 | 26 | [target.'cfg(all(unix, not(any(target_os = "redox", target_family = "wasm", target_os = "android", target_os = "ios", target_os = "macos"))))'.dependencies] 27 | wayland-backend = { version = "0.3", features = ["client_system"] } 28 | wayland-client = { version = "0.31" } 29 | wayland-protocols = { version = "0.32", features = [ 30 | "client", "staging", "unstable", 31 | ] } 32 | wayland-protocols-plasma = { version = "0.3.1", features = [ 33 | "client", 34 | ] } 35 | wayland-protocols-wlr = { version = "0.3.1", features = ["client"] } 36 | wayland-scanner = {version= "0.31" } 37 | wayland-csd-frame = { version= "0.3.0" } 38 | 39 | # Decorations 40 | sctk = { package = "smithay-client-toolkit", version = "0.19.0" } 41 | sctk-adwaita = { version = "0.10.1", default-features = false } 42 | 43 | # For keys 44 | xkbcommon = { version = "0.8.0", features = ["wayland"] } 45 | xkeysym = "0.2.0" 46 | 47 | [target.'cfg(target_os = "windows")'.dependencies.windows] 48 | version = "0.58.0" 49 | features = [ 50 | "Win32_Devices_HumanInterfaceDevice", 51 | "Win32_Foundation", 52 | "Win32_Globalization", 53 | "Win32_Graphics_Dwm", 54 | "Win32_Graphics_Gdi", 55 | "Win32_Media", 56 | "Win32_System_Com_StructuredStorage", 57 | "Win32_System_Com", 58 | "Win32_System_LibraryLoader", 59 | "Win32_System_Ole", 60 | "Win32_System_SystemInformation", 61 | "Win32_System_SystemServices", 62 | "Win32_System_Threading", 63 | "Win32_System_WindowsProgramming", 64 | "Win32_UI_Accessibility", 65 | "Win32_UI_Controls", 66 | "Win32_UI_HiDpi", 67 | "Win32_UI_Input_Ime", 68 | "Win32_UI_Input_KeyboardAndMouse", 69 | "Win32_UI_Input_Pointer", 70 | "Win32_UI_Input_Touch", 71 | "Win32_UI_Shell", 72 | "Win32_UI_TextServices", 73 | "Win32_UI_WindowsAndMessaging", 74 | ] -------------------------------------------------------------------------------- /crates/vent-window/README.md: -------------------------------------------------------------------------------- 1 | ### Vent-Window 2 | 3 | A Window creation & management Library 4 | 5 | ## Supported Platforms 6 | 7 | - Desktop 8 | - [Windows](#windows) 9 | - [macOS](#macos-planned) 10 | - [Unix/Wayland](#unix-wayland) 11 | - [Unix/X11 Info](#unix-x11) 12 | - Mobile 13 | - [Android](#android-planned) 14 | - [IOS](#ios-planned) 15 | 16 | # Desktop 17 | 18 | ## Windows 19 | 20 | | Features | Status | 21 | | ------------------- | ------ | 22 | | Window Creation | ✅️ | 23 | | Window Decorations | ✅️ | 24 | | Event Handling | ✅️ | 25 | | Full-Screen | ❌ | 26 | | Window Minimization | ✅️ | 27 | | Window Maximization | ✅️ | 28 | | Window Resizing | ✅️ | 29 | | Vulkan Rendering | ✅️ | 30 | | Keyboard Support | ✅️ | 31 | | Mouse Support | ✅️ | 32 | | GamePad Support | ❌ | 33 | | Touch Support | ❌ | 34 | | Touch Support | ❌ | 35 | | Cursor Icon | ❌ | 36 | | Cursor Own Image | ❌ | 37 | | Drag&Drop | ❌ | 38 | 39 | ## macOS (planned) 40 | 41 | | Features | Status | 42 | | ------------------- | ------ | 43 | | Window Creation | ❌ | 44 | | Window Decorations | ❌ | 45 | | Event Handling | ❌ | 46 | | Full-Screen | ❌ | 47 | | Window Minimization | ❌ | 48 | | Window Maximization | ❌ | 49 | | Window Resizing | ❌ | 50 | | Vulkan Rendering | ❌ | 51 | | Keyboard Support | ❌ | 52 | | Mouse Support | ❌ | 53 | | GamePad Support | ❌ | 54 | | Touch Support | ❌ | 55 | | Touch Support | ❌ | 56 | | Cursor Icon | ❌ | 57 | | Cursor Own Image | ❌ | 58 | | Drag&Drop | ❌ | 59 | 60 | ## Unix (Wayland) 61 | 62 | | Features | Status | 63 | | ------------------- | ------ | 64 | | Window Creation | ✅️ | 65 | | Window Decorations | ✅️ | 66 | | Event Handling | ✅️ | 67 | | Full-Screen | ✅️ | 68 | | Window Minimization | ✅️ | 69 | | Window Maximization | ✅️ | 70 | | Window Resizing | ✅️ | 71 | | Vulkan Rendering | ✅️ | 72 | | Keyboard Support | ✅️ | 73 | | Mouse Support | ✅️ | 74 | | GamePad Support | ❌ | 75 | | Touch Support | ❌ | 76 | | Touch Support | ❌ | 77 | | Cursor Icon | ❌ | 78 | | Cursor Own Image | ❌ | 79 | | Drag&Drop | ❌ | 80 | 81 | ## Unix (X11) 82 | X11 is not planned 83 | 84 | # Mobile 85 | 86 | ## Android (planned) 87 | 88 | | Features | Status | 89 | | ------------------- | ------ | 90 | | Window Creation | ❌ | 91 | | Window Decorations | ❌ | 92 | | Event Handling | ❌ | 93 | | Full-Screen | ❌ | 94 | | Window Minimization | ❌ | 95 | | Window Maximization | ❌ | 96 | | Window Resizing | ❌ | 97 | | Vulkan Rendering | ❌ | 98 | | Keyboard Support | ❌ | 99 | | Mouse Support | ❌ | 100 | | GamePad Support | ❌ | 101 | | Touch Support | ❌ | 102 | | Touch Support | ❌ | 103 | | Cursor Icon | ❌ | 104 | | Cursor Own Image | ❌ | 105 | | Drag&Drop | ❌ | 106 | 107 | ## IOS (planned) 108 | 109 | | Features | Status | 110 | | ------------------- | ------ | 111 | | Window Creation | ❌ | 112 | | Window Decorations | ❌ | 113 | | Event Handling | ❌ | 114 | | Full-Screen | ❌ | 115 | | Window Minimization | ❌ | 116 | | Window Maximization | ❌ | 117 | | Window Resizing | ❌ | 118 | | Vulkan Rendering | ❌ | 119 | | Keyboard Support | ❌ | 120 | | Mouse Support | ❌ | 121 | | GamePad Support | ❌ | 122 | | Touch Support | ❌ | 123 | | Touch Support | ❌ | 124 | | Cursor Icon | ❌ | 125 | | Cursor Own Image | ❌ | 126 | | Drag&Drop | ❌ | 127 | 128 | 129 | ## Contributing 130 | 131 | See [Contributing](../../CONTRIBUTING.md) 132 | 133 | ## License 134 | 135 | Vent-Window is licensed under the [Apache 2.0 License](../../LICENSE) 136 | -------------------------------------------------------------------------------- /crates/vent-window/src/keyboard.rs: -------------------------------------------------------------------------------- 1 | #[derive(PartialEq, Clone, Debug)] 2 | pub enum Key { 3 | A, 4 | B, 5 | C, 6 | D, 7 | E, 8 | F, 9 | G, 10 | H, 11 | I, 12 | J, 13 | K, 14 | L, 15 | M, 16 | N, 17 | O, 18 | P, 19 | Q, 20 | R, 21 | S, 22 | T, 23 | U, 24 | V, 25 | W, 26 | X, 27 | Y, 28 | Z, 29 | Space, 30 | ShiftL, 31 | ShiftR, 32 | Leftarrow, 33 | Uparrow, 34 | Rightarrow, 35 | Downarrow, 36 | Unknown, 37 | } 38 | 39 | #[derive(PartialEq, Clone)] 40 | pub enum KeyState { 41 | Pressed, 42 | Released, 43 | } 44 | -------------------------------------------------------------------------------- /crates/vent-window/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::num::NonZeroU32; 2 | 3 | use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle}; 4 | use serde::{Deserialize, Serialize}; 5 | pub mod keyboard; 6 | pub mod mouse; 7 | pub mod platform; 8 | 9 | type EventHandler = dyn FnMut(WindowEvent); 10 | 11 | #[derive(PartialEq, Clone)] 12 | pub enum WindowEvent { 13 | Close, 14 | Key { 15 | key: keyboard::Key, 16 | state: keyboard::KeyState, 17 | }, 18 | MouseButton { 19 | button: mouse::Button, 20 | state: mouse::ButtonState, 21 | }, 22 | MouseMotion { 23 | x: f64, 24 | y: f64, 25 | }, 26 | Resize { 27 | new_width: u32, 28 | new_height: u32, 29 | }, 30 | Draw, 31 | } 32 | 33 | #[derive(Serialize, Deserialize, PartialEq, Clone)] 34 | pub enum WindowMode { 35 | Default, 36 | FullScreen, 37 | Maximized, 38 | Minimized, 39 | } 40 | 41 | #[derive(Serialize, Deserialize, Clone)] 42 | pub struct WindowAttribs { 43 | title: String, 44 | app_id: String, 45 | width: NonZeroU32, 46 | height: NonZeroU32, 47 | mode: WindowMode, 48 | min_size: Option<(u32, u32)>, 49 | max_size: Option<(u32, u32)>, 50 | resizable: bool, 51 | closeable: bool, 52 | } 53 | 54 | impl WindowAttribs { 55 | pub fn with_title(mut self, title: String) -> Self { 56 | self.title = title; 57 | self 58 | } 59 | pub fn set_mode(mut self, mode: WindowMode) -> Self { 60 | self.mode = mode; 61 | self 62 | } 63 | } 64 | 65 | impl Default for WindowAttribs { 66 | fn default() -> Self { 67 | Self { 68 | title: "Vent Engine".to_string(), 69 | app_id: "com.ventengine.VentEngine".to_string(), 70 | width: unsafe { NonZeroU32::new_unchecked(800) }, 71 | height: unsafe { NonZeroU32::new_unchecked(600) }, 72 | mode: WindowMode::Default, 73 | max_size: None, 74 | min_size: None, 75 | resizable: true, 76 | closeable: true, 77 | } 78 | } 79 | } 80 | 81 | /** 82 | * Cross Platform window Wrapper 83 | */ 84 | pub struct Window { 85 | window: platform::PlatformWindow, 86 | } 87 | 88 | impl Window { 89 | pub fn new(inital_attribs: WindowAttribs) -> Self { 90 | Self { 91 | window: platform::PlatformWindow::create_window(inital_attribs), 92 | } 93 | } 94 | 95 | pub fn poll(mut self, event_handler: F) 96 | where 97 | F: FnMut(WindowEvent) + 'static, 98 | { 99 | self.window.poll(event_handler); 100 | } 101 | 102 | pub fn set_cursor_visible(&mut self, visible: bool) { 103 | self.window.set_cursor_visible(visible) 104 | } 105 | 106 | pub fn close(&mut self) { 107 | self.window.close() 108 | } 109 | 110 | pub fn width(&self) -> u32 { 111 | self.window.width() 112 | } 113 | 114 | pub fn height(&self) -> u32 { 115 | self.window.height() 116 | } 117 | 118 | pub fn size(&self) -> (u32, u32) { 119 | (self.window.width(), self.window.height()) 120 | } 121 | } 122 | 123 | impl HasDisplayHandle for Window { 124 | fn display_handle(&self) -> Result, raw_window_handle::HandleError> { 125 | let raw = self.window.raw_display_handle(); 126 | Ok(unsafe { raw_window_handle::DisplayHandle::borrow_raw(raw) }) 127 | } 128 | } 129 | 130 | impl HasWindowHandle for Window { 131 | fn window_handle( 132 | &self, 133 | ) -> Result, raw_window_handle::HandleError> { 134 | let raw = self.window.raw_window_handle(); 135 | Ok(unsafe { raw_window_handle::WindowHandle::borrow_raw(raw) }) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /crates/vent-window/src/mouse.rs: -------------------------------------------------------------------------------- 1 | #[derive(PartialEq, Clone)] 2 | pub enum Button { 3 | LEFT, 4 | RIGHT, 5 | MIDDLE, 6 | SIDE, 7 | EXTRA, 8 | FORWARD, 9 | BACK, 10 | } 11 | 12 | #[derive(PartialEq, Clone)] 13 | pub enum ButtonState { 14 | Pressed, 15 | Released, 16 | } 17 | -------------------------------------------------------------------------------- /crates/vent-window/src/platform/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(unix)] 2 | #[path = "wayland/mod.rs"] 3 | #[allow(clippy::module_inception)] 4 | pub mod platform; 5 | 6 | #[cfg(target_os = "windows")] 7 | #[path = "windows/mod.rs"] 8 | #[allow(clippy::module_inception)] 9 | pub mod platform; 10 | 11 | pub use self::platform::*; 12 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ventengine/Vent-Engine/89d706c80c2f1ae3c2b441cbec49c49b388471c0/docs/logo.png -------------------------------------------------------------------------------- /test/runtime-sandbox/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "runtime-sandbox" 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 | vent-runtime = { path = "../../crates/vent-runtime"} 10 | -------------------------------------------------------------------------------- /test/runtime-sandbox/project.vent: -------------------------------------------------------------------------------- 1 | {"name":"runtime-sandbox","version":"0.1.0"} -------------------------------------------------------------------------------- /test/runtime-sandbox/src/main.rs: -------------------------------------------------------------------------------- 1 | use vent_runtime::VentApplication; 2 | 3 | fn main() { 4 | VentApplication::default(); 5 | } 6 | --------------------------------------------------------------------------------