├── web
├── README.md
├── examples
│ ├── README.md
│ ├── cube
│ │ ├── README.md
│ │ ├── wgpu_rust_renderer_example_cube_bg.wasm
│ │ ├── build.sh
│ │ ├── Cargo.toml
│ │ ├── index.html
│ │ └── src
│ │ │ └── lib.rs
│ ├── gltf
│ │ ├── README.md
│ │ ├── assets
│ │ │ ├── Default_AO.jpg
│ │ │ ├── DamagedHelmet.bin
│ │ │ ├── Default_albedo.jpg
│ │ │ ├── Default_normal.jpg
│ │ │ ├── Default_emissive.jpg
│ │ │ ├── Default_metalRoughness.jpg
│ │ │ └── DamagedHelmet.gltf
│ │ ├── wgpu_rust_renderer_example_gltf_bg.wasm
│ │ ├── build.sh
│ │ ├── Cargo.toml
│ │ ├── index.html
│ │ └── src
│ │ │ └── lib.rs
│ ├── rotation
│ │ ├── README.md
│ │ ├── wgpu_rust_renderer_example_rotation_bg.wasm
│ │ ├── build.sh
│ │ ├── Cargo.toml
│ │ ├── index.html
│ │ └── src
│ │ │ └── lib.rs
│ ├── texture
│ │ ├── README.md
│ │ ├── assets
│ │ │ └── texture.png
│ │ ├── wgpu_rust_renderer_example_texture_bg.wasm
│ │ ├── build.sh
│ │ ├── Cargo.toml
│ │ ├── index.html
│ │ └── src
│ │ │ └── lib.rs
│ ├── triangle
│ │ ├── README.md
│ │ ├── wgpu_rust_renderer_example_triangle_bg.wasm
│ │ ├── build.sh
│ │ ├── Cargo.toml
│ │ ├── index.html
│ │ └── src
│ │ │ └── lib.rs
│ ├── face_culling
│ │ ├── README.md
│ │ ├── wgpu_rust_renderer_example_face_culling_bg.wasm
│ │ ├── build.sh
│ │ ├── Cargo.toml
│ │ ├── index.html
│ │ └── src
│ │ │ └── lib.rs
│ ├── build.sh
│ ├── icons
│ │ ├── ic_arrow_drop_down_black_24dp.svg
│ │ ├── ic_menu_black_24dp.svg
│ │ ├── ic_close_black_24dp.svg
│ │ └── ic_search_black_24dp.svg
│ ├── utils
│ │ └── window.rs
│ └── index.html
└── build_examples.sh
├── .gitignore
├── src
├── resource
│ ├── mod.rs
│ └── resource.rs
├── material
│ ├── mod.rs
│ └── node
│ │ ├── mod.rs
│ │ ├── node.rs
│ │ ├── normal.rs
│ │ ├── normal_matrix.rs
│ │ ├── const_float.rs
│ │ ├── float.rs
│ │ ├── const_vector3.rs
│ │ ├── vector3.rs
│ │ ├── x.rs
│ │ ├── y.rs
│ │ ├── z.rs
│ │ ├── xyz.rs
│ │ ├── linear_to_srgb.rs
│ │ ├── srgb_to_linear.rs
│ │ ├── add.rs
│ │ ├── sub.rs
│ │ ├── multiply.rs
│ │ ├── texture.rs
│ │ ├── tangent_to_object_normal.rs
│ │ └── brdf.rs
├── texture
│ ├── mod.rs
│ ├── texture.rs
│ └── sampler.rs
├── geometry
│ ├── mod.rs
│ ├── index.rs
│ ├── attribute.rs
│ └── geometry.rs
├── web
│ ├── mod.rs
│ └── wgpu_web_renderer.rs
├── scene
│ ├── mod.rs
│ ├── mesh.rs
│ ├── camera.rs
│ ├── scene.rs
│ └── node.rs
├── math
│ ├── mod.rs
│ ├── color.rs
│ ├── euler.rs
│ ├── matrix3gpu.rs
│ ├── vector3.rs
│ ├── quaternion.rs
│ └── matrix3.rs
├── utils
│ ├── mod.rs
│ ├── log.rs
│ ├── file_loader.rs
│ ├── material_helper.rs
│ ├── texture_loader.rs
│ └── geometry_helper.rs
├── lib.rs
└── renderer
│ ├── mod.rs
│ ├── wgpu_attributes.rs
│ ├── wgpu_indices.rs
│ ├── wgpu_samplers.rs
│ ├── wgpu_textures.rs
│ └── wgpu_render_pipeline.rs
├── .travis.yml
├── screenshots
├── web.png
└── desktop.png
├── examples
├── texture
│ ├── texture.png
│ └── main.rs
├── gltf
│ ├── assets
│ │ ├── Default_AO.jpg
│ │ ├── DamagedHelmet.bin
│ │ ├── Default_albedo.jpg
│ │ ├── Default_normal.jpg
│ │ ├── Default_emissive.jpg
│ │ ├── Default_metalRoughness.jpg
│ │ └── DamagedHelmet.gltf
│ └── main.rs
├── triangle
│ └── main.rs
├── rotation
│ └── main.rs
├── cube
│ └── main.rs
├── pbr
│ └── main.rs
└── face_culling
│ └── main.rs
├── LICENSE
├── Cargo.toml
└── README.md
/web/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/examples/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/examples/cube/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/examples/gltf/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/examples/rotation/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/examples/texture/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/web/examples/triangle/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Cargo.lock
2 | target/
3 |
--------------------------------------------------------------------------------
/src/resource/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod resource;
--------------------------------------------------------------------------------
/web/examples/face_culling/README.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: rust
2 | rust:
3 | - stable
4 |
5 |
--------------------------------------------------------------------------------
/src/material/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod material;
2 | pub mod node;
3 |
--------------------------------------------------------------------------------
/src/texture/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod sampler;
2 | pub mod texture;
3 |
--------------------------------------------------------------------------------
/web/build_examples.sh:
--------------------------------------------------------------------------------
1 | cd examples
2 | bash build.sh
3 | cd -
4 |
5 |
--------------------------------------------------------------------------------
/src/geometry/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod attribute;
2 | pub mod geometry;
3 | pub mod index;
4 |
--------------------------------------------------------------------------------
/src/web/mod.rs:
--------------------------------------------------------------------------------
1 | #[cfg(target_arch = "wasm32")]
2 | pub mod wgpu_web_renderer;
3 |
--------------------------------------------------------------------------------
/src/scene/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod camera;
2 | pub mod mesh;
3 | pub mod node;
4 | pub mod scene;
5 |
--------------------------------------------------------------------------------
/screenshots/web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/screenshots/web.png
--------------------------------------------------------------------------------
/screenshots/desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/screenshots/desktop.png
--------------------------------------------------------------------------------
/examples/texture/texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/examples/texture/texture.png
--------------------------------------------------------------------------------
/examples/gltf/assets/Default_AO.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/examples/gltf/assets/Default_AO.jpg
--------------------------------------------------------------------------------
/examples/gltf/assets/DamagedHelmet.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/examples/gltf/assets/DamagedHelmet.bin
--------------------------------------------------------------------------------
/examples/gltf/assets/Default_albedo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/examples/gltf/assets/Default_albedo.jpg
--------------------------------------------------------------------------------
/examples/gltf/assets/Default_normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/examples/gltf/assets/Default_normal.jpg
--------------------------------------------------------------------------------
/web/examples/build.sh:
--------------------------------------------------------------------------------
1 | for dir in $(ls -d ./*/ | grep -v icons | grep -v utils)
2 | do
3 | cd $dir
4 | bash build.sh
5 | cd -
6 | done
7 |
--------------------------------------------------------------------------------
/web/examples/gltf/assets/Default_AO.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/gltf/assets/Default_AO.jpg
--------------------------------------------------------------------------------
/web/examples/texture/assets/texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/texture/assets/texture.png
--------------------------------------------------------------------------------
/examples/gltf/assets/Default_emissive.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/examples/gltf/assets/Default_emissive.jpg
--------------------------------------------------------------------------------
/web/examples/gltf/assets/DamagedHelmet.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/gltf/assets/DamagedHelmet.bin
--------------------------------------------------------------------------------
/web/examples/gltf/assets/Default_albedo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/gltf/assets/Default_albedo.jpg
--------------------------------------------------------------------------------
/web/examples/gltf/assets/Default_normal.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/gltf/assets/Default_normal.jpg
--------------------------------------------------------------------------------
/examples/gltf/assets/Default_metalRoughness.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/examples/gltf/assets/Default_metalRoughness.jpg
--------------------------------------------------------------------------------
/web/examples/gltf/assets/Default_emissive.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/gltf/assets/Default_emissive.jpg
--------------------------------------------------------------------------------
/src/math/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod color;
2 | pub mod euler;
3 | pub mod matrix3;
4 | pub mod matrix3gpu;
5 | pub mod matrix4;
6 | pub mod quaternion;
7 | pub mod vector3;
--------------------------------------------------------------------------------
/web/examples/gltf/assets/Default_metalRoughness.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/gltf/assets/Default_metalRoughness.jpg
--------------------------------------------------------------------------------
/src/utils/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod file_loader;
2 | pub mod log;
3 | pub mod geometry_helper;
4 | pub mod gltf_loader;
5 | pub mod material_helper;
6 | pub mod texture_loader;
7 |
--------------------------------------------------------------------------------
/web/examples/cube/wgpu_rust_renderer_example_cube_bg.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/cube/wgpu_rust_renderer_example_cube_bg.wasm
--------------------------------------------------------------------------------
/web/examples/gltf/wgpu_rust_renderer_example_gltf_bg.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/gltf/wgpu_rust_renderer_example_gltf_bg.wasm
--------------------------------------------------------------------------------
/web/examples/texture/wgpu_rust_renderer_example_texture_bg.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/texture/wgpu_rust_renderer_example_texture_bg.wasm
--------------------------------------------------------------------------------
/web/examples/rotation/wgpu_rust_renderer_example_rotation_bg.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/rotation/wgpu_rust_renderer_example_rotation_bg.wasm
--------------------------------------------------------------------------------
/web/examples/triangle/wgpu_rust_renderer_example_triangle_bg.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/triangle/wgpu_rust_renderer_example_triangle_bg.wasm
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub mod geometry;
2 | pub mod material;
3 | pub mod math;
4 | pub mod renderer;
5 | pub mod resource;
6 | pub mod scene;
7 | pub mod texture;
8 | pub mod utils;
9 | pub mod web;
10 |
--------------------------------------------------------------------------------
/web/examples/face_culling/wgpu_rust_renderer_example_face_culling_bg.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/takahirox/wgpu-rust-renderer/HEAD/web/examples/face_culling/wgpu_rust_renderer_example_face_culling_bg.wasm
--------------------------------------------------------------------------------
/src/renderer/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod wgpu_attributes;
2 | pub mod wgpu_bindings;
3 | pub mod wgpu_indices;
4 | pub mod wgpu_render_pipeline;
5 | pub mod wgpu_renderer;
6 | pub mod wgpu_samplers;
7 | pub mod wgpu_textures;
8 |
--------------------------------------------------------------------------------
/web/examples/icons/ic_arrow_drop_down_black_24dp.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/web/examples/icons/ic_menu_black_24dp.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/web/examples/cube/build.sh:
--------------------------------------------------------------------------------
1 | RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --no-default-features --release --lib --target wasm32-unknown-unknown
2 | wasm-bindgen ./target/wasm32-unknown-unknown/release/wgpu_rust_renderer_example_cube.wasm --out-dir ./ --target web --no-typescript
3 |
--------------------------------------------------------------------------------
/web/examples/gltf/build.sh:
--------------------------------------------------------------------------------
1 | RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --no-default-features --release --lib --target wasm32-unknown-unknown
2 | wasm-bindgen ./target/wasm32-unknown-unknown/release/wgpu_rust_renderer_example_gltf.wasm --out-dir ./ --target web --no-typescript
3 |
--------------------------------------------------------------------------------
/web/examples/texture/build.sh:
--------------------------------------------------------------------------------
1 | RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --no-default-features --release --lib --target wasm32-unknown-unknown
2 | wasm-bindgen ./target/wasm32-unknown-unknown/release/wgpu_rust_renderer_example_texture.wasm --out-dir ./ --target web --no-typescript
3 |
--------------------------------------------------------------------------------
/web/examples/rotation/build.sh:
--------------------------------------------------------------------------------
1 | RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --no-default-features --release --lib --target wasm32-unknown-unknown
2 | wasm-bindgen ./target/wasm32-unknown-unknown/release/wgpu_rust_renderer_example_rotation.wasm --out-dir ./ --target web --no-typescript
3 |
--------------------------------------------------------------------------------
/web/examples/triangle/build.sh:
--------------------------------------------------------------------------------
1 | RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --no-default-features --release --lib --target wasm32-unknown-unknown
2 | wasm-bindgen ./target/wasm32-unknown-unknown/release/wgpu_rust_renderer_example_triangle.wasm --out-dir ./ --target web --no-typescript
3 |
--------------------------------------------------------------------------------
/web/examples/face_culling/build.sh:
--------------------------------------------------------------------------------
1 | RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --no-default-features --release --lib --target wasm32-unknown-unknown
2 | wasm-bindgen ./target/wasm32-unknown-unknown/release/wgpu_rust_renderer_example_face_culling.wasm --out-dir ./ --target web --no-typescript
3 |
--------------------------------------------------------------------------------
/web/examples/icons/ic_close_black_24dp.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/utils/log.rs:
--------------------------------------------------------------------------------
1 | // Non-Wasm
2 |
3 | #[cfg(not(target_arch = "wasm32"))]
4 | pub fn log(s: &str) {
5 | println!("{}", s);
6 | }
7 |
8 | // Wasm
9 |
10 | #[cfg(target_arch = "wasm32")]
11 | use wasm_bindgen::prelude::*;
12 |
13 | #[cfg(target_arch = "wasm32")]
14 | #[wasm_bindgen]
15 | extern "C" {
16 | #[wasm_bindgen(js_namespace = console)]
17 | pub fn log(s: &str);
18 | }
19 |
--------------------------------------------------------------------------------
/src/geometry/index.rs:
--------------------------------------------------------------------------------
1 | // @TODO: Should we reuse Attribute?
2 |
3 | pub struct Index {
4 | count: u32,
5 | data: Vec,
6 | }
7 |
8 | impl Index {
9 | pub fn new(data: Vec) -> Self {
10 | Index {
11 | count: data.len() as u32,
12 | data: data,
13 | }
14 | }
15 |
16 | pub fn get_count(&self) -> u32 {
17 | self.count
18 | }
19 |
20 | pub fn borrow_data(&self) -> &Vec {
21 | &self.data
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/material/node/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod add;
2 | pub mod brdf;
3 | pub mod const_float;
4 | pub mod const_vector3;
5 | pub mod float;
6 | pub mod linear_to_srgb;
7 | pub mod multiply;
8 | pub mod node;
9 | pub mod normal;
10 | pub mod normal_matrix;
11 | pub mod srgb_to_linear;
12 | pub mod sub;
13 | pub mod tangent_to_object_normal;
14 | pub mod texture;
15 | pub mod vector3;
16 | pub mod xyz;
17 | pub mod x;
18 | pub mod y;
19 | pub mod z;
20 |
--------------------------------------------------------------------------------
/web/examples/icons/ic_search_black_24dp.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/geometry/attribute.rs:
--------------------------------------------------------------------------------
1 | pub struct Attribute {
2 | count: u32,
3 | data: Vec,
4 | _item_size: u32,
5 | }
6 |
7 | impl Attribute {
8 | pub fn new(data: Vec, item_size: u32) -> Self {
9 | Attribute {
10 | count: data.len() as u32 / item_size,
11 | data: data,
12 | _item_size: item_size,
13 | }
14 | }
15 |
16 | pub fn get_count(&self) -> u32 {
17 | self.count
18 | }
19 |
20 | pub fn borrow_data(&self) -> &Vec {
21 | &self.data
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/math/color.rs:
--------------------------------------------------------------------------------
1 | const ELEMENT_NUM: usize = 3;
2 | type Elements = [f32; ELEMENT_NUM];
3 |
4 | pub struct Color {
5 | }
6 |
7 | impl Color {
8 | pub fn create() -> Elements {
9 | [0.0; ELEMENT_NUM]
10 | }
11 |
12 | pub fn set(c: &mut Elements, r: f32, g: f32, b: f32) -> &mut Elements {
13 | c[0] = r;
14 | c[1] = g;
15 | c[2] = b;
16 | c
17 | }
18 |
19 | pub fn copy<'a>(c: &'a mut Elements, c2: &'a Elements) -> &'a mut Elements {
20 | for i in 0..ELEMENT_NUM {
21 | c[i] = c2[i];
22 | }
23 | c
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/web/examples/cube/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wgpu_rust_renderer_example_cube"
3 | version = "0.1.0"
4 | authors = ["Takahiro "]
5 | edition = "2018"
6 | resolver = "2"
7 |
8 | [lib]
9 | path = "src/lib.rs"
10 | crate-type = ["cdylib"]
11 |
12 | [dependencies]
13 | console_error_panic_hook = "0.1.6"
14 | console_log = "0.1.2"
15 | wasm-bindgen = "0.2.78"
16 | wasm-bindgen-futures = "0.4.28"
17 | web-sys = "0.3.55"
18 | wgpu_rust_renderer = {path = "../../../"}
19 |
20 | [dependencies.winit]
21 | version = "0.25"
22 | features = ["web-sys"]
23 |
--------------------------------------------------------------------------------
/web/examples/gltf/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wgpu_rust_renderer_example_gltf"
3 | version = "0.1.0"
4 | authors = ["Takahiro "]
5 | edition = "2018"
6 | resolver = "2"
7 |
8 | [lib]
9 | path = "src/lib.rs"
10 | crate-type = ["cdylib"]
11 |
12 | [dependencies]
13 | console_error_panic_hook = "0.1.6"
14 | console_log = "0.1.2"
15 | wasm-bindgen = "0.2.78"
16 | wasm-bindgen-futures = "0.4.28"
17 | web-sys = "0.3.55"
18 | wgpu_rust_renderer = {path = "../../../"}
19 |
20 | [dependencies.winit]
21 | version = "0.25"
22 | features = ["web-sys"]
23 |
--------------------------------------------------------------------------------
/web/examples/rotation/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wgpu_rust_renderer_example_rotation"
3 | version = "0.1.0"
4 | authors = ["Takahiro "]
5 | edition = "2018"
6 | resolver = "2"
7 |
8 | [lib]
9 | path = "src/lib.rs"
10 | crate-type = ["cdylib"]
11 |
12 | [dependencies]
13 | console_error_panic_hook = "0.1.6"
14 | console_log = "0.1.2"
15 | wasm-bindgen = "0.2.78"
16 | wasm-bindgen-futures = "0.4.28"
17 | web-sys = "0.3.55"
18 | wgpu_rust_renderer = {path = "../../../"}
19 |
20 | [dependencies.winit]
21 | version = "0.25"
22 | features = ["web-sys"]
23 |
--------------------------------------------------------------------------------
/web/examples/texture/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wgpu_rust_renderer_example_texture"
3 | version = "0.1.0"
4 | authors = ["Takahiro "]
5 | edition = "2018"
6 | resolver = "2"
7 |
8 | [lib]
9 | path = "src/lib.rs"
10 | crate-type = ["cdylib"]
11 |
12 | [dependencies]
13 | console_error_panic_hook = "0.1.6"
14 | console_log = "0.1.2"
15 | wasm-bindgen = "0.2.78"
16 | wasm-bindgen-futures = "0.4.28"
17 | web-sys = "0.3.55"
18 | wgpu_rust_renderer = {path = "../../../"}
19 |
20 | [dependencies.winit]
21 | version = "0.25"
22 | features = ["web-sys"]
23 |
--------------------------------------------------------------------------------
/web/examples/triangle/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wgpu_rust_renderer_example_triangle"
3 | version = "0.1.0"
4 | authors = ["Takahiro "]
5 | edition = "2018"
6 | resolver = "2"
7 |
8 | [lib]
9 | path = "src/lib.rs"
10 | crate-type = ["cdylib"]
11 |
12 | [dependencies]
13 | console_error_panic_hook = "0.1.6"
14 | console_log = "0.1.2"
15 | wasm-bindgen = "0.2.78"
16 | wasm-bindgen-futures = "0.4.28"
17 | web-sys = "0.3.55"
18 | wgpu_rust_renderer = {path = "../../../"}
19 |
20 | [dependencies.winit]
21 | version = "0.25"
22 | features = ["web-sys"]
23 |
--------------------------------------------------------------------------------
/web/examples/face_culling/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wgpu_rust_renderer_example_face_culling"
3 | version = "0.1.0"
4 | authors = ["Takahiro "]
5 | edition = "2018"
6 | resolver = "2"
7 |
8 | [lib]
9 | path = "src/lib.rs"
10 | crate-type = ["cdylib"]
11 |
12 | [dependencies]
13 | console_error_panic_hook = "0.1.6"
14 | console_log = "0.1.2"
15 | wasm-bindgen = "0.2.78"
16 | wasm-bindgen-futures = "0.4.28"
17 | web-sys = "0.3.55"
18 | wgpu_rust_renderer = {path = "../../../"}
19 |
20 | [dependencies.winit]
21 | version = "0.25"
22 | features = ["web-sys"]
23 |
--------------------------------------------------------------------------------
/src/scene/mesh.rs:
--------------------------------------------------------------------------------
1 | use crate::{
2 | geometry::geometry::Geometry,
3 | material::material::Material,
4 | resource::resource::ResourceId,
5 | };
6 |
7 | // @TODO: Support shared geometry and material
8 | pub struct Mesh {
9 | geometry: ResourceId,
10 | material: ResourceId,
11 | }
12 |
13 | impl Mesh {
14 | pub fn new(
15 | geometry: ResourceId,
16 | material: ResourceId,
17 | ) -> Self {
18 | Mesh {
19 | geometry: geometry,
20 | material: material,
21 | }
22 | }
23 |
24 | pub fn borrow_geometry(&self) -> &ResourceId {
25 | &self.geometry
26 | }
27 |
28 | pub fn borrow_material(&self) -> &ResourceId {
29 | &self.material
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/math/euler.rs:
--------------------------------------------------------------------------------
1 | const ELEMENT_NUM: usize = 3;
2 | type Elements = [f32; ELEMENT_NUM];
3 |
4 | pub struct Euler {
5 | }
6 |
7 | impl Euler {
8 | pub fn create() -> Elements {
9 | [0.0; ELEMENT_NUM]
10 | }
11 |
12 | pub fn set_from_quaternion<'a>(
13 | e: &'a mut Elements,
14 | q: &'a [f32; 4],
15 | ) -> &'a mut Elements {
16 | // Assume XYZ order
17 | let q0 = q[0];
18 | let q1 = q[1];
19 | let q2 = q[2];
20 | let q3 = q[3];
21 |
22 | let q0q0 = q0 * q0;
23 | let q0q1 = q0 * q1;
24 | let q0q2 = q0 * q2;
25 | let q0q3 = q0 * q3;
26 | let q1q1 = q1 * q1;
27 | let q1q2 = q1 * q2;
28 | let q1q3 = q1 * q3;
29 | let q2q2 = q2 * q2;
30 | let q2q3 = q2 * q3;
31 | let q3q3 = q3 * q3;
32 |
33 | let roll = (2.0 * (q2q3 + q0q1)).atan2(q0q0 - q1q1 - q2q2 + q3q3);
34 | let pitch = (2.0 * (q0q2 - q1q3)).asin();
35 | let yaw = (2.0 * (q1q2 + q0q3)).atan2(q0q0 + q1q1 - q2q2 - q3q3);
36 |
37 | e[0] = roll;
38 | e[1] = pitch;
39 | e[2] = yaw;
40 |
41 | e
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/texture/texture.rs:
--------------------------------------------------------------------------------
1 | // @TODO: Support more format
2 | pub enum TextureFormat {
3 | Float,
4 | Uint8,
5 | Uint8Srgb,
6 | }
7 |
8 | impl Default for TextureFormat {
9 | fn default() -> Self {
10 | TextureFormat::Uint8
11 | }
12 | }
13 |
14 | // @TODO: Support 3D texture
15 | pub struct Texture {
16 | format: TextureFormat,
17 | height: u32,
18 | texels: Vec, // @TODO: Support shared texels?
19 | width: u32,
20 | }
21 |
22 | impl Texture {
23 | pub fn new(
24 | width: u32,
25 | height: u32,
26 | format: TextureFormat,
27 | texels: Vec,
28 | ) -> Self {
29 | Texture {
30 | format: format,
31 | height: height,
32 | texels: texels,
33 | width: width,
34 | }
35 | }
36 |
37 | pub fn get_width(&self) -> u32 {
38 | self.width
39 | }
40 |
41 | pub fn get_height(&self) -> u32 {
42 | self.height
43 | }
44 |
45 | pub fn borrow_format(&self) -> &TextureFormat {
46 | &self.format
47 | }
48 |
49 | pub fn borrow_texels(&self) -> &Vec {
50 | &self.texels
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/web/examples/cube/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebGPU Rust Renderer example - cube
4 |
5 |
6 |
7 |
13 |
14 |
15 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/web/examples/gltf/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebGPU Rust Renderer example - glTF
4 |
5 |
6 |
7 |
13 |
14 |
15 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/web/examples/texture/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebGPU Rust Renderer example - cube
4 |
5 |
6 |
7 |
13 |
14 |
15 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/web/examples/rotation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebGPU Rust Renderer example - rotation
4 |
5 |
6 |
7 |
13 |
14 |
15 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/web/examples/triangle/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebGPU Rust Renderer example - triangle
4 |
5 |
6 |
7 |
13 |
14 |
15 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/web/examples/face_culling/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | WebGPU Rust Renderer example - Face culling
4 |
5 |
6 |
7 |
13 |
14 |
15 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Takahiro
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/geometry/geometry.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use crate::{
4 | geometry::{
5 | attribute::Attribute,
6 | index::Index,
7 | },
8 | resource::resource::ResourceId,
9 | };
10 |
11 | // @TODO: Support shared attribute
12 | pub struct Geometry {
13 | attributes: HashMap<&'static str, ResourceId>,
14 | index: Option>,
15 | }
16 |
17 | impl Geometry {
18 | pub fn new() -> Self {
19 | Geometry {
20 | attributes: HashMap::new(),
21 | index: None,
22 | }
23 | }
24 |
25 | pub fn set_attribute(&mut self, key: &'static str, attribute: ResourceId) -> &mut Self {
26 | self.attributes.insert(key, attribute);
27 | self
28 | }
29 |
30 | pub fn borrow_attribute(&self, key: &'static str) -> Option<&ResourceId> {
31 | self.attributes.get(key)
32 | }
33 |
34 | pub fn set_index(&mut self, index: ResourceId) -> &mut Self {
35 | self.index = Some(index);
36 | self
37 | }
38 |
39 | pub fn remove_index(&mut self) -> &mut Self {
40 | self.index = None;
41 | self
42 | }
43 |
44 | pub fn borrow_index(&self) -> Option<&ResourceId> {
45 | self.index.as_ref()
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/math/matrix3gpu.rs:
--------------------------------------------------------------------------------
1 | const ELEMENT_NUM: usize = 12;
2 | type Elements = [f32; ELEMENT_NUM];
3 |
4 | pub struct Matrix3GPU {
5 | }
6 |
7 | impl Matrix3GPU {
8 | pub fn create() -> Elements {
9 | let mut elements = [0.0; ELEMENT_NUM];
10 | Self::identity(&mut elements);
11 | elements
12 | }
13 |
14 | pub fn identity(m: &mut Elements) -> &mut Elements {
15 | m[0] = 1.0;
16 | m[1] = 0.0;
17 | m[2] = 0.0;
18 | m[3] = 0.0;
19 | m[4] = 0.0;
20 | m[5] = 1.0;
21 | m[6] = 0.0;
22 | m[7] = 0.0;
23 | m[8] = 0.0;
24 | m[9] = 0.0;
25 | m[10] = 1.0;
26 | m[11] = 0.0;
27 | m
28 | }
29 |
30 | pub fn copy<'a>(m: &'a mut Elements, src: &'a Elements) -> &'a mut Elements {
31 | for i in 0..ELEMENT_NUM {
32 | m[i] = src[i];
33 | }
34 | m
35 | }
36 |
37 | pub fn copy_from_matrix3<'a>(m: &'a mut Elements, src: &'a [f32; 9]) -> &'a mut Elements {
38 | // @TODO: Use loop?
39 | m[0] = src[0];
40 | m[1] = src[1];
41 | m[2] = src[2];
42 | m[3] = 0.0;
43 | m[4] = src[3];
44 | m[5] = src[4];
45 | m[6] = src[5];
46 | m[7] = 0.0;
47 | m[8] = src[6];
48 | m[9] = src[7];
49 | m[10] = src[8];
50 | m[11] = 0.0;
51 | m
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/material/node/node.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | resource::resource::{
4 | ResourceId,
5 | ResourcePool,
6 | },
7 | texture::{
8 | sampler::Sampler,
9 | texture::Texture,
10 | },
11 | };
12 |
13 | pub enum UniformContents {
14 | Float {value: [f32; 1]},
15 | Matrix4 {value: [f32; 16]},
16 | Vector3 {value: [f32; 3]},
17 | Texture {
18 | texture: ResourceId,
19 | sampler: ResourceId,
20 | },
21 | }
22 |
23 | pub trait MaterialNode {
24 | fn collect_nodes (
25 | &self,
26 | pool: &ResourcePool>,
27 | nodes: &mut Vec>>,
28 | visited: &mut HashMap>, bool>,
29 | self_rid: ResourceId>,
30 | );
31 | fn borrow_contents(&self) -> Option<&UniformContents>;
32 | fn build_declaration(&self, self_id: usize) -> String;
33 | fn build_functions(&self, self_id: usize) -> String;
34 | fn build_fragment_shader(
35 | &self,
36 | pool: &ResourcePool>,
37 | visited: &mut HashMap,
38 | self_id: usize,
39 | ) -> String;
40 | fn get_fragment_output(&self, self_id: usize) -> String;
41 | }
42 |
43 | // @TODO: Ensure unique variable names
44 |
--------------------------------------------------------------------------------
/src/math/vector3.rs:
--------------------------------------------------------------------------------
1 | const ELEMENT_NUM: usize = 3;
2 | type Elements = [f32; ELEMENT_NUM];
3 |
4 | pub struct Vector3 {
5 | }
6 |
7 | impl Vector3 {
8 | pub fn create() -> Elements {
9 | [0.0; ELEMENT_NUM]
10 | }
11 |
12 | pub fn set(v: &mut Elements, x: f32, y: f32, z: f32) -> &mut Elements {
13 | v[0] = x;
14 | v[1] = y;
15 | v[2] = z;
16 | v
17 | }
18 |
19 | pub fn copy<'a>(v: &'a mut Elements, v2: &'a Elements) -> &'a mut Elements {
20 | for i in 0..ELEMENT_NUM {
21 | v[i] = v2[i];
22 | }
23 | v
24 | }
25 |
26 | pub fn add<'a>(v: &'a mut Elements, v2: &'a Elements) -> &'a mut Elements {
27 | for i in 0..ELEMENT_NUM {
28 | v[i] += v2[i];
29 | }
30 | v
31 | }
32 |
33 | pub fn sub<'a>(v: &'a mut Elements, v2: &'a Elements) -> &'a mut Elements {
34 | for i in 0..ELEMENT_NUM {
35 | v[i] -= v2[i];
36 | }
37 | v
38 | }
39 |
40 | pub fn length(v: &Elements) -> f32 {
41 | (v[0].powf(2.0) + v[1].powf(2.0) + v[2].powf(2.0)).sqrt()
42 | }
43 |
44 | pub fn normalize(v: &mut Elements) -> &mut Elements {
45 | let length = Self::length(v);
46 |
47 | // @TODO: Error handling?
48 | if length != 0.0 {
49 | for i in 0..ELEMENT_NUM {
50 | v[i] /= length;
51 | }
52 | }
53 |
54 | v
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/scene/camera.rs:
--------------------------------------------------------------------------------
1 | use crate::math::matrix4::Matrix4;
2 |
3 | pub struct PerspectiveCamera {
4 | aspect: f32,
5 | far: f32,
6 | fovy: f32,
7 | near: f32,
8 | projection_matrix: [f32; 16],
9 | projection_matrix_inverse: [f32; 16],
10 | }
11 |
12 | impl PerspectiveCamera {
13 | pub fn new(fovy: f32, aspect: f32, near: f32, far: f32) -> Self {
14 | let mut camera = PerspectiveCamera {
15 | aspect: aspect,
16 | far: far,
17 | fovy: fovy,
18 | near: near,
19 | projection_matrix: Matrix4::create(),
20 | projection_matrix_inverse: Matrix4::create(),
21 | };
22 | camera.update_projection_matrix();
23 | camera
24 | }
25 |
26 | pub fn set_aspect(&mut self, aspect: f32) -> &mut Self {
27 | self.aspect = aspect;
28 | self.update_projection_matrix();
29 | self
30 | }
31 |
32 | pub fn update_projection_matrix(&mut self) {
33 | Matrix4::make_perspective(
34 | &mut self.projection_matrix,
35 | self.fovy,
36 | self.aspect,
37 | self.near,
38 | self.far,
39 | );
40 | Matrix4::invert(
41 | Matrix4::copy(&mut self.projection_matrix_inverse, &self.projection_matrix)
42 | );
43 | }
44 |
45 | pub fn borrow_projection_matrix(&self) -> &[f32; 16] {
46 | &self.projection_matrix
47 | }
48 |
49 | pub fn borrow_projection_matrix_inverse(&self) -> &[f32; 16] {
50 | &self.projection_matrix_inverse
51 | }
52 | }
--------------------------------------------------------------------------------
/web/examples/utils/window.rs:
--------------------------------------------------------------------------------
1 | use wasm_bindgen::{
2 | JsCast,
3 | prelude::*,
4 | };
5 | use winit::{
6 | event_loop::EventLoop,
7 | };
8 |
9 | // Window and DOM element helpers
10 |
11 | pub fn get_window_inner_size() -> (f64, f64) {
12 | let window = web_sys::window().unwrap();
13 | (
14 | window.inner_width().unwrap().as_f64().unwrap(),
15 | window.inner_height().unwrap().as_f64().unwrap()
16 | )
17 | }
18 |
19 | pub fn get_window_device_pixel_ratio() -> f64 {
20 | let window = web_sys::window().unwrap();
21 | window.device_pixel_ratio()
22 | }
23 |
24 | pub fn create_window(event_loop: &EventLoop<()>) -> std::rc::Rc {
25 | let window = winit::window::Window::new(&event_loop).unwrap();
26 | let window = std::rc::Rc::new(window);
27 |
28 | // winit::window::Window doesn't seem to detect browser's onresize event so we emulate it.
29 | {
30 | let window = window.clone();
31 | let closure = Closure::wrap(Box::new(move |_e: web_sys::Event| {
32 | let size = get_window_inner_size();
33 | window.set_inner_size(winit::dpi::PhysicalSize::new(
34 | size.0, size.1,
35 | ));
36 | }) as Box);
37 | web_sys::window()
38 | .unwrap()
39 | .add_event_listener_with_callback("resize", closure.as_ref().unchecked_ref())
40 | .unwrap();
41 | closure.forget();
42 | }
43 |
44 | window
45 | }
46 |
--------------------------------------------------------------------------------
/src/material/node/normal.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct NormalNode {
14 | }
15 |
16 | impl NormalNode {
17 | pub fn new() -> Self {
18 | NormalNode {
19 | }
20 | }
21 | }
22 |
23 | impl MaterialNode for NormalNode {
24 | fn collect_nodes (
25 | &self,
26 | _pool: &ResourcePool>,
27 | nodes: &mut Vec>>,
28 | visited: &mut HashMap>, bool>,
29 | self_rid: ResourceId>,
30 | ) {
31 | if !visited.contains_key(&self_rid) {
32 | visited.insert(self_rid, true);
33 | nodes.push(self_rid);
34 | }
35 | }
36 |
37 | fn borrow_contents(&self) -> Option<&UniformContents> {
38 | None
39 | }
40 |
41 | fn build_declaration(&self, _self_id: usize) -> String {
42 | format!("")
43 | }
44 |
45 | fn build_functions(&self, _self_id: usize) -> String {
46 | format!("")
47 | }
48 |
49 | fn build_fragment_shader(
50 | &self,
51 | _pool: &ResourcePool>,
52 | _visited: &mut HashMap,
53 | _self_id: usize,
54 | ) -> String {
55 | format!("")
56 | }
57 |
58 | fn get_fragment_output(&self, _self_id: usize) -> String {
59 | format!("in.normal")
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/renderer/wgpu_attributes.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 |
3 | use crate::{
4 | geometry::attribute::Attribute,
5 | resource::resource::{
6 | ResourceId,
7 | ResourcePools,
8 | },
9 | };
10 |
11 | pub struct WGPUAttributes {
12 | attributes: HashMap, wgpu::Buffer>,
13 | }
14 |
15 | impl WGPUAttributes {
16 | pub fn new() -> Self {
17 | WGPUAttributes {
18 | attributes: HashMap::new()
19 | }
20 | }
21 |
22 | pub fn borrow(&self, attribute: &ResourceId) -> Option<&wgpu::Buffer> {
23 | self.attributes.get(attribute)
24 | }
25 |
26 | // @TODO: Implement correctly
27 | pub fn update(
28 | &mut self,
29 | device: &wgpu::Device,
30 | pools: &ResourcePools,
31 | attribute_rid: &ResourceId,
32 | ) {
33 | if !self.attributes.contains_key(attribute_rid) {
34 | if let Some(attribute) = pools.borrow::().borrow(attribute_rid) {
35 | self.attributes.insert(*attribute_rid, create_buffer(
36 | device,
37 | bytemuck::cast_slice(attribute.borrow_data()),
38 | wgpu::BufferUsages::VERTEX,
39 | ));
40 | }
41 | }
42 | }
43 | }
44 |
45 | fn create_buffer(device: &wgpu::Device, contents: &[u8], usage: wgpu::BufferUsages) -> wgpu::Buffer {
46 | use wgpu::util::DeviceExt;
47 | device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
48 | label: None,
49 | contents: contents,
50 | usage: usage,
51 | })
52 | }
53 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "wgpu_rust_renderer"
3 | version = "0.0.4"
4 | description = "Tiny WebGPU Renderer in Rust"
5 | authors = ["Takahiro "]
6 | edition = "2018"
7 | license = "MIT"
8 | resolver = "2"
9 | homepage = "https://github.com/takahirox/wgpu-rust-renderer"
10 | repository = "https://github.com/takahirox/wgpu-rust-renderer"
11 | exclude = [
12 | "screenshots/*",
13 | "web/*"
14 | ]
15 |
16 | [dependencies]
17 | bytemuck = {version = "1.7.2", features = ["derive"]}
18 | futures = "0.3.17"
19 | gltf = "0.16.0"
20 | png = "0.17.1"
21 | wgpu = "0.11.0"
22 |
23 | [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
24 | jpeg-decoder = "0.1.22"
25 | winit = "0.25.0"
26 |
27 | [target.'cfg(target_arch = "wasm32")'.dependencies]
28 | jpeg-decoder = {version = "0.1.22", default-features = false}
29 | js-sys = "0.3.55"
30 | wasm-bindgen = "0.2.78"
31 | wasm-bindgen-futures = "0.4.28"
32 | winit = {version = "0.25.0", features = ["web-sys"]}
33 |
34 | [target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
35 | version = "0.3.55"
36 | features = [
37 | "CssStyleDeclaration",
38 | "HtmlCanvasElement",
39 | "Request",
40 | "RequestInit",
41 | "RequestMode",
42 | "Response",
43 | ]
44 |
45 | [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
46 | tokio = {version = "1.12.0", features = ["full"]}
47 |
48 | [badges]
49 | travis-ci = {repository = "takahirox/wgpu-rust-renderer"}
50 |
--------------------------------------------------------------------------------
/src/renderer/wgpu_indices.rs:
--------------------------------------------------------------------------------
1 | // @TODO: Should we reuse wgpu_attributes?
2 |
3 | use std::collections::HashMap;
4 |
5 | use crate::{
6 | geometry::index::Index,
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePools,
10 | },
11 | };
12 |
13 | pub struct WGPUIndices {
14 | indices: HashMap, wgpu::Buffer>,
15 | }
16 |
17 | impl WGPUIndices {
18 | pub fn new() -> Self {
19 | WGPUIndices {
20 | indices: HashMap::new()
21 | }
22 | }
23 |
24 | pub fn borrow(&self, index: &ResourceId) -> Option<&wgpu::Buffer> {
25 | self.indices.get(index)
26 | }
27 |
28 | // @TODO: Implement correctly
29 | pub fn update(
30 | &mut self,
31 | device: &wgpu::Device,
32 | pools: &ResourcePools,
33 | index_rid: &ResourceId,
34 | ) {
35 | if !self.indices.contains_key(index_rid) {
36 | if let Some(index) = pools.borrow::().borrow(index_rid) {
37 | self.indices.insert(*index_rid, create_buffer(
38 | device,
39 | bytemuck::cast_slice(index.borrow_data()),
40 | wgpu::BufferUsages::INDEX,
41 | ));
42 | }
43 | }
44 | }
45 | }
46 |
47 | // @TODO: Remove duplication with wgpu_attributes.rs
48 | fn create_buffer(device: &wgpu::Device, contents: &[u8], usage: wgpu::BufferUsages) -> wgpu::Buffer {
49 | use wgpu::util::DeviceExt;
50 | device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
51 | label: None,
52 | contents: contents,
53 | usage: usage,
54 | })
55 | }
56 |
--------------------------------------------------------------------------------
/src/material/node/normal_matrix.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct NormalMatrixNode {
14 | }
15 |
16 | impl NormalMatrixNode {
17 | pub fn new() -> Self {
18 | NormalMatrixNode {
19 | }
20 | }
21 | }
22 |
23 | impl MaterialNode for NormalMatrixNode {
24 | fn collect_nodes (
25 | &self,
26 | _pool: &ResourcePool>,
27 | nodes: &mut Vec>>,
28 | visited: &mut HashMap>, bool>,
29 | self_rid: ResourceId>,
30 | ) {
31 | if !visited.contains_key(&self_rid) {
32 | visited.insert(self_rid, true);
33 | nodes.push(self_rid);
34 | }
35 | }
36 |
37 | fn borrow_contents(&self) -> Option<&UniformContents> {
38 | None
39 | }
40 |
41 | fn build_declaration(&self, _self_id: usize) -> String {
42 | format!("")
43 | }
44 |
45 | fn build_functions(&self, _self_id: usize) -> String {
46 | format!("")
47 | }
48 |
49 | fn build_fragment_shader(
50 | &self,
51 | _pool: &ResourcePool>,
52 | _visited: &mut HashMap,
53 | _self_id: usize,
54 | ) -> String {
55 | format!("")
56 | }
57 |
58 | fn get_fragment_output(&self, _self_id: usize) -> String {
59 | format!("object.normal_matrix")
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/material/node/const_float.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct ConstFloatNode {
14 | value: f32,
15 | }
16 |
17 | impl ConstFloatNode {
18 | pub fn new(value: f32) -> Self {
19 | ConstFloatNode {
20 | value: value,
21 | }
22 | }
23 | }
24 |
25 | impl MaterialNode for ConstFloatNode {
26 | fn collect_nodes (
27 | &self,
28 | _pool: &ResourcePool>,
29 | nodes: &mut Vec>>,
30 | visited: &mut HashMap>, bool>,
31 | self_rid: ResourceId>,
32 | ) {
33 | if !visited.contains_key(&self_rid) {
34 | visited.insert(self_rid, true);
35 | nodes.push(self_rid);
36 | }
37 | }
38 |
39 | fn borrow_contents(&self) -> Option<&UniformContents> {
40 | None
41 | }
42 |
43 | fn build_declaration(&self, _self_id: usize) -> String {
44 | format!("")
45 | }
46 |
47 | fn build_functions(&self, _self_id: usize) -> String {
48 | format!("")
49 | }
50 |
51 | fn build_fragment_shader(
52 | &self,
53 | _pool: &ResourcePool>,
54 | _visited: &mut HashMap,
55 | _self_id: usize,
56 | ) -> String {
57 | format!("")
58 | }
59 |
60 | fn get_fragment_output(&self, _self_id: usize) -> String {
61 | format!("{:.16}", self.value)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/material/node/float.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct FloatNode {
14 | contents: UniformContents,
15 | }
16 |
17 | impl FloatNode {
18 | pub fn new(value: f32) -> Self {
19 | FloatNode {
20 | contents: UniformContents::Float {
21 | value: [value],
22 | },
23 | }
24 | }
25 | }
26 |
27 | impl MaterialNode for FloatNode {
28 | fn collect_nodes (
29 | &self,
30 | _pool: &ResourcePool>,
31 | nodes: &mut Vec>>,
32 | visited: &mut HashMap>, bool>,
33 | self_rid: ResourceId>,
34 | ) {
35 | if !visited.contains_key(&self_rid) {
36 | visited.insert(self_rid, true);
37 | nodes.push(self_rid);
38 | }
39 | }
40 |
41 | fn borrow_contents(&self) -> Option<&UniformContents> {
42 | Some(&self.contents)
43 | }
44 |
45 | fn build_declaration(&self, self_id: usize) -> String {
46 | format!("f32_{}: f32;\n", self_id)
47 | }
48 |
49 | fn build_functions(&self, _self_id: usize) -> String {
50 | format!("")
51 | }
52 |
53 | fn build_fragment_shader(
54 | &self,
55 | _pool: &ResourcePool>,
56 | _visited: &mut HashMap,
57 | _self_id: usize,
58 | ) -> String {
59 | format!("")
60 | }
61 |
62 | fn get_fragment_output(&self, self_id: usize) -> String {
63 | format!("unif.f32_{}", self_id)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/material/node/const_vector3.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct ConstVector3Node {
14 | value: [f32; 3],
15 | }
16 |
17 | impl ConstVector3Node {
18 | pub fn new(value: [f32; 3]) -> Self {
19 | ConstVector3Node {
20 | value: value,
21 | }
22 | }
23 | }
24 |
25 | impl MaterialNode for ConstVector3Node {
26 | fn collect_nodes (
27 | &self,
28 | _pool: &ResourcePool>,
29 | nodes: &mut Vec>>,
30 | visited: &mut HashMap>, bool>,
31 | self_rid: ResourceId>,
32 | ) {
33 | if !visited.contains_key(&self_rid) {
34 | visited.insert(self_rid, true);
35 | nodes.push(self_rid);
36 | }
37 | }
38 |
39 | fn borrow_contents(&self) -> Option<&UniformContents> {
40 | None
41 | }
42 |
43 | fn build_declaration(&self, _self_id: usize) -> String {
44 | format!("")
45 | }
46 |
47 | fn build_functions(&self, _self_id: usize) -> String {
48 | format!("")
49 | }
50 |
51 | fn build_fragment_shader(
52 | &self,
53 | _pool: &ResourcePool>,
54 | _visited: &mut HashMap,
55 | _self_id: usize,
56 | ) -> String {
57 | format!("")
58 | }
59 |
60 | fn get_fragment_output(&self, _self_id: usize) -> String {
61 | format!("vec3({}, {}, {})",
62 | self.value[0],
63 | self.value[1],
64 | self.value[2],
65 | )
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/material/node/vector3.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct Vector3Node {
14 | contents: UniformContents,
15 | }
16 |
17 | impl Vector3Node {
18 | pub fn new(value: [f32; 3]) -> Self {
19 | Vector3Node {
20 | contents: UniformContents::Vector3 {
21 | value: value,
22 | },
23 | }
24 | }
25 | }
26 |
27 | impl MaterialNode for Vector3Node {
28 | fn collect_nodes (
29 | &self,
30 | _pool: &ResourcePool>,
31 | nodes: &mut Vec>>,
32 | visited: &mut HashMap>, bool>,
33 | self_rid: ResourceId>,
34 | ) {
35 | if !visited.contains_key(&self_rid) {
36 | visited.insert(self_rid, true);
37 | nodes.push(self_rid);
38 | }
39 | }
40 |
41 | fn borrow_contents(&self) -> Option<&UniformContents> {
42 | Some(&self.contents)
43 | }
44 |
45 | fn build_declaration(&self, self_id: usize) -> String {
46 | format!("vector3_{}: vec3;\n", self_id)
47 | }
48 |
49 | fn build_functions(&self, _self_id: usize) -> String {
50 | format!("")
51 | }
52 |
53 | fn build_fragment_shader(
54 | &self,
55 | _pool: &ResourcePool>,
56 | _visited: &mut HashMap,
57 | _self_id: usize,
58 | ) -> String {
59 | format!("")
60 | }
61 |
62 | fn get_fragment_output(&self, self_id: usize) -> String {
63 | format!("unif.vector3_{}", self_id)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/texture/sampler.rs:
--------------------------------------------------------------------------------
1 | pub enum WrapMode {
2 | ClampToBorder,
3 | ClampToEdge,
4 | MirrorRepeat,
5 | Repeat,
6 | }
7 |
8 | pub enum FilterMode {
9 | Linear,
10 | Nearest,
11 | }
12 |
13 | pub struct Sampler {
14 | mag_filter: FilterMode,
15 | min_filter: FilterMode,
16 | mipmap_filter: FilterMode,
17 | wrap_u: WrapMode,
18 | wrap_v: WrapMode,
19 | wrap_w: WrapMode,
20 | }
21 |
22 | pub struct SamplerDescriptor {
23 | pub mag_filter: FilterMode,
24 | pub min_filter: FilterMode,
25 | pub mipmap_filter: FilterMode,
26 | pub wrap_u: WrapMode,
27 | pub wrap_v: WrapMode,
28 | pub wrap_w: WrapMode,
29 | }
30 |
31 | impl Default for SamplerDescriptor {
32 | fn default() -> Self {
33 | SamplerDescriptor {
34 | mag_filter: FilterMode::Linear,
35 | min_filter: FilterMode::Linear,
36 | mipmap_filter: FilterMode::Linear,
37 | wrap_u: WrapMode::ClampToEdge,
38 | wrap_v: WrapMode::ClampToEdge,
39 | wrap_w: WrapMode::ClampToEdge,
40 | }
41 | }
42 | }
43 |
44 | impl Sampler {
45 | pub fn new(desc: SamplerDescriptor) -> Self {
46 | // @TODO: Fix default parameters
47 | Sampler {
48 | mag_filter: desc.mag_filter,
49 | min_filter: desc.min_filter,
50 | mipmap_filter: desc.mipmap_filter,
51 | wrap_u: desc.wrap_u,
52 | wrap_v: desc.wrap_v,
53 | wrap_w: desc.wrap_w,
54 | }
55 | }
56 |
57 | pub fn mag_filter(&self) -> &FilterMode {
58 | &self.mag_filter
59 | }
60 |
61 | pub fn min_filter(&self) -> &FilterMode {
62 | &self.min_filter
63 | }
64 |
65 | pub fn mipmap_filter(&self) -> &FilterMode {
66 | &self.mipmap_filter
67 | }
68 |
69 | pub fn wrap_u(&self) -> &WrapMode {
70 | &self.wrap_u
71 | }
72 |
73 | pub fn wrap_v(&self) -> &WrapMode {
74 | &self.wrap_v
75 | }
76 |
77 | pub fn wrap_w(&self) -> &WrapMode {
78 | &self.wrap_w
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/material/node/x.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct XNode {
14 | node: ResourceId>,
15 | }
16 |
17 | impl XNode {
18 | pub fn new(
19 | node: ResourceId>,
20 | ) -> Self {
21 | XNode {
22 | node: node,
23 | }
24 | }
25 | }
26 |
27 | impl MaterialNode for XNode {
28 | fn collect_nodes (
29 | &self,
30 | pool: &ResourcePool>,
31 | nodes: &mut Vec>>,
32 | visited: &mut HashMap>, bool>,
33 | self_rid: ResourceId>,
34 | ) {
35 | pool.borrow(&self.node).unwrap().collect_nodes(
36 | pool, nodes, visited, self.node,
37 | );
38 | if !visited.contains_key(&self_rid) {
39 | visited.insert(self_rid, true);
40 | nodes.push(self_rid);
41 | }
42 | }
43 |
44 | fn borrow_contents(&self) -> Option<&UniformContents> {
45 | None
46 | }
47 |
48 | fn build_declaration(&self, _self_id: usize) -> String {
49 | format!("")
50 | }
51 |
52 | fn build_functions(&self, _self_id: usize) -> String {
53 | format!("")
54 | }
55 |
56 | fn build_fragment_shader(
57 | &self,
58 | pool: &ResourcePool>,
59 | visited: &mut HashMap,
60 | self_id: usize,
61 | ) -> String {
62 | if visited.contains_key(&self_id) {
63 | return "".to_string();
64 | }
65 | visited.insert(self_id, true);
66 |
67 | let node = pool.borrow(&self.node).unwrap();
68 |
69 | node.build_fragment_shader(pool, visited, self.node.id) +
70 | &format!("let {} = {}.x;\n",
71 | self.get_fragment_output(self_id),
72 | node.get_fragment_output(self.node.id),
73 | )
74 | }
75 |
76 | fn get_fragment_output(&self, self_id: usize) -> String {
77 | format!("x_output_{}", self_id)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/material/node/y.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct YNode {
14 | node: ResourceId>,
15 | }
16 |
17 | impl YNode {
18 | pub fn new(
19 | node: ResourceId>,
20 | ) -> Self {
21 | YNode {
22 | node: node,
23 | }
24 | }
25 | }
26 |
27 | impl MaterialNode for YNode {
28 | fn collect_nodes (
29 | &self,
30 | pool: &ResourcePool>,
31 | nodes: &mut Vec>>,
32 | visited: &mut HashMap>, bool>,
33 | self_rid: ResourceId>,
34 | ) {
35 | pool.borrow(&self.node).unwrap().collect_nodes(
36 | pool, nodes, visited, self.node,
37 | );
38 | if !visited.contains_key(&self_rid) {
39 | visited.insert(self_rid, true);
40 | nodes.push(self_rid);
41 | }
42 | }
43 |
44 | fn borrow_contents(&self) -> Option<&UniformContents> {
45 | None
46 | }
47 |
48 | fn build_declaration(&self, _self_id: usize) -> String {
49 | format!("")
50 | }
51 |
52 | fn build_functions(&self, _self_id: usize) -> String {
53 | format!("")
54 | }
55 |
56 | fn build_fragment_shader(
57 | &self,
58 | pool: &ResourcePool>,
59 | visited: &mut HashMap,
60 | self_id: usize,
61 | ) -> String {
62 | if visited.contains_key(&self_id) {
63 | return "".to_string();
64 | }
65 | visited.insert(self_id, true);
66 |
67 | let node = pool.borrow(&self.node).unwrap();
68 |
69 | node.build_fragment_shader(pool, visited, self.node.id) +
70 | &format!("let {} = {}.y;\n",
71 | self.get_fragment_output(self_id),
72 | node.get_fragment_output(self.node.id),
73 | )
74 | }
75 |
76 | fn get_fragment_output(&self, self_id: usize) -> String {
77 | format!("y_output_{}", self_id)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/material/node/z.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct ZNode {
14 | node: ResourceId>,
15 | }
16 |
17 | impl ZNode {
18 | pub fn new(
19 | node: ResourceId>,
20 | ) -> Self {
21 | ZNode {
22 | node: node,
23 | }
24 | }
25 | }
26 |
27 | impl MaterialNode for ZNode {
28 | fn collect_nodes<'a> (
29 | &self,
30 | pool: &ResourcePool>,
31 | nodes: &mut Vec>>,
32 | visited: &mut HashMap>, bool>,
33 | self_rid: ResourceId>,
34 | ) {
35 | pool.borrow(&self.node).unwrap().collect_nodes(
36 | pool, nodes, visited, self.node,
37 | );
38 | if !visited.contains_key(&self_rid) {
39 | visited.insert(self_rid, true);
40 | nodes.push(self_rid);
41 | }
42 | }
43 |
44 | fn borrow_contents(&self) -> Option<&UniformContents> {
45 | None
46 | }
47 |
48 | fn build_declaration(&self, _self_id: usize) -> String {
49 | format!("")
50 | }
51 |
52 | fn build_functions(&self, _self_id: usize) -> String {
53 | format!("")
54 | }
55 |
56 | fn build_fragment_shader(
57 | &self,
58 | pool: &ResourcePool>,
59 | visited: &mut HashMap,
60 | self_id: usize,
61 | ) -> String {
62 | if visited.contains_key(&self_id) {
63 | return "".to_string();
64 | }
65 | visited.insert(self_id, true);
66 |
67 | let node = pool.borrow(&self.node).unwrap();
68 |
69 | node.build_fragment_shader(pool, visited, self.node.id) +
70 | &format!("let {} = {}.z;\n",
71 | self.get_fragment_output(self_id),
72 | node.get_fragment_output(self.node.id),
73 | )
74 | }
75 |
76 | fn get_fragment_output(&self, self_id: usize) -> String {
77 | format!("z_output_{}", self_id)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/material/node/xyz.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct XYZNode {
14 | node: ResourceId>,
15 | }
16 |
17 | impl XYZNode {
18 | pub fn new(
19 | node: ResourceId>,
20 | ) -> Self {
21 | XYZNode {
22 | node: node,
23 | }
24 | }
25 | }
26 |
27 | impl MaterialNode for XYZNode {
28 | fn collect_nodes (
29 | &self,
30 | pool: &ResourcePool>,
31 | nodes: &mut Vec>>,
32 | visited: &mut HashMap>, bool>,
33 | self_rid: ResourceId>,
34 | ) {
35 | pool.borrow(&self.node).unwrap().collect_nodes(
36 | pool, nodes, visited, self.node,
37 | );
38 | if !visited.contains_key(&self_rid) {
39 | visited.insert(self_rid, true);
40 | nodes.push(self_rid);
41 | }
42 | }
43 |
44 | fn borrow_contents(&self) -> Option<&UniformContents> {
45 | None
46 | }
47 |
48 | fn build_declaration(&self, _self_id: usize) -> String {
49 | format!("")
50 | }
51 |
52 | fn build_functions(&self, _self_id: usize) -> String {
53 | format!("")
54 | }
55 |
56 | fn build_fragment_shader(
57 | &self,
58 | pool: &ResourcePool>,
59 | visited: &mut HashMap,
60 | self_id: usize,
61 | ) -> String {
62 | if visited.contains_key(&self_id) {
63 | return "".to_string();
64 | }
65 | visited.insert(self_id, true);
66 |
67 | let node = pool.borrow(&self.node).unwrap();
68 |
69 | node.build_fragment_shader(pool, visited, self.node.id) +
70 | &format!("let {} = {}.xyz;\n",
71 | self.get_fragment_output(self_id),
72 | node.get_fragment_output(self.node.id),
73 | )
74 | }
75 |
76 | fn get_fragment_output(&self, self_id: usize) -> String {
77 | format!("xyz_output_{}", self_id)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/math/quaternion.rs:
--------------------------------------------------------------------------------
1 | const ELEMENT_NUM: usize = 4;
2 | type Elements = [f32; ELEMENT_NUM];
3 |
4 | pub struct Quaternion {
5 | }
6 |
7 | impl Quaternion {
8 | pub fn create() -> Elements {
9 | [0.0, 0.0, 0.0, 1.0]
10 | }
11 |
12 | pub fn set_from_euler<'a>(q: &'a mut Elements, e: &'a [f32; 3]) -> &'a mut Elements {
13 | // Assume XYZ order
14 | let x = e[0];
15 | let y = e[1];
16 | let z = e[2];
17 |
18 | let c1 = (x / 2.0).cos();
19 | let c2 = (y / 2.0).cos();
20 | let c3 = (z / 2.0).cos();
21 |
22 | let s1 = (x / 2.0).sin();
23 | let s2 = (y / 2.0).sin();
24 | let s3 = (z / 2.0).sin();
25 |
26 | q[0] = s1 * c2 * c3 + c1 * s2 * s3;
27 | q[1] = c1 * s2 * c3 - s1 * c2 * s3;
28 | q[2] = c1 * c2 * s3 + s1 * s2 * c3;
29 | q[3] = c1 * c2 * c3 - s1 * s2 * s3;
30 |
31 | q
32 | }
33 |
34 | pub fn set_from_rotation_matrix<'a>(
35 | q: &'a mut Elements,
36 | m: &'a [f32; 16],
37 | ) -> &'a mut Elements {
38 | let m11 = m[0];
39 | let m12 = m[4];
40 | let m13 = m[8];
41 | let m21 = m[1];
42 | let m22 = m[5];
43 | let m23 = m[9];
44 | let m31 = m[2];
45 | let m32 = m[6];
46 | let m33 = m[10];
47 |
48 | let trace = m11 + m22 + m33;
49 |
50 | if trace > 0.0 {
51 | let s = 0.5 / (trace + 1.0).sqrt();
52 | q[0] = (m32 - m23) * s;
53 | q[1] = (m13 - m31) * s;
54 | q[2] = (m21 - m12) * s;
55 | q[3] = 0.25 / s;
56 | } else if m11 > m22 && m11 > m33 {
57 | let s = 2.0 * (1.0 + m11 - m22 - m33).sqrt();
58 | q[0] = 0.25 * s;
59 | q[1] = (m12 + m21) / s;
60 | q[2] = (m13 + m31) / s;
61 | q[3] = (m32 - m23) / s;
62 | } else if m22 > m33 {
63 | let s = 2.0 * (1.0 + m22 - m11 - m33).sqrt();
64 | q[0] = (m12 + m21) / s;
65 | q[1] = 0.25 * s;
66 | q[2] = (m23 + m32) / s;
67 | q[3] = (m13 - m31) / s;
68 | } else {
69 | let s = 2.0 * (1.0 + m33 - m11 - m22).sqrt();
70 | q[0] = (m13 + m31) / s;
71 | q[1] = (m23 + m32) / s;
72 | q[2] = 0.25 * s;
73 | q[3] = (m21 - m12) / s;
74 | }
75 |
76 | q
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/material/node/linear_to_srgb.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct LinearToSRGBNode {
14 | node: ResourceId>,
15 | }
16 |
17 | impl LinearToSRGBNode {
18 | pub fn new(
19 | node: ResourceId>,
20 | ) -> Self {
21 | LinearToSRGBNode {
22 | node: node,
23 | }
24 | }
25 | }
26 |
27 | impl MaterialNode for LinearToSRGBNode {
28 | fn collect_nodes (
29 | &self,
30 | pool: &ResourcePool>,
31 | nodes: &mut Vec>>,
32 | visited: &mut HashMap>, bool>,
33 | self_rid: ResourceId>,
34 | ) {
35 | pool.borrow(&self.node).unwrap().collect_nodes(
36 | pool, nodes, visited, self.node,
37 | );
38 | if !visited.contains_key(&self_rid) {
39 | visited.insert(self_rid, true);
40 | nodes.push(self_rid);
41 | }
42 | }
43 |
44 | fn borrow_contents(&self) -> Option<&UniformContents> {
45 | None
46 | }
47 |
48 | fn build_declaration(&self, _self_id: usize) -> String {
49 | format!("")
50 | }
51 |
52 | fn build_functions(&self, _self_id: usize) -> String {
53 | format!("")
54 | }
55 |
56 | fn build_fragment_shader(
57 | &self,
58 | pool: &ResourcePool>,
59 | visited: &mut HashMap,
60 | self_id: usize,
61 | ) -> String {
62 | if visited.contains_key(&self_id) {
63 | return "".to_string();
64 | }
65 | visited.insert(self_id, true);
66 |
67 | let node = pool.borrow(&self.node).unwrap();
68 |
69 | node.build_fragment_shader(pool, visited, self.node.id) +
70 | &format!("let {} = linear_to_srgb({});\n",
71 | self.get_fragment_output(self_id),
72 | node.get_fragment_output(self.node.id),
73 | )
74 | }
75 |
76 | fn get_fragment_output(&self, self_id: usize) -> String {
77 | format!("linear_to_srgb_output_{}", self_id)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/material/node/srgb_to_linear.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct SRGBToLinearNode {
14 | node: ResourceId>,
15 | }
16 |
17 | impl SRGBToLinearNode {
18 | pub fn new(
19 | node: ResourceId>,
20 | ) -> Self {
21 | SRGBToLinearNode {
22 | node: node,
23 | }
24 | }
25 | }
26 |
27 | impl MaterialNode for SRGBToLinearNode {
28 | fn collect_nodes (
29 | &self,
30 | pool: &ResourcePool>,
31 | nodes: &mut Vec>>,
32 | visited: &mut HashMap>, bool>,
33 | self_rid: ResourceId>,
34 | ) {
35 | pool.borrow(&self.node).unwrap().collect_nodes(
36 | pool, nodes, visited, self.node,
37 | );
38 | if !visited.contains_key(&self_rid) {
39 | visited.insert(self_rid, true);
40 | nodes.push(self_rid);
41 | }
42 | }
43 |
44 | fn borrow_contents(&self) -> Option<&UniformContents> {
45 | None
46 | }
47 |
48 | fn build_declaration(&self, _self_id: usize) -> String {
49 | format!("")
50 | }
51 |
52 | fn build_functions(&self, _self_id: usize) -> String {
53 | format!("")
54 | }
55 |
56 | fn build_fragment_shader(
57 | &self,
58 | pool: &ResourcePool>,
59 | visited: &mut HashMap,
60 | self_id: usize,
61 | ) -> String {
62 | if visited.contains_key(&self_id) {
63 | return "".to_string();
64 | }
65 | visited.insert(self_id, true);
66 |
67 | let node = pool.borrow(&self.node).unwrap();
68 |
69 | node.build_fragment_shader(pool, visited, self.node.id) +
70 | &format!("let {} = srgb_to_linear({});\n",
71 | self.get_fragment_output(self_id),
72 | node.get_fragment_output(self.node.id),
73 | )
74 | }
75 |
76 | fn get_fragment_output(&self, self_id: usize) -> String {
77 | format!("srgb_to_linear_output_{}", self_id)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/utils/file_loader.rs:
--------------------------------------------------------------------------------
1 | pub struct FileLoader {
2 | }
3 |
4 | // Non-Wasm
5 |
6 | #[cfg(not(target_arch = "wasm32"))]
7 | use std::fs::File;
8 |
9 | #[cfg(not(target_arch = "wasm32"))]
10 | impl FileLoader {
11 | pub async fn open(file_path: &str) -> File {
12 | File::open(file_path).unwrap()
13 | }
14 | }
15 |
16 | // Wasm
17 |
18 | #[cfg(target_arch = "wasm32")]
19 | use {
20 | std::io::Cursor,
21 | wasm_bindgen::JsCast,
22 | wasm_bindgen_futures::JsFuture,
23 | web_sys::{
24 | Request,
25 | RequestInit,
26 | RequestMode,
27 | Response,
28 | },
29 | };
30 |
31 | // @TODO: Proper error handling
32 | #[cfg(target_arch = "wasm32")]
33 | impl FileLoader {
34 | pub async fn open(file_path: &str) -> Cursor> {
35 | let result = fetch_as_binary(file_path).await.unwrap();
36 | Cursor::new(result)
37 | }
38 | }
39 |
40 | // @TODO: Proper error handling
41 | #[cfg(target_arch = "wasm32")]
42 | pub async fn fetch_as_binary(url: &str) -> Result, String> {
43 | let mut opts = RequestInit::new();
44 | opts.method("GET");
45 | opts.mode(RequestMode::Cors); // @TODO: Should be able to opt-out
46 |
47 | let request = match Request::new_with_str_and_init(&url, &opts) {
48 | Ok(request) => request,
49 | Err(_e) => return Err("Failed to create request".to_string()),
50 | };
51 |
52 | let window = web_sys::window().unwrap();
53 | let response = match JsFuture::from(window.fetch_with_request(&request)).await {
54 | Ok(response) => response,
55 | Err(_e) => return Err("Failed to fetch".to_string()),
56 | };
57 |
58 | let response: Response = match response.dyn_into() {
59 | Ok(response) => response,
60 | Err(_e) => return Err("Failed to dyn_into Response".to_string()),
61 | };
62 |
63 | let buffer = match response.array_buffer() {
64 | Ok(buffer) => buffer,
65 | Err(_e) => return Err("Failed to get as array buffer".to_string()),
66 | };
67 |
68 | let buffer = match JsFuture::from(buffer).await {
69 | Ok(buffer) => buffer,
70 | Err(_e) => return Err("Failed to ...?".to_string()),
71 | };
72 |
73 | Ok(js_sys::Uint8Array::new(&buffer).to_vec())
74 | }
75 |
--------------------------------------------------------------------------------
/src/web/wgpu_web_renderer.rs:
--------------------------------------------------------------------------------
1 | use std::ops::{Deref, DerefMut};
2 | use winit::window::Window;
3 | use crate::renderer::wgpu_renderer::{
4 | WGPURenderer,
5 | WGPURendererOptions,
6 | };
7 |
8 | pub struct WGPUWebRenderer {
9 | canvas: web_sys::HtmlCanvasElement,
10 | renderer: WGPURenderer,
11 | }
12 |
13 | // Using Deref/DerefMut for inheritance may be a bad design
14 |
15 | impl Deref for WGPUWebRenderer {
16 | type Target = WGPURenderer;
17 | fn deref(&self) -> &WGPURenderer {
18 | &self.renderer
19 | }
20 | }
21 |
22 | impl DerefMut for WGPUWebRenderer {
23 | fn deref_mut(&mut self) -> &mut WGPURenderer {
24 | &mut self.renderer
25 | }
26 | }
27 |
28 | impl WGPUWebRenderer {
29 | pub async fn new(
30 | window: &Window,
31 | canvas: web_sys::HtmlCanvasElement,
32 | options: WGPURendererOptions,
33 | ) -> WGPUWebRenderer {
34 | WGPUWebRenderer {
35 | canvas: canvas,
36 | renderer: WGPURenderer::new(window, options).await,
37 | }
38 | }
39 |
40 | pub fn borrow_canvas(&self) -> &web_sys::HtmlCanvasElement {
41 | &self.canvas
42 | }
43 |
44 | pub fn set_size(
45 | &mut self,
46 | width: f64,
47 | height: f64,
48 | ) {
49 | WGPURenderer::set_size(&mut self.renderer, width, height);
50 | update_canvas_size(
51 | &self.canvas,
52 | self.renderer.get_size(),
53 | self.renderer.get_pixel_ratio(),
54 | );
55 | }
56 |
57 | pub fn set_pixel_ratio(
58 | &mut self,
59 | _pixel_ratio: f64,
60 | ) {
61 | // I don't know thy but pixel_ratio parameter needs to be 1.0 for Web.
62 | // Otherwise, crashes with
63 | // Attachment size mismatch
64 | // - While encoding BeginRenderPass([RenderPassDescriptor]).
65 | // error.
66 | // @TODO: Fix the root issue
67 | let pixel_ratio = 1.0;
68 |
69 | WGPURenderer::set_pixel_ratio(&mut self.renderer, pixel_ratio);
70 | update_canvas_size(
71 | &self.canvas,
72 | self.renderer.get_size(),
73 | self.renderer.get_pixel_ratio(),
74 | );
75 | }
76 | }
77 |
78 | fn update_canvas_size(
79 | canvas: &web_sys::HtmlCanvasElement,
80 | (width, height): (f64, f64),
81 | pixel_ratio: f64
82 | ) {
83 | canvas.set_width((width * pixel_ratio) as u32);
84 | canvas.set_height((height * pixel_ratio) as u32);
85 | canvas.style().set_property("width", &((width as u32).to_string() + "px")).unwrap();
86 | canvas.style().set_property("height", &((height as u32).to_string() + "px")).unwrap();
87 | }
88 |
--------------------------------------------------------------------------------
/src/material/node/add.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct AddNode {
14 | value1: ResourceId>,
15 | value2: ResourceId>,
16 | }
17 |
18 | impl AddNode {
19 | pub fn new(
20 | value1: ResourceId>,
21 | value2: ResourceId>,
22 | ) -> Self {
23 | AddNode {
24 | value1: value1,
25 | value2: value2,
26 | }
27 | }
28 | }
29 |
30 | impl MaterialNode for AddNode {
31 | fn collect_nodes (
32 | &self,
33 | pool: &ResourcePool>,
34 | nodes: &mut Vec>>,
35 | visited: &mut HashMap>, bool>,
36 | self_rid: ResourceId>,
37 | ) {
38 | pool.borrow(&self.value1).unwrap().collect_nodes(
39 | pool, nodes, visited, self.value1,
40 | );
41 | pool.borrow(&self.value2).unwrap().collect_nodes(
42 | pool, nodes, visited, self.value2,
43 | );
44 | if !visited.contains_key(&self_rid) {
45 | visited.insert(self_rid, true);
46 | nodes.push(self_rid);
47 | }
48 | }
49 |
50 | fn borrow_contents(&self) -> Option<&UniformContents> {
51 | None
52 | }
53 |
54 | fn build_declaration(&self, _self_id: usize) -> String {
55 | format!("")
56 | }
57 |
58 | fn build_functions(&self, _self_id: usize) -> String {
59 | format!("")
60 | }
61 |
62 | fn build_fragment_shader(
63 | &self,
64 | pool: &ResourcePool>,
65 | visited: &mut HashMap,
66 | self_id: usize,
67 | ) -> String {
68 | if visited.contains_key(&self_id) {
69 | return "".to_string();
70 | }
71 | visited.insert(self_id, true);
72 |
73 | let value1 = pool.borrow(&self.value1).unwrap();
74 | let value2 = pool.borrow(&self.value2).unwrap();
75 |
76 | value1.build_fragment_shader(pool, visited, self.value1.id) +
77 | &value2.build_fragment_shader(pool, visited, self.value2.id) +
78 | &format!("let {} = {} + {};\n",
79 | self.get_fragment_output(self_id),
80 | value1.get_fragment_output(self.value1.id),
81 | value2.get_fragment_output(self.value2.id),
82 | )
83 | }
84 |
85 | fn get_fragment_output(&self, self_id: usize) -> String {
86 | format!("add_output_{}", self_id)
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/material/node/sub.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct SubNode {
14 | value1: ResourceId>,
15 | value2: ResourceId>,
16 | }
17 |
18 | impl SubNode {
19 | pub fn new(
20 | value1: ResourceId>,
21 | value2: ResourceId>,
22 | ) -> Self {
23 | SubNode {
24 | value1: value1,
25 | value2: value2,
26 | }
27 | }
28 | }
29 |
30 | impl MaterialNode for SubNode {
31 | fn collect_nodes (
32 | &self,
33 | pool: &ResourcePool>,
34 | nodes: &mut Vec>>,
35 | visited: &mut HashMap>, bool>,
36 | self_rid: ResourceId>,
37 | ) {
38 | pool.borrow(&self.value1).unwrap().collect_nodes(
39 | pool, nodes, visited, self.value1,
40 | );
41 | pool.borrow(&self.value2).unwrap().collect_nodes(
42 | pool, nodes, visited, self.value2,
43 | );
44 | if !visited.contains_key(&self_rid) {
45 | visited.insert(self_rid, true);
46 | nodes.push(self_rid);
47 | }
48 | }
49 |
50 | fn borrow_contents(&self) -> Option<&UniformContents> {
51 | None
52 | }
53 |
54 | fn build_declaration(&self, _self_id: usize) -> String {
55 | format!("")
56 | }
57 |
58 | fn build_functions(&self, _self_id: usize) -> String {
59 | format!("")
60 | }
61 |
62 | fn build_fragment_shader(
63 | &self,
64 | pool: &ResourcePool>,
65 | visited: &mut HashMap,
66 | self_id: usize,
67 | ) -> String {
68 | if visited.contains_key(&self_id) {
69 | return "".to_string();
70 | }
71 | visited.insert(self_id, true);
72 |
73 | let value1 = pool.borrow(&self.value1).unwrap();
74 | let value2 = pool.borrow(&self.value2).unwrap();
75 |
76 | value1.build_fragment_shader(pool, visited, self.value1.id) +
77 | &value2.build_fragment_shader(pool, visited, self.value2.id) +
78 | &format!("let {} = {} - {};\n",
79 | self.get_fragment_output(self_id),
80 | value1.get_fragment_output(self.value1.id),
81 | value2.get_fragment_output(self.value2.id),
82 | )
83 | }
84 |
85 | fn get_fragment_output(&self, self_id: usize) -> String {
86 | format!("sub_output_{}", self_id)
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/math/matrix3.rs:
--------------------------------------------------------------------------------
1 | const ELEMENT_NUM: usize = 9;
2 | type Elements = [f32; ELEMENT_NUM];
3 |
4 | pub struct Matrix3 {
5 | }
6 |
7 | impl Matrix3 {
8 | pub fn create() -> Elements {
9 | let mut elements = [0.0; ELEMENT_NUM];
10 | Self::identity(&mut elements);
11 | elements
12 | }
13 |
14 | pub fn identity(m: &mut Elements) -> &mut Elements {
15 | m[0] = 1.0;
16 | m[1] = 0.0;
17 | m[2] = 0.0;
18 | m[3] = 0.0;
19 | m[4] = 1.0;
20 | m[5] = 0.0;
21 | m[6] = 0.0;
22 | m[7] = 0.0;
23 | m[8] = 1.0;
24 | m
25 | }
26 |
27 | pub fn copy<'a>(m: &'a mut Elements, src: &'a Elements) -> &'a mut Elements {
28 | for i in 0..ELEMENT_NUM {
29 | m[i] = src[i];
30 | }
31 | m
32 | }
33 |
34 | pub fn make_normal_from_matrix4<'a>(
35 | m: &'a mut Elements,
36 | src: &'a [f32; 16],
37 | ) -> &'a mut Elements {
38 | let a00 = src[0];
39 | let a01 = src[1];
40 | let a02 = src[2];
41 | let a03 = src[3];
42 | let a10 = src[4];
43 | let a11 = src[5];
44 | let a12 = src[6];
45 | let a13 = src[7];
46 | let a20 = src[8];
47 | let a21 = src[9];
48 | let a22 = src[10];
49 | let a23 = src[11];
50 | let a30 = src[12];
51 | let a31 = src[13];
52 | let a32 = src[14];
53 | let a33 = src[15];
54 |
55 | let b00 = a00 * a11 - a01 * a10;
56 | let b01 = a00 * a12 - a02 * a10;
57 | let b02 = a00 * a13 - a03 * a10;
58 | let b03 = a01 * a12 - a02 * a11;
59 | let b04 = a01 * a13 - a03 * a11;
60 | let b05 = a02 * a13 - a03 * a12;
61 | let b06 = a20 * a31 - a21 * a30;
62 | let b07 = a20 * a32 - a22 * a30;
63 | let b08 = a20 * a33 - a23 * a30;
64 | let b09 = a21 * a32 - a22 * a31;
65 | let b10 = a21 * a33 - a23 * a31;
66 | let b11 = a22 * a33 - a23 * a32;
67 |
68 | let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
69 |
70 | if det == 0.0 {
71 | // @TODO: Error handling?
72 | return m;
73 | }
74 |
75 | let det = 1.0 / det;
76 | m[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
77 | m[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
78 | m[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
79 | m[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
80 | m[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
81 | m[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
82 | m[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
83 | m[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
84 | m[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
85 |
86 | m
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/material/node/multiply.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | pub struct MultiplyNode {
14 | value1: ResourceId>,
15 | value2: ResourceId>,
16 | }
17 |
18 | impl MultiplyNode {
19 | pub fn new(
20 | value1: ResourceId>,
21 | value2: ResourceId>,
22 | ) -> Self {
23 | MultiplyNode {
24 | value1: value1,
25 | value2: value2,
26 | }
27 | }
28 | }
29 |
30 | impl MaterialNode for MultiplyNode {
31 | fn collect_nodes (
32 | &self,
33 | pool: &ResourcePool>,
34 | nodes: &mut Vec>>,
35 | visited: &mut HashMap>, bool>,
36 | self_rid: ResourceId>,
37 | ) {
38 | pool.borrow(&self.value1).unwrap().collect_nodes(
39 | pool, nodes, visited, self.value1,
40 | );
41 | pool.borrow(&self.value2).unwrap().collect_nodes(
42 | pool, nodes, visited, self.value2,
43 | );
44 | if !visited.contains_key(&self_rid) {
45 | visited.insert(self_rid, true);
46 | nodes.push(self_rid);
47 | }
48 | }
49 |
50 | fn borrow_contents(&self) -> Option<&UniformContents> {
51 | None
52 | }
53 |
54 | fn build_declaration(&self, _self_id: usize) -> String {
55 | format!("")
56 | }
57 |
58 | fn build_functions(&self, _self_id: usize) -> String {
59 | format!("")
60 | }
61 |
62 | fn build_fragment_shader(
63 | &self,
64 | pool: &ResourcePool>,
65 | visited: &mut HashMap,
66 | self_id: usize,
67 | ) -> String {
68 | if visited.contains_key(&self_id) {
69 | return "".to_string();
70 | }
71 | visited.insert(self_id, true);
72 |
73 | let value1 = pool.borrow(&self.value1).unwrap();
74 | let value2 = pool.borrow(&self.value2).unwrap();
75 |
76 | value1.build_fragment_shader(pool, visited, self.value1.id) +
77 | &value2.build_fragment_shader(pool, visited, self.value2.id) +
78 | &format!("let {} = {} * {};\n",
79 | self.get_fragment_output(self_id),
80 | value1.get_fragment_output(self.value1.id),
81 | value2.get_fragment_output(self.value2.id),
82 | )
83 | }
84 |
85 | fn get_fragment_output(&self, self_id: usize) -> String {
86 | format!("multiply_output_{}", self_id)
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/material/node/texture.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | texture::{
12 | sampler::Sampler,
13 | texture::Texture,
14 | }
15 | };
16 |
17 | pub struct TextureNode {
18 | contents: UniformContents,
19 | }
20 |
21 | impl TextureNode {
22 | pub fn new(
23 | texture: ResourceId,
24 | sampler: ResourceId,
25 | ) -> Self {
26 | TextureNode {
27 | contents: UniformContents::Texture {
28 | sampler: sampler,
29 | texture: texture,
30 | },
31 | }
32 | }
33 |
34 | fn get_texture_name(&self) -> String {
35 | match self.contents {
36 | UniformContents::Texture{texture, ..} => {
37 | format!("texture_{}", texture.id)
38 | },
39 | _ => panic!(),
40 | }
41 | }
42 |
43 | fn get_sampler_name(&self) -> String {
44 | match self.contents {
45 | UniformContents::Texture{sampler, ..} => {
46 | format!("sampler_{}", sampler.id)
47 | },
48 | _ => panic!(),
49 | }
50 | }
51 | }
52 |
53 | impl MaterialNode for TextureNode {
54 | fn collect_nodes (
55 | &self,
56 | _pool: &ResourcePool>,
57 | nodes: &mut Vec>>,
58 | visited: &mut HashMap>, bool>,
59 | self_rid: ResourceId>,
60 | ) {
61 | if !visited.contains_key(&self_rid) {
62 | visited.insert(self_rid, true);
63 | nodes.push(self_rid);
64 | }
65 | }
66 |
67 | fn borrow_contents(&self) -> Option<&UniformContents> {
68 | Some(&self.contents)
69 | }
70 |
71 | fn build_declaration(&self, _self_id: usize) -> String {
72 | format!("")
73 | }
74 |
75 | fn build_functions(&self, _self_id: usize) -> String {
76 | format!("")
77 | }
78 |
79 | fn build_fragment_shader(
80 | &self,
81 | _pool: &ResourcePool>,
82 | visited: &mut HashMap,
83 | self_id: usize,
84 | ) -> String {
85 | if visited.contains_key(&self_id) {
86 | return "".to_string();
87 | }
88 | visited.insert(self_id, true);
89 |
90 | format!("let {} = textureSample({}, {}, in.uv);\n",
91 | self.get_fragment_output(self_id),
92 | self.get_texture_name(),
93 | self.get_sampler_name(),
94 | )
95 | }
96 |
97 | fn get_fragment_output(&self, self_id: usize) -> String {
98 | format!("texture_output_{}", self_id)
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/renderer/wgpu_samplers.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::{
4 | material::Material,
5 | node::node::MaterialNode,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePools,
10 | },
11 | texture::sampler::{
12 | FilterMode,
13 | Sampler,
14 | WrapMode,
15 | },
16 | };
17 |
18 | pub struct WGPUSamplers {
19 | samplers: HashMap, wgpu::Sampler>,
20 | }
21 |
22 | impl WGPUSamplers {
23 | pub fn new() -> Self {
24 | WGPUSamplers {
25 | samplers: HashMap::new(),
26 | }
27 | }
28 |
29 | pub fn borrow(&self, sampler: &ResourceId) -> Option<&wgpu::Sampler> {
30 | self.samplers.get(sampler)
31 | }
32 |
33 | // @TODO: Implement correctly
34 | fn update(
35 | &mut self,
36 | device: &wgpu::Device,
37 | pools: &ResourcePools,
38 | sampler_rid: &ResourceId,
39 | ) {
40 | if !self.samplers.contains_key(sampler_rid) {
41 | if let Some(sampler) = pools.borrow::().borrow(sampler_rid) {
42 | let sampler_gpu = create_sampler(
43 | device,
44 | sampler,
45 | );
46 | self.samplers.insert(*sampler_rid, sampler_gpu);
47 | }
48 | }
49 | }
50 |
51 | pub fn update_from_material(
52 | &mut self,
53 | device: &wgpu::Device,
54 | pools: &ResourcePools,
55 | material: &Material,
56 | ) {
57 | let samplers = material.borrow_samplers(
58 | pools.borrow::>(),
59 | );
60 | for sampler in samplers.iter() {
61 | self.update(device, pools, sampler);
62 | }
63 | }
64 | }
65 |
66 | fn create_sampler(
67 | device: &wgpu::Device,
68 | sampler: &Sampler,
69 | ) -> wgpu::Sampler {
70 | // @TODO: Fix me
71 | device.create_sampler(&wgpu::SamplerDescriptor {
72 | address_mode_u: get_address_mode(sampler.wrap_u()),
73 | address_mode_v: get_address_mode(sampler.wrap_v()),
74 | address_mode_w: get_address_mode(sampler.wrap_w()),
75 | anisotropy_clamp: None,
76 | border_color: None,
77 | compare: None,
78 | mag_filter: get_filter_mode(sampler.mag_filter()),
79 | min_filter: get_filter_mode(sampler.min_filter()),
80 | mipmap_filter: get_filter_mode(sampler.mipmap_filter()),
81 | label: None,
82 | lod_max_clamp: 0.0,
83 | lod_min_clamp: 0.0,
84 | })
85 | }
86 |
87 | fn get_address_mode(mode: &WrapMode) -> wgpu::AddressMode {
88 | match mode {
89 | WrapMode::ClampToBorder => wgpu::AddressMode::ClampToBorder,
90 | WrapMode::ClampToEdge => wgpu::AddressMode::ClampToEdge,
91 | WrapMode::MirrorRepeat => wgpu::AddressMode::MirrorRepeat,
92 | WrapMode::Repeat => wgpu::AddressMode::Repeat,
93 | }
94 | }
95 |
96 | fn get_filter_mode(mode: &FilterMode) -> wgpu::FilterMode {
97 | match mode {
98 | FilterMode::Nearest => wgpu::FilterMode::Nearest,
99 | FilterMode::Linear => wgpu::FilterMode::Linear,
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/material/node/tangent_to_object_normal.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::node::node::{
4 | MaterialNode,
5 | UniformContents,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePool,
10 | },
11 | };
12 |
13 | const FUNCTION_CHUNK: &str = "
14 | fn perturb_normal_to_arb(
15 | eye_pos: vec3,
16 | surf_norm: vec3,
17 | map_n: vec3,
18 | uv: vec2
19 | ) -> vec3 {
20 | let q0: vec3 = vec3(dpdx(eye_pos.x), dpdx(eye_pos.y), dpdx(eye_pos.z));
21 | let q1: vec3 = vec3(dpdy(eye_pos.x), dpdy(eye_pos.y), dpdy(eye_pos.z));
22 | let st0: vec2 = dpdx(uv);
23 | let st1: vec2 = dpdy(uv);
24 | let n: vec3 = surf_norm; // normalized
25 | let q1perp: vec3 = cross(q1, n);
26 | let q0perp: vec3 = cross(n, q0);
27 | let t = q1perp * st0.x + q0perp * st1.x;
28 | let b = q1perp * st0.y + q0perp * st1.y;
29 | let det: f32 = max(dot(t, t), dot(b, b));
30 | var scale: f32;
31 | if (det == 0.0) {
32 | scale = 0.0;
33 | } else {
34 | scale = inverseSqrt(det);
35 | }
36 | return normalize(t * (map_n.x * scale) + b * (map_n.y * scale) + n * map_n.z);
37 | }
38 | ";
39 |
40 | pub struct TangentToObjectNormalNode {
41 | node: ResourceId>,
42 | }
43 |
44 | impl TangentToObjectNormalNode {
45 | pub fn new(
46 | node: ResourceId>,
47 | ) -> Self {
48 | TangentToObjectNormalNode {
49 | node: node,
50 | }
51 | }
52 | }
53 |
54 | impl MaterialNode for TangentToObjectNormalNode {
55 | fn collect_nodes (
56 | &self,
57 | pool: &ResourcePool>,
58 | nodes: &mut Vec>>,
59 | visited: &mut HashMap>, bool>,
60 | self_rid: ResourceId>,
61 | ) {
62 | pool.borrow(&self.node).unwrap().collect_nodes(
63 | pool, nodes, visited, self.node,
64 | );
65 | if !visited.contains_key(&self_rid) {
66 | visited.insert(self_rid, true);
67 | nodes.push(self_rid);
68 | }
69 | }
70 |
71 | fn borrow_contents(&self) -> Option<&UniformContents> {
72 | None
73 | }
74 |
75 | fn build_declaration(&self, _self_id: usize) -> String {
76 | format!("")
77 | }
78 |
79 | fn build_functions(&self, _self_id: usize) -> String {
80 | // @TODO: Add self_id suffix for unique function name
81 | FUNCTION_CHUNK.to_string()
82 | }
83 |
84 | fn build_fragment_shader(
85 | &self,
86 | pool: &ResourcePool>,
87 | visited: &mut HashMap,
88 | self_id: usize,
89 | ) -> String {
90 | if visited.contains_key(&self_id) {
91 | return "".to_string();
92 | }
93 | visited.insert(self_id, true);
94 |
95 | let node = pool.borrow(&self.node).unwrap();
96 |
97 | node.build_fragment_shader(pool, visited, self.node.id) +
98 | &format!("let {} = perturb_normal_to_arb(-in.view_position, in.normal, {}, in.uv);\n",
99 | self.get_fragment_output(self_id),
100 | node.get_fragment_output(self.node.id),
101 | )
102 | }
103 |
104 | fn get_fragment_output(&self, self_id: usize) -> String {
105 | format!("tangent_to_object_normal_output_{}", self_id)
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/utils/material_helper.rs:
--------------------------------------------------------------------------------
1 | use crate::{
2 | material::{
3 | material::{
4 | Material,
5 | Side,
6 | },
7 | node::{
8 | brdf::{
9 | BRDFNode,
10 | BRDFNodeDescriptor,
11 | },
12 | float::FloatNode,
13 | multiply::MultiplyNode,
14 | node::MaterialNode,
15 | normal::NormalNode,
16 | texture::TextureNode,
17 | vector3::Vector3Node,
18 | xyz::XYZNode,
19 | },
20 | },
21 | math::color::Color,
22 | resource::resource::{
23 | ResourceId,
24 | ResourcePools,
25 | },
26 | texture::{
27 | sampler::{
28 | Sampler,
29 | SamplerDescriptor,
30 | },
31 | texture::Texture,
32 | },
33 | };
34 |
35 | pub struct MaterialHelper {
36 | }
37 |
38 | impl MaterialHelper {
39 | pub fn create_basic_material(
40 | pools: &mut ResourcePools,
41 | color: &[f32; 3],
42 | ) -> ResourceId {
43 | let color_node = pools.borrow_mut::>().add(
44 | Box::new(Vector3Node::new(
45 | *Color::copy(&mut Color::create(), color),
46 | )),
47 | );
48 |
49 | pools.borrow_mut::().add(Material::new(color_node, Side::default()))
50 | }
51 |
52 | pub fn create_basic_material_with_texture(
53 | pools: &mut ResourcePools,
54 | color: &[f32; 3],
55 | texture: ResourceId,
56 | ) -> ResourceId {
57 | let color = pools.borrow_mut::>().add(
58 | Box::new(Vector3Node::new(
59 | *Color::copy(&mut Color::create(), color),
60 | ),
61 | ));
62 |
63 | let sampler = pools.borrow_mut::().add(
64 | Sampler::new(SamplerDescriptor::default()),
65 | );
66 |
67 | let texture = pools.borrow_mut::>().add(
68 | Box::new(TextureNode::new(texture, sampler)),
69 | );
70 |
71 | let texture_rgb = pools.borrow_mut::>().add(
72 | Box::new(XYZNode::new(texture)),
73 | );
74 |
75 | let color_node = pools.borrow_mut::>().add(
76 | Box::new(MultiplyNode::new(color, texture_rgb)),
77 | );
78 |
79 | pools.borrow_mut::().add(Material::new(color_node, Side::default()))
80 | }
81 |
82 | pub fn create_brdf_material(
83 | pools: &mut ResourcePools,
84 | color: &[f32; 3],
85 | metallic: f32,
86 | roughness: f32,
87 | ) -> ResourceId {
88 | let base_color = pools.borrow_mut::>().add(
89 | Box::new(Vector3Node::new(
90 | *Color::copy(&mut Color::create(), color),
91 | )),
92 | );
93 |
94 | let metallic = pools.borrow_mut::>().add(
95 | Box::new(FloatNode::new(metallic)),
96 | );
97 |
98 | let roughness = pools.borrow_mut::>().add(
99 | Box::new(FloatNode::new(roughness)),
100 | );
101 |
102 | let normal = pools.borrow_mut::>().add(
103 | Box::new(NormalNode::new()),
104 | );
105 |
106 | let desc = BRDFNodeDescriptor {
107 | base_color: base_color,
108 | metallic: metallic,
109 | normal: normal,
110 | roughness: roughness,
111 | };
112 |
113 | let brdf_node = pools.borrow_mut::>().add(
114 | Box::new(BRDFNode::new(desc)),
115 | );
116 |
117 | pools.borrow_mut::().add(Material::new(brdf_node, Side::default()))
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/utils/texture_loader.rs:
--------------------------------------------------------------------------------
1 | use crate::utils::file_loader::FileLoader;
2 |
3 | use crate::{
4 | resource::resource::{
5 | ResourceId,
6 | ResourcePools,
7 | },
8 | texture::{
9 | texture::{
10 | Texture,
11 | TextureFormat,
12 | },
13 | },
14 | };
15 |
16 | pub struct TextureLoader {
17 | }
18 |
19 | impl TextureLoader {
20 | pub fn load_png(
21 | pools: &mut ResourcePools,
22 | reader: R,
23 | // @TODO: Should use default rather than Option?
24 | format: TextureFormat,
25 | ) -> ResourceId {
26 | let decoder = png::Decoder::new(reader);
27 | let mut reader = decoder.read_info().unwrap();
28 | let (width, height) = {
29 | let info = reader.info();
30 | (info.width, info.height)
31 | };
32 | let mut buf = vec![0; reader.output_buffer_size()];
33 | reader.next_frame(&mut buf).unwrap();
34 |
35 | pools.borrow_mut::().add(
36 | Texture::new(
37 | width,
38 | height,
39 | format,
40 | buf,
41 | )
42 | )
43 | }
44 |
45 | pub async fn load_png_with_filepath(
46 | pools: &mut ResourcePools,
47 | file_path: &str,
48 | format: TextureFormat,
49 | ) -> ResourceId {
50 | Self::load_png(pools, FileLoader::open(file_path).await, format)
51 | }
52 |
53 | pub fn load_jpg(
54 | pools: &mut ResourcePools,
55 | reader: R,
56 | format: TextureFormat,
57 | ) -> ResourceId {
58 | let mut decoder = jpeg_decoder::Decoder::new(reader);
59 | let pixels = decoder.decode().expect("failed to decode image");
60 | let (width, height) = {
61 | let metadata = decoder.info().unwrap();
62 | (metadata.width as u32, metadata.height as u32)
63 | };
64 |
65 | // @TODO: Fix me
66 | let mut data = Vec::new();
67 | for y in 0..height as usize {
68 | for x in 0..width as usize {
69 | data.push(pixels[(y * width as usize + x) * 3 + 0]);
70 | data.push(pixels[(y * width as usize + x) * 3 + 1]);
71 | data.push(pixels[(y * width as usize + x) * 3 + 2]);
72 | data.push(255);
73 | }
74 | }
75 |
76 | pools.borrow_mut::().add(
77 | Texture::new(
78 | width,
79 | height,
80 | format,
81 | data,
82 | )
83 | )
84 | }
85 |
86 | pub async fn load_jpg_with_filepath(
87 | pools: &mut ResourcePools,
88 | file_path: &str,
89 | format: TextureFormat,
90 | ) -> ResourceId {
91 | Self::load_jpg(pools, FileLoader::open(file_path).await, format)
92 | }
93 |
94 | pub async fn load_with_filepath(
95 | pools: &mut ResourcePools,
96 | file_path: &str,
97 | format: TextureFormat,
98 | ) -> ResourceId {
99 | let path = std::path::Path::new(file_path);
100 | // @TODO: proper error handling
101 | match path.extension() {
102 | Some(extension) => match extension.to_str() {
103 | Some(str) => match str.to_lowercase().as_str() {
104 | "png" => Self::load_png_with_filepath(pools, file_path, format).await,
105 | "jpg" | "jpeg" => Self::load_jpg_with_filepath(pools, file_path, format).await,
106 | _ => panic!("Unknown texture image format, {:?}", extension),
107 | },
108 | None => panic!("Can not detect image file format from the file path, {}", file_path),
109 | },
110 | None => panic!("Can not detect image file format from the file path, {}", file_path),
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/renderer/wgpu_textures.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use crate::{
3 | material::{
4 | material::Material,
5 | node::node::MaterialNode,
6 | },
7 | resource::resource::{
8 | ResourceId,
9 | ResourcePools,
10 | },
11 | texture::texture::{
12 | Texture,
13 | TextureFormat,
14 | },
15 | };
16 |
17 | pub struct WGPUTextures {
18 | textures: HashMap, wgpu::Texture>,
19 | }
20 |
21 | impl WGPUTextures {
22 | pub fn new() -> WGPUTextures {
23 | WGPUTextures {
24 | textures: HashMap::new(),
25 | }
26 | }
27 |
28 | pub fn borrow(&self, texture: &ResourceId) -> Option<&wgpu::Texture> {
29 | self.textures.get(texture)
30 | }
31 |
32 | // @TODO: Implement correctly
33 | fn update(
34 | &mut self,
35 | device: &wgpu::Device,
36 | queue: &wgpu::Queue,
37 | pools: &ResourcePools,
38 | texture_rid: &ResourceId,
39 | ) {
40 | if !self.textures.contains_key(texture_rid) {
41 | if let Some(texture) = pools.borrow::().borrow(texture_rid) {
42 | let texture_gpu = create_texture(
43 | device,
44 | texture.get_width(),
45 | texture.get_height(),
46 | get_wgpu_format(texture.borrow_format()),
47 | );
48 | upload_texture(
49 | queue,
50 | &texture_gpu,
51 | texture.get_width(),
52 | texture.get_height(),
53 | bytemuck::cast_slice(texture.borrow_texels()),
54 | );
55 | self.textures.insert(*texture_rid, texture_gpu);
56 | }
57 | }
58 | }
59 |
60 | pub fn update_from_material(
61 | &mut self,
62 | device: &wgpu::Device,
63 | queue: &wgpu::Queue,
64 | pools: &ResourcePools,
65 | material: &Material,
66 | ) {
67 | let textures = material.borrow_textures(
68 | pools.borrow::>(),
69 | );
70 | for texture in textures.iter() {
71 | self.update(device, queue, pools, texture);
72 | }
73 | }
74 | }
75 |
76 | fn create_texture(
77 | device: &wgpu::Device,
78 | width: u32,
79 | height: u32,
80 | format: wgpu::TextureFormat
81 | ) -> wgpu::Texture {
82 | device.create_texture(&wgpu::TextureDescriptor {
83 | label: None,
84 | size: wgpu::Extent3d {
85 | width: width,
86 | height: height,
87 | depth_or_array_layers: 1,
88 | },
89 | mip_level_count: 1,
90 | sample_count: 1,
91 | dimension: wgpu::TextureDimension::D2,
92 | format: format,
93 | usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
94 | })
95 | }
96 |
97 | fn upload_texture(
98 | queue: &wgpu::Queue,
99 | texture: &wgpu::Texture,
100 | width: u32,
101 | height: u32,
102 | texels: &[u8],
103 | ) {
104 | queue.write_texture(
105 | texture.as_image_copy(),
106 | &texels,
107 | wgpu::ImageDataLayout {
108 | offset: 0,
109 | // @TODO: Fix me
110 | bytes_per_row: Some(std::num::NonZeroU32::new(width * 4).unwrap()),
111 | rows_per_image: None,
112 | },
113 | wgpu::Extent3d {
114 | width: width,
115 | height: height,
116 | depth_or_array_layers: 1,
117 | },
118 | );
119 | }
120 |
121 | fn get_wgpu_format(format: &TextureFormat) -> wgpu::TextureFormat {
122 | match format {
123 | TextureFormat::Float => wgpu::TextureFormat::Rgba32Float,
124 | TextureFormat::Uint8 => wgpu::TextureFormat::Rgba8Unorm,
125 | TextureFormat::Uint8Srgb => wgpu::TextureFormat::Rgba8UnormSrgb,
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/examples/triangle/main.rs:
--------------------------------------------------------------------------------
1 | use winit::{
2 | event::{Event, WindowEvent},
3 | event_loop::{ControlFlow, EventLoop},
4 | window::Window,
5 | };
6 | use wgpu_rust_renderer::{
7 | math::color::Color,
8 | renderer::wgpu_renderer::{
9 | WGPURenderer,
10 | WGPURendererOptions,
11 | },
12 | resource::resource::{
13 | ResourceId,
14 | ResourcePools,
15 | },
16 | scene::{
17 | camera::PerspectiveCamera,
18 | mesh::Mesh,
19 | node::Node,
20 | scene::Scene,
21 | },
22 | utils::{
23 | geometry_helper::GeometryHelper,
24 | material_helper::MaterialHelper,
25 | }
26 | };
27 |
28 | fn create_scene(
29 | window: &Window,
30 | pools: &mut ResourcePools
31 | ) -> (ResourceId, ResourceId) {
32 | let mut scene = Scene::new();
33 |
34 | let geometry = GeometryHelper::create_triangle(
35 | pools,
36 | 1.0,
37 | 1.0,
38 | );
39 |
40 | let material = MaterialHelper::create_basic_material(
41 | pools,
42 | Color::set(&mut Color::create(), 1.0, 0.0, 0.0),
43 | );
44 |
45 | let mesh = pools.borrow_mut::().add(Mesh::new(geometry, material));
46 | let node = pools.borrow_mut::().add(Node::new());
47 | scene.add_node(&node);
48 | scene.assign(&node, &mesh);
49 |
50 | let window_size = window.inner_size();
51 | let camera = pools.borrow_mut::().add(
52 | PerspectiveCamera::new(
53 | 60.0_f32.to_radians(),
54 | window_size.width as f32 / window_size.height as f32,
55 | 0.1,
56 | 1000.0,
57 | ),
58 | );
59 |
60 | let mut node = Node::new();
61 | node.borrow_position_mut()[2] = 1.0;
62 |
63 | let node = pools.borrow_mut::().add(node);
64 | scene.add_node(&node);
65 | scene.assign(&node, &camera);
66 |
67 | (pools.borrow_mut::().add(scene), camera)
68 | }
69 |
70 | fn resize(
71 | renderer: &mut WGPURenderer,
72 | pools: &mut ResourcePools,
73 | camera: &ResourceId,
74 | width: u32,
75 | height: u32,
76 | ) {
77 | pools
78 | .borrow_mut::()
79 | .borrow_mut(camera)
80 | .unwrap()
81 | .set_aspect(width as f32 / height as f32);
82 | renderer.set_size(width as f64, height as f64);
83 | }
84 |
85 | fn update(
86 | pools: &mut ResourcePools,
87 | scene: &ResourceId,
88 | ) {
89 | pools.borrow::()
90 | .borrow(scene)
91 | .unwrap()
92 | .update_matrices(pools);
93 | }
94 |
95 | fn render(
96 | renderer: &mut WGPURenderer,
97 | pools: &ResourcePools,
98 | scene: &ResourceId,
99 | camera: &ResourceId,
100 | ) {
101 | renderer.render(pools, scene, camera);
102 | }
103 |
104 | #[tokio::main]
105 | async fn main() {
106 | let event_loop = EventLoop::new();
107 | let window = Window::new(&event_loop).unwrap();
108 |
109 | let window_size = window.inner_size();
110 | let pixel_ratio = window.scale_factor();
111 |
112 | let mut renderer = WGPURenderer::new(&window, WGPURendererOptions::default()).await;
113 | renderer.set_size(window_size.width as f64, window_size.height as f64);
114 | renderer.set_pixel_ratio(pixel_ratio);
115 |
116 | let mut pools = ResourcePools::new();
117 | let (scene, camera) = create_scene(&window, &mut pools);
118 |
119 | event_loop.run(move |event, _, control_flow| {
120 | *control_flow = ControlFlow::Wait;
121 | match event {
122 | Event::WindowEvent {
123 | event: WindowEvent::Resized(size),
124 | ..
125 | } => {
126 | resize(&mut renderer, &mut pools, &camera, size.width, size.height);
127 | update(&mut pools, &scene);
128 | render(&mut renderer, &mut pools, &scene, &camera);
129 | },
130 | Event::RedrawRequested(_) => {
131 | update(&mut pools, &scene);
132 | render(&mut renderer, &mut pools, &scene, &camera);
133 | },
134 | Event::WindowEvent {
135 | event: WindowEvent::CloseRequested,
136 | ..
137 | } => {
138 | *control_flow = ControlFlow::Exit;
139 | },
140 | _ => {}
141 | }
142 | });
143 | }
144 |
--------------------------------------------------------------------------------
/web/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | wgpu-rust-renderer web examples
8 |
9 |
10 |
11 |
12 |
22 |
23 |
24 |
25 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/examples/rotation/main.rs:
--------------------------------------------------------------------------------
1 | use winit::{
2 | event::{Event, WindowEvent},
3 | event_loop::{ControlFlow, EventLoop},
4 | window::Window,
5 | };
6 | use wgpu_rust_renderer::{
7 | math::color::Color,
8 | renderer::wgpu_renderer::{
9 | WGPURenderer,
10 | WGPURendererOptions,
11 | },
12 | resource::resource::{
13 | ResourceId,
14 | ResourcePools,
15 | },
16 | scene::{
17 | camera::PerspectiveCamera,
18 | mesh::Mesh,
19 | node::Node,
20 | scene::Scene,
21 | },
22 | utils::{
23 | geometry_helper::GeometryHelper,
24 | material_helper::MaterialHelper,
25 | },
26 | };
27 |
28 | fn create_scene(
29 | window: &Window,
30 | pools: &mut ResourcePools
31 | ) -> (ResourceId, ResourceId, Vec>) {
32 | let mut objects = Vec::new();
33 | let mut scene = Scene::new();
34 |
35 | let geometry = GeometryHelper::create_plane(
36 | pools,
37 | 1.0,
38 | 1.0,
39 | );
40 |
41 | let material = MaterialHelper::create_basic_material(
42 | pools,
43 | Color::set(&mut Color::create(), 0.0, 1.0, 0.0),
44 | );
45 |
46 | let mesh = pools.borrow_mut::().add(Mesh::new(geometry, material));
47 | let node = pools.borrow_mut::().add(Node::new());
48 | scene.add_node(&node);
49 | scene.assign(&node, &mesh);
50 | objects.push(node);
51 |
52 | let window_size = window.inner_size();
53 | let camera = pools.borrow_mut::().add(
54 | PerspectiveCamera::new(
55 | 60.0_f32.to_radians(),
56 | window_size.width as f32 / window_size.height as f32,
57 | 0.1,
58 | 1000.0,
59 | ),
60 | );
61 |
62 | let mut node = Node::new();
63 | node.borrow_position_mut()[2] = 2.0;
64 |
65 | let node = pools.borrow_mut::().add(node);
66 | scene.add_node(&node);
67 | scene.assign(&node, &camera);
68 |
69 | (pools.borrow_mut::().add(scene), camera, objects)
70 | }
71 |
72 | fn resize(
73 | renderer: &mut WGPURenderer,
74 | pools: &mut ResourcePools,
75 | camera: &ResourceId,
76 | width: u32,
77 | height: u32,
78 | ) {
79 | pools
80 | .borrow_mut::()
81 | .borrow_mut(camera)
82 | .unwrap()
83 | .set_aspect(width as f32 / height as f32);
84 | renderer.set_size(width as f64, height as f64);
85 | }
86 |
87 | fn update(
88 | pools: &mut ResourcePools,
89 | scene: &ResourceId