GithubHelp home page GithubHelp logo

sotrh / learn-wgpu Goto Github PK

View Code? Open in Web Editor NEW
1.4K 21.0 243.0 253.57 MB

Guide for using gfx-rs's wgpu library.

Home Page: https://sotrh.github.io/learn-wgpu/

License: MIT License

Rust 88.98% Shell 0.08% GLSL 3.08% HTML 0.49% Python 0.04% WGSL 7.33%

learn-wgpu's Introduction

Introduction

What is wgpu?

Wgpu is a Rust implementation of the WebGPU API spec. WebGPU is a specification published by the GPU for the Web Community Group. It aims to allow web code access to GPU functions in a safe and reliable manner. It does this by mimicking the Vulkan API, and translating that down to whatever API the host hardware is using (ie. DirectX, Metal, Vulkan).

Wgpu is still in development, so some of this doc is subject to change.

Why Rust?

Wgpu actually has C bindings to allow you to write C/C++ code with it, as well as use other languages that interface with C. That being said, wgpu is written in Rust, and it has some convenient Rust bindings that don't have to jump through any hoops. On top of that, I've been enjoying writing in Rust.

You should be fairly familiar with Rust before using this tutorial as I won't go into much detail on Rust syntax. If you're not super comfortable with Rust you can review the Rust tutorial. You should also be familiar with Cargo.

I'm using this project to learn wgpu myself, so I might miss some important details, or explain things badly. I'm always open to constructive feedback.

Contribution and Support

  • I accept pull requests (GitHub repo) for fixing issues with this tutorial such as typos, incorrect information, and other inconsistencies.
  • Due to wgpu's rapidly changing api, I'm not accepting any new pull requests for showcase demos.
  • If you want to support me directly, check out my patreon!

Translations

Special thanks to these patrons!

  • David Laban
  • Lennart
  • Ian Gowen
  • Aron Granberg
  • Bernard Llanos
  • Jan Šipr
  • Zeh Fernando
  • Youngsuk Kim
  • オリトイツキ
  • Andrea Postal
  • Julius Liu
  • Feng Liang
  • Mattia Samiolo
  • Joris Willems
  • Jani Turkia
  • papyDoctor
  • Filip

learn-wgpu's People

Contributors

aevyrie avatar alexheretic avatar arifd avatar artvinn avatar blatko1 avatar catcode79 avatar cedric-h avatar dependabot[bot] avatar dis-da-moe avatar doodlewind avatar erwanvivien avatar fkloiber avatar hwoodiwiss avatar jinleili avatar kanerogers avatar linusu avatar mckahz avatar narcha avatar nxsy avatar pudnax avatar rhysd avatar rmsc avatar rofrol avatar rokonio avatar seakrueger avatar sotrh avatar supersamus avatar tonalidadehidrica avatar turbomack avatar yutannihilation avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

learn-wgpu's Issues

Inconsistent `light.vert` output type and `light.frag` input type

First, thanks so much for your tutorial. I'm learning so much going through it.

Just want to let you know that there's an error in your light shader programs under the lighting intermediate tutorial.
https://sotrh.github.io/learn-wgpu/intermediate/tutorial10-lighting/#seeing-the-light

// light.vert
layout(location=0) out vec4 v_color;


// light.frag
layout(location=0) in vec3 v_color;

The vertex shader outputs a vec4, but the fragment shader expects an input of vec3. This causes creating the light pipeline to fail. It took me a while to figure this out until after I enabled logging.

Code examples sometimes don't match the text

This tutorial is really great! I've learned a ton and I'm falling in love with wgpu. Some notes though:

For instance, the pipeline tutorial's code does shaders differently than the tutorial. The tutorial is using glsl-to-spirv = "0.1" but the code example is using shaderc = "0.6".

The texturing code has a similar issue. In the tutorial, the from_bytes function takes two parameters. In the code, it has an additional "label" parameter.

Not a big deal or anything, just thought I'd let you know!

Missing parameter in texture constructor

https://sotrh.github.io/learn-wgpu/beginner/tutorial5-textures/#cleaning-things-up

-
let (diffuse_texture, cmd_buffer) = texture::Texture::from_bytes(&device, diffuse_bytes).unwrap();

pub fn from_image(device: &Device, img: &image::DynamicImage) -> Result<(Self, CommandBuffer), failure::Error> {

label: Some("texture"),


+
let (diffuse_texture, cmd_buffer) = texture::Texture::from_bytes(&device, diffuse_bytes, "happy-tree.png").unwrap();

pub fn from_image(device: &Device, img: &image::DynamicImage, label: Option<&str>) -> Result<(Self, CommandBuffer), failure::Error> {

label: label,

imgui wgpu tutorial

we could have a showcase for imgui-rs which describes how the crates involved relate

in short:

wgpu = "^0.6.0"
winit = "^0.22.2" # opening windows and handling input
futures = "^0.3.5" # executing async functions using blocking executor
imgui = "^0.5.0"
imgui-winit-support = "^0.5.0" # connection of input (keys) to imgui
imgui-wgpu = "^0.11.0" # imgui backend for drawing using wgpu

something like this https://github.com/Yatekii/imgui-wgpu-rs/blob/master/examples/hello_world.rs
there is also imgui plotting now btw. https://github.com/4bb4/implot-rs

maybe also something how a wgpu backend for imgui works, it apparently gets lists of commands and then draws them
https://github.com/Yatekii/imgui-wgpu-rs/blob/fce781b5aaa9de40c98a1e5aa187d587c84b9c4b/src/lib.rs#L482-L497

As imgui is pretty popular for game UI I think this would be helpful and I found it to be really convenient to use so far :)

Textures example in Instancing tutorial fails with segmentation fault

Hi, I got segmentation fault with an example using textures in Instancing tutorial. Does this only happen on me? I'm using Wayland and GNOME3 on Manjaro Linux.

Note that my window manager behaves a bit strangely in that it resizes windows after it is created. I suspect the resize is the cause, so I want to know whether this is reproducible on other environments or a very rare issue.

What I did was adding this section to code/beginner/tutorial7-instancing/Cargo.toml

[[example]]
name = "tutorial7-texture"
path = "examples/texture_instances.rs"

and running the command below:

$ cargo run --example tutorial7-texture
warning: unused variable: `instance_buffer_size`
   --> code/beginner/tutorial7-instancing/examples/texture_instances.rs:393:13
    |
393 |         let instance_buffer_size = instance_data.len() * std::mem::size_of::<cgmath::Matrix4<f32>>();
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider prefixing with an underscore: `_instance_buffer_size`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: field is never read: `instances`
   --> code/beginner/tutorial7-instancing/examples/texture_instances.rs:278:5
    |
278 |     instances: Vec<Instance>,
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(dead_code)]` on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.09s
     Running `target/debug/examples/tutorial7-texture`
Segmentation fault (core dumped)

program always rebuilds

The build.rs files have println!("cargo:rerun-if-changed=src/*"); which causes cargo to always rerun because the .spv files are emitted into src/ and thus it always reruns.

As a quick fix I hardcoded it to only rerun for the vertex and fragment shader but maybe a better solution could be used like emitting into a different dir or using a more sophisticated glob which I'm not sure if cargo supports that.

error as the image is drawn before the resize event

I have found that, in my evironment, a request_redraw() executed from MainEventsCleared is done before resizing, causing an Outdated error while getting the SwapChainTexture.

The code that produce this error is avalaible here: https://github.com/marius851000/my-learning-wgpu/tree/e3fc300baf1a2b46dccc61cfd6668c935b02a30c , but this also happen with the binary exemple for part 2 for begginer here.

While I don't know how to change the redraw priority, I solved this issue by making the render function faillable, and printing error in log.

Example of what can be found in the log of my version (linking upper)

main event cleared
redrawn requested
render
error redrawing: Timeout getting texture

Caused by:
    The underlying surface has changed, and therefore the swap chain must be updated
resize
main event cleared
redrawn requested
render

It seem this error doesn't happen when I comment window.request_redraw(); in MainEventsCleared, however.

Present mode field purpose

Hi.
First of all, thanks for your tutorial. It's well written and explains really well :).
I'm opening this issue because of the explanation about present_mode field purpose in https://github.com/sotrh/learn-wgpu/blob/master/docs/beginner/tutorial2-swapchain/

There's no documentation on present_mode as of writing, but my guess is that it defines the rate at which you can acquire images from the swap_chain.

You say this, but afaik it's not exactly the purpose of the present_mode field, its purpose is to specify how much image the swapchain can hold and swap between at the same time:
https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Swap_chain#page_Presentation-mode
I don't know how to phrase this, so i won't open a PR, sorry 😅

Hope it helps atleast 🙂

Textures and bind groups

Some minor things I found that may be incorrect.

In Textures and bind groups.

let diffuse_rgba = diffuse_image.as_rgba8().unwrap();

If I'm not mistakes diffuse_rgba -> rgba?

let buffer = device.create_buffer_with_data(
    &rgba, 
    wgpu::BufferUsage::COPY_SRC,
);

It seems like the size variable in the same section is a mistake.

let size = wgpu::Extent3d {
    width: dimensions.0,
    height: dimensions.1,
    depth: 1,
};

This would redefine let size = window.inner_size();.

By the way thank you for the amazing work.
Will pop in a PR for this when I've run through the tut.

Getting this error when compiling tutorial1

I am getting this error when I run the first tutorial.

Andrews-MBP:tutorial1-window andrew$ cargo run
    Updating crates.io index
    Updating crates.io index
error: no matching package named `jpeg` found
location searched: registry `https://github.com/rust-lang/crates.io-index`
required by package `image v0.23.7`
    ... which is depended on by `tutorial7-instancing v0.1.0 (/Users/andrewcarre/code/rust/learn-wgpu/code/beginner/tutorial7-instancing)`

Any ideas?

Example code in part "The Swapchain" is not working

Hi, thanks for the cool tutorial.

While trying to follow along the tutorial, I found myself cargo-running the implementation of a basic render function, that I was almost sure would work because it was mostly copy-pasted from the tutorial.

When launching and killing the app, it made my PC freeze for a good 10 seconds for seemingly no reason.

Then after re-reading 10 times I found this quote :

The last lines of the code tell wgpu to finish the command buffer, and to submit it to the gpu's render queue.

Looking at the sample in question I noticed that .. it's actually never done.

The error comes from a missing self.queue.submit call AFAICT : we're only calling encoder.finish() and not using its result. That resulted in a crash on my machine, and I'm pretty sure that this particular sample wouldn't compile anyway. There's a ]) that has nothing to do here.

I'm submitting a PR to fix this :)
Cheers!

Cleanup | Nov 2020

Some things I need to work on

  • Come up with a method to handle swap chain Outdated errors, and discuss the other possible errors in the main tutorial. #121
  • Use mint for all the Vertex/ModelVertex structs so we can use bytemuck derive #109
  • Switch to using vertex buffers for instancing #116
  • Fix issues with build.rs #119
  • Fix any issues with the texturing tutorial #120
  • Finish compute example and put it in showcase

Stretch goals

  • imgui showcase #110

OS X: wgpu::Device::create_render_pipeline -> Result::unwrap() on an Err value: Other

Many of the code examples run fine on my OS X machine, for example this one works just great:

cargo run --manifest-path code/beginner/tutorial9-models/Cargo.toml 

However, several of the examples have an unwrap() failure like this:

RUST_BACKTRACE=1 cargo run --manifest-path code/intermediate/tutorial11-normals/Cargo.toml 
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/tutorial11-normals`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Other', /Users/alex/.cargo/registry/src/github.com-1ecc6299db9ec823/wgpu-core-0.5.4/src/device/mod.rs:1797:17
stack backtrace:
   0: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
   1: core::fmt::write
   2: std::io::Write::write_fmt
   3: std::panicking::default_hook::{{closure}}
   4: std::panicking::default_hook
   5: std::panicking::rust_panic_with_hook
   6: rust_begin_unwind
   7: core::panicking::panic_fmt
   8: core::result::unwrap_failed
   9: core::result::Result<T,E>::unwrap
  10: wgpu_core::device::<impl wgpu_core::hub::Global<G>>::device_create_render_pipeline
  11: wgpu_device_create_render_pipeline
  12: wgpu::Device::create_render_pipeline
  13: tutorial11_normals::create_render_pipeline
  14: tutorial11_normals::State::new::{{closure}}
  15: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
  16: futures_executor::local_pool::block_on::{{closure}}
  17: futures_executor::local_pool::run_executor::{{closure}}
  18: std::thread::local::LocalKey<T>::try_with
  19: std::thread::local::LocalKey<T>::with
  20: futures_executor::local_pool::run_executor
  21: futures_executor::local_pool::block_on
  22: tutorial11_normals::main
  23: std::rt::lang_start::{{closure}}
  24: std::rt::lang_start_internal
  25: std::rt::lang_start
  26: main
 let pipeline = unsafe {                                                                                                                                                                       
                device                                                                                                                                                                                    
                    .raw                                                                                                                                                                                  
                    .create_graphics_pipeline(&pipeline_desc, None)   // <-- here                                                                                                                                    
                    .unwrap()                                                                                                                                                                             
            };  

System: OS X 10.15.5, Intel Iris Plus Graphics 655

Resize panic crashes in later tutorials

Hi and thanks for the great tutorials! I noticed that the tutorials for 9, 10, and 11 all crash when resizing the window. It looks like the issue is that in the resize function the depth texture is being created with the old size value because it's happening before the sc_desc variable is updated with the new sizes. I was able to fix it by moving the depth texture creation to after the new height and width are set.

Specifically, this is where I made the change. Thanks again for making these available.

collab with https://github.com/rust-tutorials/learn-wgpu ?

Hi, I'm the maintainer of the rust-tutorials github org. I had a contributor who was starting on a wgpu tutorial, but they had some personal issues and essentially won't be able to continue the work.

Luckily, I was pointed to your wgpu tutorial here!

I'd love to know how we might work together. I could just have the rust-tutorials/learn-wgpu readme link to your repo, or if you want I can make you a maintainer of that repo and you can move your stuff in and merge the two projects, or however you feel is best.

Possible mistake in Blinn-Phong shading implementation

Hi. I just finished the light tutorial, and Blinn-Phong shading doesn't seem to work right.

So v_position, which is later used in the fragment shader to determine the direction to the camera, is calculated in the vertex shader like this:

    // Get the position relative to the view for the lighting calc
    v_position = gl_Position.xyz / gl_Position.w;

I'm not sure what the division by .w component does, but as I understand, v_position shouldn't be projected to screen coordinates as gl_Position is. I separated view and projection matrices, passed them separately in the uniform, and applied only view matrix to v_position likes this:

layout(set=0, binding=0) uniform Uniform {
    mat4 u_view;
    mat4 u_proj;
};

void main() {
    // ...
    vec4 view_position = u_view * vec4(a_position, 1.0);
    v_position = view_position.xyz / view_position.w;
    gl_Position = u_proj * view_position;
}

And after that it seems to work correctly. Does this make sense?

And btw, thank you very much for great tutorials and my ticket to graphics world with Rust!

Code in Swapchain tutorial panics

The code described in the SwapChain Tutorial panics with the following output:

thread 'main' panicked at 'Failed to focus input context: XError { description: "BadDrawable (invalid Pixmap or Window parameter)", error_code: 9, request_code: 149, minor_code: 4 }', src/libcore/result.rs:1165:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

Running with backtrace gives the following output:

thread 'main' panicked at 'Failed to focus input context: XError { description: "BadDrawable (invalid Pixmap or Window parameter)", error_code: 9, request_code: 149, minor_code: 4 }', src/libcore/result.rs:1165:5
stack backtrace:
   0:     0x5634fb192674 - backtrace::backtrace::libunwind::trace::hda41dbcdfba36aa0
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/libunwind.rs:88
   1:     0x5634fb192674 - backtrace::backtrace::trace_unsynchronized::h1a8d6e1f8cb3f5d4
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/mod.rs:66
   2:     0x5634fb192674 - std::sys_common::backtrace::_print_fmt::h610c4127487e10da
                               at src/libstd/sys_common/backtrace.rs:76
   3:     0x5634fb192674 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h0722dc552e01bd1d
                               at src/libstd/sys_common/backtrace.rs:60
   4:     0x5634fb1b429c - core::fmt::write::h01edf6dd68a42c9c
                               at src/libcore/fmt/mod.rs:1030
   5:     0x5634fb18fb77 - std::io::Write::write_fmt::hf15985f193f03c04
                               at src/libstd/io/mod.rs:1412
   6:     0x5634fb194b85 - std::sys_common::backtrace::_print::hd8d5d08a1795e743
                               at src/libstd/sys_common/backtrace.rs:64
   7:     0x5634fb194b85 - std::sys_common::backtrace::print::hf89a79e3921a2366
                               at src/libstd/sys_common/backtrace.rs:49
   8:     0x5634fb194b85 - std::panicking::default_hook::{{closure}}::h3a8f42beb3bb8ae3
                               at src/libstd/panicking.rs:196
   9:     0x5634fb194876 - std::panicking::default_hook::h8f803b0bc31a5c37
                               at src/libstd/panicking.rs:210
  10:     0x5634fb195285 - std::panicking::rust_panic_with_hook::h825f041245da8739
                               at src/libstd/panicking.rs:473
  11:     0x5634fb194e22 - std::panicking::continue_panic_fmt::hbe0378e33481e81b
                               at src/libstd/panicking.rs:380
  12:     0x5634fb194d16 - rust_begin_unwind
                               at src/libstd/panicking.rs:307
  13:     0x5634fb1b069a - core::panicking::panic_fmt::h527855ce0bc891f6
                               at src/libcore/panicking.rs:85
  14:     0x5634fb1b0797 - core::result::unwrap_failed::ha8b77e6004f0ba38
                               at src/libcore/result.rs:1165
  15:     0x5634fab0c981 - core::result::Result<T,E>::expect::ha3dc71e3c3df67a5
                               at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libcore/result.rs:960
  16:     0x5634fab1ca05 - winit::platform_impl::platform::x11::event_processor::EventProcessor<T>::process_event::h99f30c7b91bd4e01
                               at /home/kunal/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.20.0/src/platform_impl/linux/x11/event_processor.rs:868
  17:     0x5634fab2a9f5 - winit::platform_impl::platform::x11::EventLoop<T>::drain_events::ha2600fbdf631ab40
                               at /home/kunal/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.20.0/src/platform_impl/linux/x11/mod.rs:402
  18:     0x5634fab29500 - winit::platform_impl::platform::x11::EventLoop<T>::run_return::h09d5b07aee8bc6fe
                               at /home/kunal/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.20.0/src/platform_impl/linux/x11/mod.rs:260
  19:     0x5634fab2ae0b - winit::platform_impl::platform::x11::EventLoop<T>::run::h3a8df3fe1aebdcb2
                               at /home/kunal/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.20.0/src/platform_impl/linux/x11/mod.rs:386
  20:     0x5634fab2d57e - winit::platform_impl::platform::EventLoop<T>::run::h22021ac5f0e88e76
                               at /home/kunal/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.20.0/src/platform_impl/linux/mod.rs:644
  21:     0x5634faaf72c4 - winit::event_loop::EventLoop<T>::run::he611cc003761aeb0
                               at /home/kunal/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.20.0/src/event_loop.rs:148
  22:     0x5634faaffd97 - try_wgpu::main::hf5dd9c0cb7449a73
                               at src/main.rs:12
  23:     0x5634fab34ec0 - std::rt::lang_start::{{closure}}::h9e5098d20c41fd21
                               at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/rt.rs:64
  24:     0x5634fb194cb3 - std::rt::lang_start_internal::{{closure}}::ha04574f12d97cbe2
                               at src/libstd/rt.rs:49
  25:     0x5634fb194cb3 - std::panicking::try::do_call::h7c2a8488f72db90c
                               at src/libstd/panicking.rs:292
  26:     0x5634fb19898a - __rust_maybe_catch_panic
                               at src/libpanic_unwind/lib.rs:80
  27:     0x5634fb19577d - std::panicking::try::hc3a9b5da4250385d
                               at src/libstd/panicking.rs:271
  28:     0x5634fb19577d - std::panic::catch_unwind::hf27600bf8c37809a
                               at src/libstd/panic.rs:394
  29:     0x5634fb19577d - std::rt::lang_start_internal::h409d4f2fe51133b0
                               at src/libstd/rt.rs:48
  30:     0x5634fab34e99 - std::rt::lang_start::haf1cb75fea9702a9
                               at /rustc/4560ea788cb760f0a34127156c78e2552949f734/src/libstd/rt.rs:64
  31:     0x5634fab0045a - main
  32:     0x7f1645cf2b6b - __libc_start_main
  33:     0x5634faabb19a - _start
  34:                0x0 - <unknown>

I am running it on Ubuntu 19.04

Tutorial 6: some problems with the camera

I had some problems with the camera navigation on tutorial 6:

  1. If you move the camera too close, the camera co-ords "glitch out" and go very positive negative (looks like some kind of overflow/ floating point error).
  2. If you rotate the camera, it slowly spins out from the target, because it's not really rotating. It's moving a small delta along the tangent of the circle, made by the radius of the target-to-eye vector.

This is some example code which fixes that:

    fn update_camera(&self, camera: &mut Camera) {
        use cgmath::InnerSpace;
        let forward = camera.target - camera.eye;
        let forward_norm = forward.normalize();
        let forward_mag = forward.magnitude();

        // Additional condition to if to eye exceeding distance to target. Fixes error #1.
        if self.is_forward_pressed && forward_mag > self.speed {
            camera.eye += forward_norm * self.speed;
        }
        if self.is_backward_pressed {
            camera.eye -= forward_norm * self.speed;
        }

        let right = forward_norm.cross(camera.up);

        // Redo radius calc in case the up/ down is pressed.
        let forward = camera.target - camera.eye;
        let forward_mag = forward.magnitude();

        if self.is_right_pressed {
            // Rescale the distance between the target and eye so that it doesn't change.
            // The eye therefore still lies on the circle made by the target and eye.
            camera.eye = camera.target - (forward + right * self.speed).normalize() * forward_mag;
        }
        if self.is_left_pressed {
            camera.eye = camera.target - (forward - right * self.speed).normalize() * forward_mag;
        }
    }

The fix for the rotation is not the best. A proper rotation matrix would be better, but this may be better for a tutorial.

Ps. Thanks for this repo. I've always found it hard to get into graphics programming and this is the first tutorial I've managed to get a grasp of :) .

Use bytemuck derives instead of unsafe impls

In the vertex buffer tutorial, bytemuck is introduced. bytemuck now has a derive feature that enables deriving the traits used in the tutorial. The derive validates that bytemuck's preconditions are met, which can be easy to mess up.

The Vertex would change to this:

#[repr(C)]
#[derive(Copy, Clone, Debug, Pod, Zezroable)]
struct Vertex {
    position: [f32; 3],
    color: [f32; 3],
}

I tried putting together a PR to make this switch. It was straightforward for this type, but other uses of bytemuck use types from crates like cgmath which do not implement the bytemuck traits. Some people stick with the plain unsafe trait impls for that reason.

I am a little bit paranoid about the ABI of math library types, so I generally use raw types or a crate I built specifically for safe uniform definitions.

Summer Cleaning

I'm creating this issue to document some of the changes and thoughts I'd like to make to the tutorial. Currently there are some issues that make development rather cumbersome.

1. Performance

This is probably the biggest issue. The tutorials take quite some time to load up, and also tend to be stuttery. I need to do some research into what's causing the issues. Looking at the current wgpu examples shows that my winit event loop could be improved.

Stuttering also effects getting screenshots. Currently my computer will freeze for a couple seconds whenever I take a screenshot, or change windows. This makes creating new tutorials, and updating old ones difficult.

2. The Camera

Currently the camera can only rotate around the scene, and zoom in and out. This works, but it can make it hard to focus in on a particular part of the scene. I'm debating between a Minecraft creative mode style camera were you can move in the x/z freely, and move up and down with the shift/ctrl keys; and a regular flying free cam.

3. Difficulty creating new pipelines

Not sure how best to improve this. The difficulty is bind groups are kind of a pain to manage. I need to do some research into different ways of managing bind groups.

4. Slowing down development

The WepGPU spec is currently in flux. I haven't been super motivated to create a bunch of new tutorials, as that just means I have to update them when the API changes. On top of that, I'm running out of wgpu specific things to talk about. There are plenty of tutorials on GLSL, and a variety of graphics techniques, and once you know how to use pipelines, buffers, textures etc. adapting these techniques is not too hard. Because of this I'm going to be slowing down the rate that I make tutorials.

That being said, there are a couple things I'd like to do before I go into maintenance mode.

  1. Some sort of compute pipeline tutorial. I haven't touched command pipelines at all. I'm thinking some combination of terrain generation, and post processing. I'm also interested in doing a PBR guide.
  2. Text, there are libraries that exist to do this: wgpu_glyph, wgpu_imgui, others I'm unaware of. I want to implement this myself though as I haven't covered alpha blending yet.

Question: difference between DynamicImage::as_rgba8() and DynamicImage::to_rgba()

(Sorry, this might not be a wgpu-related issue. Please feel free to close this if this is not the topic that should be covered in this guide.)

I was stuck on tutorial 9 for a while to find out the difference between my code and the correct answer. In the end, I found I needed to change img.as_rgba8().unwrap() to img.to_rgba(), but I still don't get how they are different. I'd really appreciate if the guide has some explanation on this. (If this is not worth explaining, can the all tutorials use to_rgba() to avoid confusion?)

Until tutorial 8:

let rgba = img.as_rgba8().unwrap();

After tutorial 9:

tutorial1-window on OS X

If you're on MacOS, you can specify Vulkan (MoltenVK) as your desired backend instead of Metal by removing the wgpu = "0.5.0" and adding the following.

[dependencies.wgpu]
version = "0.5.0"
features = ["vulkan"]

I would also add something about what is the benefit or reason for adding features = ["vulkan"] .
My understanding is that without specifying vulkan, the pipeline on OS X is like:

wgpu-rs -> wgpu-core -> metal

adding features = ["vulkan"] then the pipeline on OS X is like this:

wgpu-rs -> wgpu-core -> vulkan -> moltenvk -> metal

But what would the tradoffs or pros/cons be of doing that? Confusing issues, there is actually an OS X SDK listed at https://vulkan.lunarg.com/sdk/home . I have a feeling there might be a lot of outdated information about Vulkan and OS X, on the web, but I am just learning. Let me know what you think about that, and I would be happy to submit a PR for this.

PS, also thanks so much for this awesome tutorial. Enjoying digging into it.

Unnecessary block_on() calls in swapchain chapter

I'm currently following the chapter on setting up the swapchain and noticed some inconsistencies in how the State struct is implemented from how it's referenced in the main event loop.

Namely the update, render, and resize functions are not asynchronous, so you shouldn't need to include block_on() in event loop. Was the intent for them to be asynchronous, or should the event loop code in the tutorial be updated?

Buffers tutoral on Linux: no data is send to vertex shader

I was following the tutorial until I got to Buffers and Indices in Beginner.
When I got to the point where we implemented a vertex buffer (without a index buffer) I did not get the expected result.
All I get is an empty screen with just containing the clear color.

The previous chapter The Pipeline did work fine and produced a triangle as expected.
By going back to using the hard coded position data in the vertex shader, but still using the color from the vertex shader, I got a black triangle.
This tells me that for some reason a_position and a_color are both set to all zeros.

This is not just a bug in my code. I get the same result running code from this repo. (at dfd9609) Running tutorial3-pipeline works fine. However both tutorial4-buffer and tutorial5-textures won't work. I get window with just a blue background.
What is strange is that tutorial6-uniforms works fine again.

display: X11
os: Linux 5.4.50
gpu: Nvidia GTX 670

Normal maps are using incorrect format.

You can't use Rgba8UnormSrgb for normal maps as you'll get very incorrect results. I would suggest using Rgba8Unorm instead.

Also you should unpack the normals in the shader as well like:

normal = normal * 2.0 - 1.0;

Inaccuracy Regarding Enabling Vulkan on Windows

https://sotrh.github.io/learn-wgpu/beginner/tutorial1-window/#what-crates-are-we-using says that to enable vulkan on windows you need to enable the vulkan feature of wgpu. That feature only has an effect on mac, where it enables the vulkan backend for use with MoltenVK.

To enable/disable various backends, the BackendBit flag needs to be changed when requesting an adapter. PRIMARY is Vulkan | DX12 | Metal | WEBGPU, SECONDARY is DX11 | OPENGL (though the opengl backend is disabled entirely, and DX11 barely works).

If vulkan is available, vulkan will always be preferred by wgpu as it almost always performs better than the DX12 backend and has less compatibility issues.

The order of backend preference:
Windows: Vulkan, DX12, DX11
Mac: Vulkan(if enabled), Metal
Linux: Vulkan

Thanks for this awesome resource to point people to!

GLSL usage

Would it make sense to state somewhere in the tutorial when shaders are first introduced that the GLSL used is with the Vulkan extension? Not mentioning it might confuse readers familiar with OpenGL but not with Vulkan, if they for example try to look up more information on some of the topics from khronos.org OpenGL docs.

Reworking Instancing Tutorial

The current instancing tutorial covers a lot of different instancing methods without explaining much about how they work. On top of that it doesn't go into why instancing is important/useful. I'm planning to implement two (2) changes.

  1. The instancing tutorial will be simplified to introduce the concept of instancing and explain it's importance.
  2. I'll create a new showcase project to show off the various instancing methods, and go into a little more detail about there pros and cons. (I'll probably need a lot of help fact checking on those ;) )

Cannot access diffuse_texture.view while working through the beginner tutorial on textures

https://sotrh.github.io/learn-wgpu/beginner/tutorial5-textures/#loading-an-image-from-a-file

Basically just following along but I'm getting an error while working through the subsections. I just noticed it when I was at the shader section, but in the tutorial steps the variable diffuse_texture seems to be used for two separate things.

No matter if diffuse_texture is a Texture or DynamicImage I can't seem to access the view or sampler fields.

Not sure if I'm just missing something obvious here, but wanted to bring it up!

Links in latest news section are broken

The news.md file has some broken links on github.io. They are using links such as /showcase/imgui-demo, which online are getting interpreted as sotrh.github.io/showcase/imgui-demo instead of sotrh.github.io/learn-wgpu/showcase/imgui-demo

Incorrect use of `cargo:rerun-if-changed`

Hey!

Just a heads up that the rerun-if-changed across many of the examples will not work.

use std::path::PathBuf;

fn main () {
    let path = PathBuf::from("src/foo.vert.glsl");
    
    // Incorrect
    println!("cargo:rerun-if-changed={:?}", path);
    
    // Correct
    println!("cargo:rerun-if-changed={}", path.to_str().unwrap());

    // Also correct
    println!("cargo:rerun-if-changed={}", path.display());
}

Output:

cargo:rerun-if-changed="src/foo.vert.glsl"
cargo:rerun-if-changed=src/foo.vert.glsl
cargo:rerun-if-changed=src/foo.vert.glsl

Note that the debug representation includes quotation marks, which cargo does not respect.

Black Textures on Model at end of Model Loading Chapter

I've gotten to the end of the model loading chapter and although everything runs and compiles nicely, the actual textures are not loading, but rather are just plain black.

Screen Shot 2020-03-30 at 9 18 49 PM

I can't tell if its an issue with the tutorial or my implementation since there seems to be a file loading error for tutorial9.

Outdated contents in Markdown website, compared to Github repo/directory

In the "The Swapchain" section of the tutorial, the State::new() block calls let size = window.inner_size(); twice. I don't think both calls are needed. Was the call intended to go at the beginning or end of the code block?

https://github.com/sotrh/learn-wgpu/blob/master/docs/beginner/tutorial2-swapchain/README.md#statenew


Actually I've noticed multiple differences between the .md code and your repo. State::new() writes the adapter field into Self = State, which doesn't exist. This field was removed in the repo at https://github.com/sotrh/learn-wgpu/blob/master/code/beginner/tutorial2-swapchain/src/main.rs .


Also the code doesn't compile on wgpu 0.6.


https://github.com/sotrh/learn-wgpu/blob/master/code/beginner/tutorial6-uniforms/src/main.rs#L466
self.queue.write_buffer(&self.uniform_buffer, 0, &bytemuck::cast_slice(&[self.uniforms]));
I suspect the & in &bytemuck::cast_slice is redundant and gets silently discarded.

Ordering of statements in render method

I was working through this tutorial when got stuck on the "Textures and bind groups" section. When trying to run the code at the "Results" section I hit this error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: IncompatibleBindGroup. The current render pipeline has a layout which is incompatible with a currently set bind group. They first differ at entry index 0.', /.../wgpu-core-0.5.5/src/command/render.rs:1150:21

After looking through your full examples on github I found the discrepancy was that in my render function I had this ordering of method calls:

render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_vertex_buffer(0, &self.vertex_buffer, 0, 0);
render_pass.set_index_buffer(&self.index_buffer, 0, 0);
render_pass.draw_indexed(0..self.num_indices, 0, 0..1);
render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]);  // Note that this call was last.

and your example code has this ordering:

render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]);  // Note that this is the second call.
render_pass.set_vertex_buffer(0, &self.vertex_buffer, 0, 0);
render_pass.set_index_buffer(&self.index_buffer, 0, 0);
render_pass.draw_indexed(0..self.num_indices, 0, 0..1);

Switching the ordering fixed the error and I don't understand why that's the case. I think it would be helpful to others if this was highlighted and/or explained at the end of the "The BindGroup" section.

renderpass setup

The order of these statements is important. The pipeline needs to be set first, then the bind groups, vertex buffers, and index buffer, finally the draw call. If you don't do this, you'll likely get a crash.

I asked about that on matrix and was told:

that's not actually true, you can bind them in any order as long as they're all bound by the time you draw
the one exception is push constants which have to be bound after the pipeline, but that's a bug

Add import to window::Window in main.rs

This is a minor issue

I'm on /beginner/tutorial2-swapchain/#first-some-house-keeping. While following along with the tutorial, I realized that I needed to import window::Window along with window::WindowBuilder.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.